/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *******************************************************************************/ package org.apache.ofbiz.service; import java.io.IOException; import java.io.Serializable; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.xml.parsers.ParserConfigurationException; import org.apache.ofbiz.base.config.GenericConfigException; import org.apache.ofbiz.base.config.ResourceHandler; import org.apache.ofbiz.base.metrics.MetricsFactory; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.GeneralException; import org.apache.ofbiz.base.util.UtilTimer; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.base.util.UtilXml; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.GenericEntityException; import org.apache.ofbiz.entity.model.ModelEntity; import org.apache.ofbiz.entity.model.ModelField; import org.apache.ofbiz.entity.model.ModelFieldType; import org.apache.ofbiz.service.ModelParam.ModelParamValidator; import org.apache.ofbiz.service.group.GroupModel; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * Generic Service - Service Definition Reader */ @SuppressWarnings("serial") public class ModelServiceReader implements Serializable { public static final String module = ModelServiceReader.class.getName(); /** is either from a URL or from a ResourceLoader (through the ResourceHandler) */ protected boolean isFromURL; protected URL readerURL = null; protected ResourceHandler handler = null; protected Delegator delegator = null; public static Map<String, ModelService> getModelServiceMap(URL readerURL, Delegator delegator) { if (readerURL == null) { Debug.logError("Cannot add reader with a null reader URL", module); return null; } ModelServiceReader reader = new ModelServiceReader(true, readerURL, null, delegator); return reader.getModelServices(); } public static Map<String, ModelService> getModelServiceMap(ResourceHandler handler, Delegator delegator) { ModelServiceReader reader = new ModelServiceReader(false, null, handler, delegator); return reader.getModelServices(); } private ModelServiceReader(boolean isFromURL, URL readerURL, ResourceHandler handler, Delegator delegator) { this.isFromURL = isFromURL; this.readerURL = readerURL; this.handler = handler; this.delegator = delegator; } private Map<String, ModelService> getModelServices() { UtilTimer utilTimer = new UtilTimer(); Document document; if (this.isFromURL) { // utilTimer.timerString("Before getDocument in file " + readerURL); document = getDocument(readerURL); if (document == null) { return null; } } else { // utilTimer.timerString("Before getDocument in " + handler); try { document = handler.getDocument(); } catch (GenericConfigException e) { Debug.logError(e, "Error getting XML document from resource", module); return null; } } Map<String, ModelService> modelServices = new HashMap<String, ModelService>(); if (this.isFromURL) {// utilTimer.timerString("Before getDocumentElement in file " + readerURL); } else {// utilTimer.timerString("Before getDocumentElement in " + handler); } Element docElement = document.getDocumentElement(); if (docElement == null) { return null; } docElement.normalize(); String resourceLocation = handler.getLocation(); try { resourceLocation = handler.getURL().toExternalForm(); } catch (GenericConfigException e) { Debug.logError(e, "Could not get resource URL", module); } int i = 0; Node curChild = docElement.getFirstChild(); if (curChild != null) { if (this.isFromURL) { utilTimer.timerString("Before start of service loop in file " + readerURL); } else { utilTimer.timerString("Before start of service loop in " + handler); } do { if (curChild.getNodeType() == Node.ELEMENT_NODE && "service".equals(curChild.getNodeName())) { i++; Element curServiceElement = (Element) curChild; String serviceName = UtilXml.checkEmpty(curServiceElement.getAttribute("name")); // check to see if service with same name has already been read if (modelServices.containsKey(serviceName)) { Debug.logWarning("Service " + serviceName + " is defined more than once, " + "most recent will over-write previous definition(s)", module); } // utilTimer.timerString(" After serviceName -- " + i + " --"); ModelService service = createModelService(curServiceElement, resourceLocation); // utilTimer.timerString(" After createModelService -- " + i + " --"); if (service != null) { modelServices.put(serviceName, service); // utilTimer.timerString(" After modelServices.put -- " + i + " --"); /* int reqIn = service.getParameterNames(ModelService.IN_PARAM, false).size(); int optIn = service.getParameterNames(ModelService.IN_PARAM, true).size() - reqIn; int reqOut = service.getParameterNames(ModelService.OUT_PARAM, false).size(); int optOut = service.getParameterNames(ModelService.OUT_PARAM, true).size() - reqOut; if (Debug.verboseOn()) { String msg = "-- getModelService: # " + i + " Loaded service: " + serviceName + " (IN) " + reqIn + "/" + optIn + " (OUT) " + reqOut + "/" + optOut; Debug.logVerbose(msg, module); } */ } else { Debug.logWarning( "-- -- SERVICE ERROR:getModelService: Could not create service for serviceName: " + serviceName, module); } } } while ((curChild = curChild.getNextSibling()) != null); } else { Debug.logWarning("No child nodes found.", module); } if (this.isFromURL) { utilTimer.timerString("Finished file " + readerURL + " - Total Services: " + i + " FINISHED"); Debug.logInfo("Loaded [" + i + "] Services from " + readerURL, module); } else { utilTimer.timerString("Finished document in " + handler + " - Total Services: " + i + " FINISHED"); if (Debug.infoOn()) { Debug.logInfo("Loaded [" + i + "] Services from " + resourceLocation, module); } } return modelServices; } private ModelService createModelService(Element serviceElement, String resourceLocation) { ModelService service = new ModelService(); service.name = UtilXml.checkEmpty(serviceElement.getAttribute("name")).intern(); service.definitionLocation = resourceLocation; service.engineName = UtilXml.checkEmpty(serviceElement.getAttribute("engine")).intern(); service.location = UtilXml.checkEmpty(serviceElement.getAttribute("location")).intern(); service.invoke = UtilXml.checkEmpty(serviceElement.getAttribute("invoke")).intern(); service.semaphore = UtilXml.checkEmpty(serviceElement.getAttribute("semaphore")).intern(); service.defaultEntityName = UtilXml.checkEmpty(serviceElement.getAttribute("default-entity-name")).intern(); service.fromLoader = isFromURL ? readerURL.toExternalForm() : handler.getLoaderName(); // these default to true; if anything but true, make false service.auth = "true".equalsIgnoreCase(serviceElement.getAttribute("auth")); service.export = "true".equalsIgnoreCase(serviceElement.getAttribute("export")); service.debug = "true".equalsIgnoreCase(serviceElement.getAttribute("debug")); // these defaults to false; if anything but false, make it true service.validate = !"false".equalsIgnoreCase(serviceElement.getAttribute("validate")); service.useTransaction = !"false".equalsIgnoreCase(serviceElement.getAttribute("use-transaction")); service.requireNewTransaction = !"false".equalsIgnoreCase(serviceElement.getAttribute("require-new-transaction")); if (service.requireNewTransaction && !service.useTransaction) { // requireNewTransaction implies that a transaction is used service.useTransaction = true; Debug.logWarning("In service definition [" + service.name + "] the value use-transaction has been changed from false to true as required when require-new-transaction is set to true", module); } service.hideResultInLog = !"false".equalsIgnoreCase(serviceElement.getAttribute("hideResultInLog")); // set the semaphore sleep/wait times String semaphoreWaitStr = UtilXml.checkEmpty(serviceElement.getAttribute("semaphore-wait-seconds")); int semaphoreWait = 300; if (UtilValidate.isNotEmpty(semaphoreWaitStr)) { try { semaphoreWait = Integer.parseInt(semaphoreWaitStr); } catch (NumberFormatException e) { Debug.logWarning(e, "Setting semaphore-wait to 5 minutes (default)", module); semaphoreWait = 300; } } service.semaphoreWait = semaphoreWait; String semaphoreSleepStr = UtilXml.checkEmpty(serviceElement.getAttribute("semaphore-sleep")); int semaphoreSleep = 500; if (UtilValidate.isNotEmpty(semaphoreSleepStr)) { try { semaphoreSleep = Integer.parseInt(semaphoreSleepStr); } catch (NumberFormatException e) { Debug.logWarning(e, "Setting semaphore-sleep to 1/2 second (default)", module); semaphoreSleep = 500; } } service.semaphoreSleep = semaphoreSleep; // set the max retry field String maxRetryStr = UtilXml.checkEmpty(serviceElement.getAttribute("max-retry")); int maxRetry = -1; if (UtilValidate.isNotEmpty(maxRetryStr)) { try { maxRetry = Integer.parseInt(maxRetryStr); } catch (NumberFormatException e) { Debug.logWarning(e, "Setting maxRetry to -1 (default)", module); maxRetry = -1; } } service.maxRetry = maxRetry; // get the timeout and convert to int String timeoutStr = UtilXml.checkEmpty(serviceElement.getAttribute("transaction-timeout"), serviceElement.getAttribute("transaction-timout")); int timeout = 0; if (UtilValidate.isNotEmpty(timeoutStr)) { try { timeout = Integer.parseInt(timeoutStr); } catch (NumberFormatException e) { Debug.logWarning(e, "Setting timeout to 0 (default)", module); timeout = 0; } } service.transactionTimeout = timeout; service.description = getCDATADef(serviceElement, "description"); service.nameSpace = getCDATADef(serviceElement, "namespace"); // construct the context service.contextInfo = new HashMap<String, ModelParam>(); this.createNotification(serviceElement, service); this.createPermission(serviceElement, service); this.createPermGroups(serviceElement, service); this.createGroupDefs(serviceElement, service); this.createImplDefs(serviceElement, service); this.createAutoAttrDefs(serviceElement, service); this.createAttrDefs(serviceElement, service); this.createOverrideDefs(serviceElement, service); // Get metrics. Element metricsElement = UtilXml.firstChildElement(serviceElement, "metric"); if (metricsElement != null) { service.metrics = MetricsFactory.getInstance(metricsElement); } return service; } private String getCDATADef(Element baseElement, String tagName) { String value = ""; NodeList nl = baseElement.getElementsByTagName(tagName); // if there are more then one decriptions we will use only the first one if (nl.getLength() > 0) { Node n = nl.item(0); NodeList childNodes = n.getChildNodes(); if (childNodes.getLength() > 0) { Node cdata = childNodes.item(0); value = UtilXml.checkEmpty(cdata.getNodeValue()); } } return value; } private void createNotification(Element baseElement, ModelService model) { List<? extends Element> n = UtilXml.childElementList(baseElement, "notification"); // default notification groups ModelNotification nSuccess = new ModelNotification(); nSuccess.notificationEvent = "success"; nSuccess.notificationGroupName = "default.success." + model.fromLoader; model.notifications.add(nSuccess); ModelNotification nFail = new ModelNotification(); nFail.notificationEvent = "fail"; nFail.notificationGroupName = "default.fail." + model.fromLoader; model.notifications.add(nFail); ModelNotification nError = new ModelNotification(); nError.notificationEvent = "error"; nError.notificationGroupName = "default.error." + model.fromLoader; model.notifications.add(nError); if (n != null) { for (Element e: n) { ModelNotification notify = new ModelNotification(); notify.notificationEvent = e.getAttribute("event"); notify.notificationGroupName = e.getAttribute("group"); model.notifications.add(notify); } } } private void createPermission(Element baseElement, ModelService model) { Element e = UtilXml.firstChildElement(baseElement, "permission-service"); if (e != null) { model.permissionServiceName = e.getAttribute("service-name"); model.permissionMainAction = e.getAttribute("main-action"); model.permissionResourceDesc = e.getAttribute("resource-description"); model.auth = true; // auth is always required when permissions are set } } private void createPermGroups(Element baseElement, ModelService model) { for (Element element: UtilXml.childElementList(baseElement, "required-permissions")) { ModelPermGroup group = new ModelPermGroup(); group.joinType = element.getAttribute("join-type"); createGroupPermissions(element, group, model); model.permissionGroups.add(group); } } private void createGroupPermissions(Element baseElement, ModelPermGroup group, ModelService service) { // create the simple permissions for (Element element: UtilXml.childElementList(baseElement, "check-permission")) { ModelPermission perm = new ModelPermission(); perm.nameOrRole = element.getAttribute("permission").intern(); perm.action = element.getAttribute("action").intern(); if (UtilValidate.isNotEmpty(perm.action)) { perm.permissionType = ModelPermission.ENTITY_PERMISSION; } else { perm.permissionType = ModelPermission.PERMISSION; } perm.serviceModel = service; group.permissions.add(perm); } // create the role member permissions for (Element element: UtilXml.childElementList(baseElement, "check-role-member")) { ModelPermission perm = new ModelPermission(); perm.permissionType = ModelPermission.ROLE_MEMBER; perm.nameOrRole = element.getAttribute("role-type").intern(); perm.serviceModel = service; group.permissions.add(perm); } // Create the permissions based on permission services for (Element element : UtilXml.childElementList(baseElement, "permission-service")) { ModelPermission perm = new ModelPermission(); if (baseElement != null) { perm.permissionType = ModelPermission.PERMISSION_SERVICE; perm.permissionServiceName = element.getAttribute("service-name"); perm.action = element.getAttribute("main-action"); perm.permissionResourceDesc = element.getAttribute("resource-description"); perm.auth = true; // auth is always required when permissions are set perm.serviceModel = service; group.permissions.add(perm); } } } private void createGroupDefs(Element baseElement, ModelService service) { List<? extends Element> group = UtilXml.childElementList(baseElement, "group"); if (UtilValidate.isNotEmpty(group)) { Element groupElement = group.get(0); groupElement.setAttribute("name", "_" + service.name + ".group"); service.internalGroup = new GroupModel(groupElement); service.invoke = service.internalGroup.getGroupName(); if (Debug.verboseOn()) Debug.logVerbose("Created INTERNAL GROUP model [" + service.internalGroup + "]", module); } } private void createImplDefs(Element baseElement, ModelService service) { for (Element implement: UtilXml.childElementList(baseElement, "implements")) { String serviceName = UtilXml.checkEmpty(implement.getAttribute("service")).intern(); boolean optional = UtilXml.checkBoolean(implement.getAttribute("optional"), false); if (serviceName.length() > 0) service.implServices.add(new ModelServiceIface(serviceName, optional)); //service.implServices.add(serviceName); } } private void createAutoAttrDefs(Element baseElement, ModelService service) { for (Element element: UtilXml.childElementList(baseElement, "auto-attributes")) { createAutoAttrDef(element, service); } } private void createAutoAttrDef(Element autoElement, ModelService service) { // get the entity name; first from the auto-attributes then from the service def String entityName = UtilXml.checkEmpty(autoElement.getAttribute("entity-name")); if (UtilValidate.isEmpty(entityName)) { entityName = service.defaultEntityName; if (UtilValidate.isEmpty(entityName)) { Debug.logWarning("Auto-Attribute does not specify an entity-name; not default-entity on service definition", module); } } // get the include type 'pk|nonpk|all' String includeType = UtilXml.checkEmpty(autoElement.getAttribute("include")); boolean includePk = "pk".equals(includeType) || "all".equals(includeType); boolean includeNonPk = "nonpk".equals(includeType) || "all".equals(includeType); if (delegator == null) { Debug.logWarning("Cannot use auto-attribute fields with a null delegator", module); } if (delegator != null && entityName != null) { Map<String, ModelParam> modelParamMap = new LinkedHashMap<String, ModelParam>(); try { ModelEntity entity = delegator.getModelEntity(entityName); if (entity == null) { throw new GeneralException("Could not find entity with name [" + entityName + "]"); } Iterator<ModelField> fieldsIter = entity.getFieldsIterator(); if (fieldsIter != null) { while (fieldsIter.hasNext()) { ModelField field = fieldsIter.next(); if ((!field.getIsAutoCreatedInternal()) && ((field.getIsPk() && includePk) || (!field.getIsPk() && includeNonPk))) { ModelFieldType fieldType = delegator.getEntityFieldType(entity, field.getType()); if (fieldType == null) { throw new GeneralException("Null field type from delegator for entity [" + entityName + "]"); } ModelParam param = new ModelParam(); param.entityName = entityName; param.fieldName = field.getName(); param.name = field.getName(); param.type = fieldType.getJavaType(); // this is a special case where we use something different in the service layer than we do in the entity/data layer if ("java.sql.Blob".equals(param.type)) { param.type = "java.nio.ByteBuffer"; } param.mode = UtilXml.checkEmpty(autoElement.getAttribute("mode")).intern(); param.optional = "true".equalsIgnoreCase(autoElement.getAttribute("optional")); // default to true param.formDisplay = !"false".equalsIgnoreCase(autoElement.getAttribute("form-display")); // default to false param.allowHtml = UtilXml.checkEmpty(autoElement.getAttribute("allow-html"), "none").intern(); // default to none modelParamMap.put(field.getName(), param); } } // get the excludes list; and remove those from the map List<? extends Element> excludes = UtilXml.childElementList(autoElement, "exclude"); if (excludes != null) { for (Element exclude: excludes) { modelParamMap.remove(UtilXml.checkEmpty(exclude.getAttribute("field-name"))); } } // now add in all the remaining params for (ModelParam thisParam: modelParamMap.values()) { //Debug.logInfo("Adding Param to " + service.name + ": " + thisParam.name + " [" + thisParam.mode + "] " + thisParam.type + " (" + thisParam.optional + ")", module); service.addParam(thisParam); } } } catch (GenericEntityException e) { Debug.logError(e, "Problem loading auto-attributes [" + entityName + "] for " + service.name, module); } catch (GeneralException e) { Debug.logError(e, "Cannot load auto-attributes : " + e.getMessage() + " for " + service.name, module); } } } private void createAttrDefs(Element baseElement, ModelService service) { // Add in the defined attributes (override the above defaults if specified) for (Element attribute: UtilXml.childElementList(baseElement, "attribute")) { ModelParam param = new ModelParam(); param.name = UtilXml.checkEmpty(attribute.getAttribute("name")).intern(); param.description = getCDATADef(attribute, "description"); param.type = UtilXml.checkEmpty(attribute.getAttribute("type")).intern(); param.mode = UtilXml.checkEmpty(attribute.getAttribute("mode")).intern(); param.entityName = UtilXml.checkEmpty(attribute.getAttribute("entity-name")).intern(); param.fieldName = UtilXml.checkEmpty(attribute.getAttribute("field-name")).intern(); param.requestAttributeName = UtilXml.checkEmpty(attribute.getAttribute("request-attribute-name")).intern(); param.sessionAttributeName = UtilXml.checkEmpty(attribute.getAttribute("session-attribute-name")).intern(); param.stringMapPrefix = UtilXml.checkEmpty(attribute.getAttribute("string-map-prefix")).intern(); param.stringListSuffix = UtilXml.checkEmpty(attribute.getAttribute("string-list-suffix")).intern(); param.formLabel = attribute.hasAttribute("form-label")?attribute.getAttribute("form-label").intern():null; param.optional = "true".equalsIgnoreCase(attribute.getAttribute("optional")); // default to true param.formDisplay = !"false".equalsIgnoreCase(attribute.getAttribute("form-display")); // default to false param.allowHtml = UtilXml.checkEmpty(attribute.getAttribute("allow-html"), "none").intern(); // default to none // default value String defValue = attribute.getAttribute("default-value"); if (UtilValidate.isNotEmpty(defValue)) { if (Debug.verboseOn()) Debug.logVerbose("Got a default-value [" + defValue + "] for service attribute [" + service.name + "." + param.name + "]", module); param.setDefaultValue(defValue.intern()); } // set the entity name to the default if not specified if (param.entityName.length() == 0) { param.entityName = service.defaultEntityName; } // set the field-name to the name if entity name is specified but no field-name if (param.fieldName.length() == 0 && param.entityName.length() > 0) { param.fieldName = param.name; } // set the validators this.addValidators(attribute, param); service.addParam(param); } // Add the default optional parameters ModelParam def; // responseMessage def = new ModelParam(); def.name = ModelService.RESPONSE_MESSAGE; def.type = "String"; def.mode = "OUT"; def.optional = true; def.internal = true; service.addParam(def); // errorMessage def = new ModelParam(); def.name = ModelService.ERROR_MESSAGE; def.type = "String"; def.mode = "OUT"; def.optional = true; def.internal = true; service.addParam(def); // errorMessageList def = new ModelParam(); def.name = ModelService.ERROR_MESSAGE_LIST; def.type = "java.util.List"; def.mode = "OUT"; def.optional = true; def.internal = true; service.addParam(def); // successMessage def = new ModelParam(); def.name = ModelService.SUCCESS_MESSAGE; def.type = "String"; def.mode = "OUT"; def.optional = true; def.internal = true; service.addParam(def); // successMessageList def = new ModelParam(); def.name = ModelService.SUCCESS_MESSAGE_LIST; def.type = "java.util.List"; def.mode = "OUT"; def.optional = true; def.internal = true; service.addParam(def); // userLogin def = new ModelParam(); def.name = "userLogin"; def.type = "org.apache.ofbiz.entity.GenericValue"; def.mode = "INOUT"; def.optional = true; def.internal = true; service.addParam(def); // login.username def = new ModelParam(); def.name = "login.username"; def.type = "String"; def.mode = "IN"; def.optional = true; def.internal = true; service.addParam(def); // login.password def = new ModelParam(); def.name = "login.password"; def.type = "String"; def.mode = "IN"; def.optional = true; def.internal = true; service.addParam(def); // Locale def = new ModelParam(); def.name = "locale"; def.type = "java.util.Locale"; def.mode = "INOUT"; def.optional = true; def.internal = true; service.addParam(def); // timeZone def = new ModelParam(); def.name = "timeZone"; def.type = "java.util.TimeZone"; def.mode = "INOUT"; def.optional = true; def.internal = true; service.addParam(def); } private void createOverrideDefs(Element baseElement, ModelService service) { for (Element overrideElement: UtilXml.childElementList(baseElement, "override")) { String name = UtilXml.checkEmpty(overrideElement.getAttribute("name")); ModelParam param = service.getParam(name); boolean directToParams = true; if (param == null) { if (!service.inheritedParameters && (service.implServices.size() > 0 || "group".equals(service.engineName))) { // create a temp def to place in the ModelService // this will get read when we read implemented services directToParams = false; param = new ModelParam(); param.name = name; } else { Debug.logWarning("No parameter found for override parameter named: " + name + " in service " + service.name, module); } } if (param != null) { // set only modified values if (UtilValidate.isNotEmpty(overrideElement.getAttribute("type"))) { param.type = UtilXml.checkEmpty(overrideElement.getAttribute("type")).intern(); } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("mode"))) { param.mode = UtilXml.checkEmpty(overrideElement.getAttribute("mode")).intern(); } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("entity-name"))) { param.entityName = UtilXml.checkEmpty(overrideElement.getAttribute("entity-name")).intern(); } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("field-name"))) { param.fieldName = UtilXml.checkEmpty(overrideElement.getAttribute("field-name")).intern(); } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("form-label"))) { param.formLabel = UtilXml.checkEmpty(overrideElement.getAttribute("form-label")).intern(); } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("optional"))) { param.optional = "true".equalsIgnoreCase(overrideElement.getAttribute("optional")); // default to true param.overrideOptional = true; } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("form-display"))) { param.formDisplay = !"false".equalsIgnoreCase(overrideElement.getAttribute("form-display")); // default to false param.overrideFormDisplay = true; } if (UtilValidate.isNotEmpty(overrideElement.getAttribute("allow-html"))) { param.allowHtml = UtilXml.checkEmpty(overrideElement.getAttribute("allow-html")).intern(); } // default value String defValue = overrideElement.getAttribute("default-value"); if (UtilValidate.isNotEmpty(defValue)) { param.setDefaultValue(defValue); } // override validators this.addValidators(overrideElement, param); if (directToParams) { service.addParam(param); } else { service.overrideParameters.add(param); } } } } private void addValidators(Element attribute, ModelParam param) { List<? extends Element> validateElements = UtilXml.childElementList(attribute, "type-validate"); if (UtilValidate.isNotEmpty(validateElements)) { // always clear out old ones; never append param.validators = new LinkedList<ModelParamValidator>(); Element validate = validateElements.get(0); String methodName = validate.getAttribute("method").intern(); String className = validate.getAttribute("class").intern(); Element fail = UtilXml.firstChildElement(validate, "fail-message"); if (fail != null) { String message = fail.getAttribute("message").intern(); param.addValidator(className, methodName, message); } else { fail = UtilXml.firstChildElement(validate, "fail-property"); if (fail != null) { String resource = fail.getAttribute("resource").intern(); String property = fail.getAttribute("property").intern(); param.addValidator(className, methodName, resource, property); } } } } private Document getDocument(URL url) { if (url == null) return null; Document document = null; try { document = UtilXml.readXmlDocument(url, true, true); } catch (SAXException sxe) { // Error generated during parsing) Exception x = sxe; if (sxe.getException() != null) x = sxe.getException(); x.printStackTrace(); } catch (ParserConfigurationException pce) { // Parser with specified options can't be built pce.printStackTrace(); } catch (IOException ioe) { ioe.printStackTrace(); } return document; } }