001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023 024package dk.netarkivet.harvester.webinterface; 025 026import java.sql.SQLException; 027import java.util.ArrayList; 028import java.util.List; 029 030import javax.servlet.ServletRequest; 031import javax.servlet.jsp.PageContext; 032 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import com.antiaction.raptor.dao.AttributeBase; 037import com.antiaction.raptor.dao.AttributeTypeBase; 038 039import dk.netarkivet.common.exceptions.ArgumentNotValid; 040import dk.netarkivet.common.exceptions.ForwardedToErrorPage; 041import dk.netarkivet.common.utils.I18n; 042import dk.netarkivet.common.webinterface.HTMLUtils; 043import dk.netarkivet.harvester.datamodel.Domain; 044import dk.netarkivet.harvester.datamodel.DomainConfiguration; 045import dk.netarkivet.harvester.datamodel.DomainDAO; 046import dk.netarkivet.harvester.datamodel.Password; 047import dk.netarkivet.harvester.datamodel.SeedList; 048import dk.netarkivet.harvester.datamodel.TemplateDAO; 049import dk.netarkivet.harvester.datamodel.eav.EAV; 050import dk.netarkivet.harvester.datamodel.eav.EAV.AttributeAndType; 051 052/** 053 * Utility class containing methods for processing a GUI-request to update the details of a domain-configuration. 054 */ 055 056public class DomainConfigurationDefinition { 057 058 private static final Logger log = LoggerFactory.getLogger(DomainConfigurationDefinition.class); 059 060 /** 061 * Extracts all required parameters from the request, checks for any inconsistencies, and passes the requisite data 062 * to the updateDomain method for processing. The specified domain configuration is then updated and the result 063 * stored in the database. 064 * <p> 065 * update: This method does nothing if update is not set 066 * <p> 067 * name: must be the name of a known domain 068 * <p> 069 * default: the defaultconfig is set to this value. Must be non-null and a known configuration of this domain. 070 * <p> 071 * edition: The edition number the config was originally read as, if any. 072 * <p> 073 * (configName, order_xml, maxRate, maxObjects, maxBytes, urlListList[], passwordList): group specifying a 074 * configuration to update or add. If configName is non null then order_xml must be a known order-xml and 075 * urlListList must contain only known seedlists, (and at least one such). load, maxObjects, maxBytes, edition must 076 * be parsable as integers if present. passwordList is currently ignored. 077 * 078 * @param context The context of this request 079 * @param i18n I18n information 080 * @throws ForwardedToErrorPage if a user error has caused forwarding to the error page, in which case processing 081 * should abort. 082 */ 083 public static void processRequest(PageContext context, I18n i18n) { 084 ArgumentNotValid.checkNotNull(context, "PageContext context"); 085 ArgumentNotValid.checkNotNull(i18n, "I18n i18n"); 086 087 ServletRequest request = context.getRequest(); 088 String update = request.getParameter(Constants.UPDATE_PARAM); 089 if (update == null) { 090 return; // no need to continue 091 } 092 093 HTMLUtils.forwardOnEmptyParameter(context, Constants.DOMAIN_PARAM, Constants.CONFIG_NAME_PARAM, 094 Constants.ORDER_XML_NAME_PARAM, Constants.SEEDLIST_LIST_PARAM); 095 String name = request.getParameter(Constants.DOMAIN_PARAM).trim(); 096 String configName = request.getParameter(Constants.CONFIG_NAME_PARAM).trim(); 097 String configOldName = request.getParameter(Constants.CONFIG_OLDNAME_PARAM); 098 if (configOldName != null) { 099 configOldName = configOldName.trim(); 100 } else { 101 configOldName = ""; 102 } 103 String order_xml = request.getParameter(Constants.ORDER_XML_NAME_PARAM).trim(); 104 String[] urlListList = request.getParameterValues(Constants.SEEDLIST_LIST_PARAM); 105 106 if (!DomainDAO.getInstance().exists(name)) { 107 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;unknown.domain.0", name); 108 throw new ForwardedToErrorPage("Domain " + name + " does not exist"); 109 } 110 111 Domain domain = DomainDAO.getInstance().read(name); 112 113 long edition = HTMLUtils.parseOptionalLong(context, Constants.EDITION_PARAM, -1L); 114 115 // check the edition number before updating 116 if (domain.getEdition() != edition) { 117 HTMLUtils.forwardWithRawErrorMessage( 118 context, 119 i18n, 120 "errormsg;domain.definition.changed.0.retry.1", 121 "<br/><a href=\"Definitions-edit-domain.jsp?" + Constants.DOMAIN_PARAM + "=" 122 + HTMLUtils.escapeHtmlValues(HTMLUtils.encode(name)) + "\">", "</a>"); 123 throw new ForwardedToErrorPage("Domain '" + name + "' has changed"); 124 } 125 126 if (!TemplateDAO.getInstance().exists(order_xml)) { 127 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;harvest.template.0.does.not.exist", order_xml); 128 throw new ForwardedToErrorPage("Unknown template " + order_xml); 129 } 130 131 for (String s : urlListList) { 132 s = s.trim(); 133 if (s.length() == 0 || !domain.hasSeedList(s)) { 134 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;unknown.seed.list.0", s); 135 throw new ForwardedToErrorPage("Unknown seed list " + s); 136 } 137 } 138 139 int load = HTMLUtils.parseOptionalLong(context, Constants.MAX_RATE_PARAM, 140 (long) dk.netarkivet.harvester.datamodel.Constants.DEFAULT_MAX_REQUEST_RATE).intValue(); 141 long maxObjects = HTMLUtils.parseOptionalLong(context, Constants.MAX_OBJECTS_PARAM, 142 dk.netarkivet.harvester.datamodel.Constants.DEFAULT_MAX_OBJECTS); 143 long maxBytes = HTMLUtils.parseOptionalLong(context, Constants.MAX_BYTES_PARAM, 144 dk.netarkivet.harvester.datamodel.Constants.DEFAULT_MAX_BYTES); 145 146 String comments = request.getParameter(Constants.COMMENTS_PARAM); 147 148 DomainConfiguration domainConf = null; 149 150 if (!configOldName.isEmpty() && !configOldName.equals(configName)){ 151 // Are we allowed to rename to the new name? or does it already exist? 152 if (domain.hasConfiguration(configName)) { 153 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;configuration.exists.0", configName); 154 throw new ForwardedToErrorPage("Configuration " + configName + " already exist"); 155 } else { 156 domainConf = domain.getConfiguration(configOldName); 157 String defaultConfigName = DomainDAO.getInstance().getDefaultDomainConfigurationName(domain.getName()); 158 if (defaultConfigName.equals(configName)){ 159 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;cannot.rename.defaultconfiguration.0", configOldName); 160 throw new ForwardedToErrorPage("Configuration " + configOldName + " cannot be renamed. It is the defaultconfiguration"); 161 } else { 162 List<SeedList> seedlistList = new ArrayList<SeedList>(); 163 for (String seedlistName : urlListList) { 164 seedlistList.add(domain.getSeedList(seedlistName)); 165 } 166 domainConf.setName(configName); 167 domainConf.setOrderXmlName(order_xml); 168 domainConf.setMaxObjects(maxObjects); 169 domainConf.setMaxBytes(maxBytes); 170 domainConf.setMaxRequestRate(load); 171 domainConf.setSeedLists(domain, seedlistList); 172 if (comments != null) { 173 domainConf.setComments(comments); 174 } 175 DomainDAO.getInstance().renameAndUpdateConfig(domain, domainConf, configOldName); 176 } 177 } 178 } else { 179 domainConf = updateDomainConfig(domain, configName, order_xml, load, maxObjects, maxBytes, urlListList, comments); 180 } 181 182 // EAV 183 try { 184 long entity_id = domainConf.getID(); 185 log.info("Saving attributes for domain config id {} and name {}", entity_id, domainConf.getName()); 186 EAV eav = EAV.getInstance(); 187 List<AttributeAndType> attributeTypes = eav.getAttributesAndTypes(EAV.DOMAIN_TREE_ID, (int)entity_id); 188 AttributeAndType attributeAndType; 189 AttributeTypeBase attributeType; 190 AttributeBase attribute; 191 for (int i=0; i<attributeTypes.size(); ++i) { 192 attributeAndType = attributeTypes.get(i); 193 attributeType = attributeAndType.attributeType; 194 attribute = attributeAndType.attribute; 195 if (attribute == null) { 196 attribute = attributeType.instanceOf(); 197 attribute.entity_id = (int)entity_id; 198 } 199 switch (attributeType.viewtype) { 200 case 1: 201 long longValue = HTMLUtils.parseOptionalLong(context, attributeType.name, (long)attributeType.def_int); 202 log.info("Setting attribute {} to value {}", attributeType.name, longValue); 203 attribute.setInteger((int)longValue); 204 break; 205 case 5: 206 case 6: 207 String paramValue = context.getRequest().getParameter(attributeType.name); 208 int intVal = 0; 209 if (paramValue != null && !"0".equals(paramValue)) { 210 log.debug("Set intVal = 1 for attribute {} when receiving paramValue={}", attributeType.name, paramValue); 211 intVal = 1; 212 } 213 attribute.setInteger(intVal); 214 break; 215 } 216 eav.saveAttribute(attribute); 217 } 218 } catch (SQLException e) { 219 throw new RuntimeException("Unable to store EAV data!", e); 220 } 221 } 222 223 /** 224 * Given the parsed values, update or create a configuration in the domain. 225 * 226 * @param domain The domain 227 * @param configName Name of config - if this exists we update, otherwise we create a new. 228 * @param orderXml Order-template name 229 * @param load Request rate 230 * @param maxObjects Max objects 231 * @param maxBytes Max bytes 232 * @param urlListList List of url list names 233 * @param comments Comments, or null for none. 234 */ 235 private static DomainConfiguration updateDomainConfig(Domain domain, String configName, String orderXml, int load, long maxObjects, 236 long maxBytes, String[] urlListList, String comments) { 237 // Update/create new configuration 238 List<SeedList> seedlistList = new ArrayList<SeedList>(); 239 for (String seedlistName : urlListList) { 240 seedlistList.add(domain.getSeedList(seedlistName)); 241 } 242 DomainConfiguration domainConf; 243 if (domain.hasConfiguration(configName)) { 244 domainConf = domain.getConfiguration(configName); 245 } else { // new DomainConfiguration 246 domainConf = new DomainConfiguration(configName, domain, seedlistList, new ArrayList<Password>()); 247 domain.addConfiguration(domainConf); 248 } 249 domainConf.setOrderXmlName(orderXml); 250 domainConf.setMaxObjects(maxObjects); 251 domainConf.setMaxBytes(maxBytes); 252 domainConf.setMaxRequestRate(load); 253 domainConf.setSeedLists(domain, seedlistList); 254 if (comments != null) { 255 domainConf.setComments(comments); 256 } 257 DomainDAO.getInstance().update(domain); 258 return domainConf; 259 } 260}