1 25 package org.ofbiz.service; 26 27 import java.io.IOException ; 28 import java.io.Serializable ; 29 import java.net.URL ; 30 import java.util.Collection ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import javax.xml.parsers.ParserConfigurationException ; 36 37 import javolution.util.FastList; 38 import javolution.util.FastMap; 39 40 import org.ofbiz.base.config.GenericConfigException; 41 import org.ofbiz.base.config.ResourceHandler; 42 import org.ofbiz.base.util.Debug; 43 import org.ofbiz.base.util.GeneralException; 44 import org.ofbiz.base.util.UtilTimer; 45 import org.ofbiz.base.util.UtilValidate; 46 import org.ofbiz.base.util.UtilXml; 47 import org.ofbiz.base.util.cache.UtilCache; 48 import org.ofbiz.entity.GenericDelegator; 49 import org.ofbiz.entity.GenericEntityException; 50 import org.ofbiz.entity.model.ModelEntity; 51 import org.ofbiz.entity.model.ModelField; 52 import org.ofbiz.entity.model.ModelFieldType; 53 54 import org.apache.commons.collections.map.LinkedMap; 55 import org.w3c.dom.Document ; 56 import org.w3c.dom.Element ; 57 import org.w3c.dom.Node ; 58 import org.w3c.dom.NodeList ; 59 import org.xml.sax.SAXException ; 60 61 69 70 public class ModelServiceReader implements Serializable { 71 72 public static final String module = ModelServiceReader.class.getName(); 73 74 protected static UtilCache readersUrl = new UtilCache("service.ModelServiceReader.ByURL", 0, 0); 75 protected static UtilCache readersLoader = new UtilCache("service.ModelServiceReader.ByResourceLoader", 0, 0); 76 77 78 protected boolean isFromURL; 79 protected URL readerURL = null; 80 protected ResourceHandler handler = null; 81 protected Map modelServices = null; 82 protected DispatchContext dctx = null; 83 84 public static ModelServiceReader getModelServiceReader(URL readerURL, DispatchContext dctx) { 85 ModelServiceReader reader = null; 86 87 reader = (ModelServiceReader) readersUrl.get(readerURL); 89 if (reader == null) { synchronized (ModelServiceReader.class) { 91 reader = (ModelServiceReader) readersUrl.get(readerURL); 93 if (reader == null) { 94 reader = new ModelServiceReader(readerURL, dctx); 96 readersUrl.put(readerURL, reader); 97 } 98 } 99 } 100 return reader; 101 } 102 103 public static ModelServiceReader getModelServiceReader(ResourceHandler handler, DispatchContext dctx) { 104 ModelServiceReader reader = null; 105 106 reader = (ModelServiceReader) readersLoader.get(handler); 107 if (reader == null) { synchronized (ModelServiceReader.class) { 109 reader = (ModelServiceReader) readersLoader.get(handler); 111 if (reader == null) { 112 reader = new ModelServiceReader(handler, dctx); 114 readersLoader.put(handler, reader); 115 } 116 } 117 } 118 return reader; 119 } 120 121 protected ModelServiceReader(URL readerURL, DispatchContext dctx) { 122 this.isFromURL = true; 123 this.readerURL = readerURL; 124 this.handler = null; 125 this.dctx = dctx; 126 getModelServices(); 128 } 129 130 protected ModelServiceReader(ResourceHandler handler, DispatchContext dctx) { 131 this.isFromURL = false; 132 this.readerURL = null; 133 this.handler = handler; 134 this.dctx = dctx; 135 getModelServices(); 137 } 138 139 public Map getModelServices() { 140 if (modelServices == null) { synchronized (ModelServiceReader.class) { 142 if (modelServices == null) { modelServices = FastMap.newInstance(); 145 146 UtilTimer utilTimer = new UtilTimer(); 147 148 Document document = null; 149 150 if (this.isFromURL) { 151 document = getDocument(readerURL); 153 154 if (document == null) { 155 modelServices = null; 156 return null; 157 } 158 } else { 159 try { 161 document = handler.getDocument(); 162 } catch (GenericConfigException e) { 163 Debug.logError(e, "Error getting XML document from resource", module); 164 return null; 165 } 166 } 167 168 if (this.isFromURL) { } else { } 171 172 Element docElement = document.getDocumentElement(); 173 if (docElement == null) { 174 modelServices = null; 175 return null; 176 } 177 178 docElement.normalize(); 179 180 int i = 0; 181 Node curChild = docElement.getFirstChild(); 182 if (curChild != null) { 183 if (this.isFromURL) { 184 utilTimer.timerString("Before start of service loop in file " + readerURL); 185 } else { 186 utilTimer.timerString("Before start of service loop in " + handler); 187 } ; 188 189 do { 190 if (curChild.getNodeType() == Node.ELEMENT_NODE && "service".equals(curChild.getNodeName())) { 191 i++; 192 Element curService = (Element ) curChild; 193 String serviceName = UtilXml.checkEmpty(curService.getAttribute("name")); 194 195 if (modelServices.containsKey(serviceName)) { 197 Debug.logWarning("WARNING: Service " + serviceName + " is defined more than once, " + 198 "most recent will over-write previous definition(s)", module); 199 } 200 201 ModelService service = createModelService(curService); 203 204 if (service != null) { 206 modelServices.put(serviceName, service); 207 221 } else { 222 Debug.logWarning( 223 "-- -- SERVICE ERROR:getModelService: Could not create service for serviceName: " + 224 serviceName, module); 225 } 226 227 } 228 } while ((curChild = curChild.getNextSibling()) != null); 229 } else { 230 Debug.logWarning("No child nodes found.", module); 231 } 232 if (this.isFromURL) { 233 utilTimer.timerString("Finished file " + readerURL + " - Total Services: " + i + " FINISHED"); 234 Debug.logImportant("Loaded " + i + " Service definitions from " + readerURL, module); 235 } else { 236 utilTimer.timerString("Finished document in " + handler + " - Total Services: " + i + " FINISHED"); 237 if (Debug.importantOn()) { 238 String resourceLocation = handler.getLocation(); 239 try { 240 resourceLocation = handler.getURL().toExternalForm(); 241 } catch (GenericConfigException e) { 242 Debug.logError(e, "Could not get resource URL", module); 243 } 244 Debug.logImportant("Loaded " + i + " Service definitions from " + resourceLocation, module); 245 } 246 } 247 } 248 } 249 } 250 return modelServices; 251 } 252 253 258 public ModelService getModelService(String serviceName) { 259 Map ec = getModelServices(); 260 261 if (ec != null) 262 return (ModelService) ec.get(serviceName); 263 else 264 return null; 265 } 266 267 271 public Iterator getServiceNamesIterator() { 272 Collection collection = getServiceNames(); 273 274 if (collection != null) { 275 return collection.iterator(); 276 } else { 277 return null; 278 } 279 } 280 281 285 public Collection getServiceNames() { 286 Map ec = getModelServices(); 287 288 return ec.keySet(); 289 } 290 291 protected ModelService createModelService(Element serviceElement) { 292 ModelService service = new ModelService(); 293 294 service.name = UtilXml.checkEmpty(serviceElement.getAttribute("name")); 295 service.engineName = UtilXml.checkEmpty(serviceElement.getAttribute("engine")); 296 service.location = UtilXml.checkEmpty(serviceElement.getAttribute("location")); 297 service.invoke = UtilXml.checkEmpty(serviceElement.getAttribute("invoke")); 298 service.defaultEntityName = UtilXml.checkEmpty(serviceElement.getAttribute("default-entity-name")); 299 300 service.auth = "true".equalsIgnoreCase(serviceElement.getAttribute("auth")); 302 service.export = "true".equalsIgnoreCase(serviceElement.getAttribute("export")); 303 service.debug = "true".equalsIgnoreCase(serviceElement.getAttribute("debug")); 304 305 service.validate = !"false".equalsIgnoreCase(serviceElement.getAttribute("validate")); 307 service.useTransaction = !"false".equalsIgnoreCase(serviceElement.getAttribute("use-transaction")); 308 service.requireNewTransaction = !"false".equalsIgnoreCase(serviceElement.getAttribute("require-new-transaction")); 309 310 String maxRetryStr = UtilXml.checkEmpty(serviceElement.getAttribute("max-retry")); 312 int maxRetry = -1; 313 if (!UtilValidate.isEmpty(maxRetryStr)) { 314 try { 315 maxRetry = Integer.parseInt(maxRetryStr); 316 } catch (NumberFormatException e) { 317 Debug.logWarning(e, "Setting maxRetry to -1 (default)", module); 318 maxRetry = -1; 319 } 320 } 321 service.maxRetry = maxRetry; 322 323 String timeoutStr = UtilXml.checkEmpty(serviceElement.getAttribute("transaction-timout")); 325 int timeout = 0; 326 if (!UtilValidate.isEmpty(timeoutStr)) { 327 try { 328 timeout = Integer.parseInt(timeoutStr); 329 } catch (NumberFormatException e) { 330 Debug.logWarning(e, "Setting timeout to 0 (default)", module); 331 timeout = 0; 332 } 333 } 334 service.transactionTimeout = timeout; 335 336 service.description = getCDATADef(serviceElement, "description"); 337 service.nameSpace = getCDATADef(serviceElement, "namespace"); 338 339 service.contextInfo = FastMap.newInstance(); 340 this.createPermGroups(serviceElement, service); 341 this.createImplDefs(serviceElement, service); 342 this.createAutoAttrDefs(serviceElement, service); 343 this.createAttrDefs(serviceElement, service); 344 this.createOverrideDefs(serviceElement, service); 345 346 return service; 347 } 348 349 protected String getCDATADef(Element baseElement, String tagName) { 350 String value = ""; 351 NodeList nl = baseElement.getElementsByTagName(tagName); 352 353 if (nl.getLength() > 0) { 355 Node n = nl.item(0); 356 NodeList childNodes = n.getChildNodes(); 357 358 if (childNodes.getLength() > 0) { 359 Node cdata = childNodes.item(0); 360 361 value = UtilXml.checkEmpty(cdata.getNodeValue()); 362 } 363 } 364 return value; 365 } 366 367 protected void createPermGroups(Element baseElement, ModelService model) { 368 List permGroups = UtilXml.childElementList(baseElement, "required-permissions"); 369 Iterator permIter = permGroups.iterator(); 370 371 while (permIter.hasNext()) { 372 Element element = (Element ) permIter.next(); 373 ModelPermGroup group = new ModelPermGroup(); 374 group.joinType = element.getAttribute("join-type"); 375 createPermissions(element, group, model); 376 model.permissionGroups.add(group); 377 } 378 } 379 380 protected void createPermissions(Element baseElement, ModelPermGroup group, ModelService service) { 381 List permElements = UtilXml.childElementList(baseElement, "check-permission"); 382 List rolePermElements = UtilXml.childElementList(baseElement, "check-role-member"); 383 384 Iterator si = permElements.iterator(); 386 while (si.hasNext()) { 387 Element element = (Element ) si.next(); 388 ModelPermission perm = new ModelPermission(); 389 perm.nameOrRole = element.getAttribute("permission"); 390 perm.action = element.getAttribute("action"); 391 if (perm.action != null && perm.action.length() > 0) { 392 perm.permissionType = ModelPermission.ENTITY_PERMISSION; 393 } else { 394 perm.permissionType = ModelPermission.PERMISSION; 395 } 396 perm.serviceModel = service; 397 group.permissions.add(perm); 398 } 399 400 Iterator ri = rolePermElements.iterator(); 402 while (ri.hasNext()) { 403 Element element = (Element ) ri.next(); 404 ModelPermission perm = new ModelPermission(); 405 perm.permissionType = ModelPermission.ROLE_MEMBER; 406 perm.nameOrRole = element.getAttribute("role-type"); 407 perm.serviceModel = service; 408 group.permissions.add(perm); 409 } 410 } 411 412 protected void createImplDefs(Element baseElement, ModelService service) { 413 List implElements = UtilXml.childElementList(baseElement, "implements"); 414 Iterator implIter = implElements.iterator(); 415 416 while (implIter.hasNext()) { 417 Element implement = (Element ) implIter.next(); 418 String serviceName = UtilXml.checkEmpty(implement.getAttribute("service")); 419 if (serviceName.length() > 0) 420 service.implServices.add(serviceName); 421 } 422 } 423 424 protected void createAutoAttrDefs(Element baseElement, ModelService service) { 425 List autoElement = UtilXml.childElementList(baseElement, "auto-attributes"); 426 Iterator autoIter = autoElement.iterator(); 427 428 while (autoIter.hasNext()) { 429 Element element = (Element ) autoIter.next(); 430 createAutoAttrDef(element, service); 431 } 432 } 433 434 protected void createAutoAttrDef(Element autoElement, ModelService service) { 435 String entityName = UtilXml.checkEmpty(autoElement.getAttribute("entity-name")); 437 if (entityName == null || entityName.length() == 0) { 438 entityName = service.defaultEntityName; 439 if (entityName == null || entityName.length() == 0) { 440 Debug.logWarning("Auto-Attribute does not specify an entity-name; not default-entity on service definition", module); 441 } 442 } 443 444 String includeType = UtilXml.checkEmpty(autoElement.getAttribute("include")); 446 boolean includePk = "pk".equals(includeType) || "all".equals(includeType); 447 boolean includeNonPk = "nonpk".equals(includeType) || "all".equals(includeType); 448 449 GenericDelegator delegator = dctx.getDelegator(); 451 if (delegator == null) { 452 Debug.logWarning("Cannot use auto-attribute fields with a null delegator", module); 453 } 454 455 if (delegator != null && entityName != null) { 456 Map modelParamMap = new LinkedMap(); 457 try { 458 ModelEntity entity = delegator.getModelEntity(entityName); 459 if (entity == null) { 460 throw new GeneralException("Could not find entity with name [" + entityName + "]"); 461 } 462 Iterator fieldsIter = entity.getFieldsIterator(); 463 if (fieldsIter != null) { 464 while (fieldsIter.hasNext()) { 465 ModelField field = (ModelField) fieldsIter.next(); 466 if ((!field.getIsAutoCreatedInternal()) && ((field.getIsPk() && includePk) || (!field.getIsPk() && includeNonPk))) { 467 ModelFieldType fieldType = delegator.getEntityFieldType(entity, field.getType()); 468 if (fieldType == null) { 469 throw new GeneralException("Null field type from delegator for entity [" + entityName + "]"); 470 } 471 ModelParam param = new ModelParam(); 472 param.entityName = entityName; 473 param.fieldName = field.getName(); 474 param.name = field.getName(); 475 param.type = fieldType.getJavaType(); 476 param.mode = UtilXml.checkEmpty(autoElement.getAttribute("mode")); 477 param.optional = "true".equalsIgnoreCase(autoElement.getAttribute("optional")); param.formDisplay = !"false".equalsIgnoreCase(autoElement.getAttribute("form-display")); modelParamMap.put(field.getName(), param); 480 } 481 } 482 483 List excludes = UtilXml.childElementList(autoElement, "exclude"); 485 if (excludes != null) { 486 Iterator excludesIter = excludes.iterator(); 487 while (excludesIter.hasNext()) { 488 Element exclude = (Element ) excludesIter.next(); 489 modelParamMap.remove(UtilXml.checkEmpty(exclude.getAttribute("field-name"))); 490 } 491 } 492 493 Set keySet = modelParamMap.keySet(); 495 Iterator setIter = keySet.iterator(); 496 while (setIter.hasNext()) { 497 ModelParam thisParam = (ModelParam) modelParamMap.get(setIter.next()); 498 service.addParam(thisParam); 500 } 501 } 502 } catch (GenericEntityException e) { 503 Debug.logError(e, "Problem loading auto-attributes [" + entityName + "] for " + service.name, module); 504 } catch (GeneralException e) { 505 Debug.logError(e, "Cannot load auto-attributes : " + e.getMessage() + " for " + service.name, module); 506 } 507 } 508 } 509 510 protected void createAttrDefs(Element baseElement, ModelService service) { 511 List paramElements = UtilXml.childElementList(baseElement, "attribute"); 513 Iterator paramIter = paramElements.iterator(); 514 515 while (paramIter.hasNext()) { 516 Element attribute = (Element ) paramIter.next(); 517 ModelParam param = new ModelParam(); 518 519 param.name = UtilXml.checkEmpty(attribute.getAttribute("name")); 520 param.type = UtilXml.checkEmpty(attribute.getAttribute("type")); 521 param.mode = UtilXml.checkEmpty(attribute.getAttribute("mode")); 522 param.entityName = UtilXml.checkEmpty(attribute.getAttribute("entity-name")); 523 param.fieldName = UtilXml.checkEmpty(attribute.getAttribute("field-name")); 524 param.stringMapPrefix = UtilXml.checkEmpty(attribute.getAttribute("string-map-prefix")); 525 param.stringListSuffix = UtilXml.checkEmpty(attribute.getAttribute("string-list-suffix")); 526 param.formLabel = attribute.hasAttribute("form-label")?attribute.getAttribute("form-label"):null; 527 param.optional = "true".equalsIgnoreCase(attribute.getAttribute("optional")); param.formDisplay = !"false".equalsIgnoreCase(attribute.getAttribute("form-display")); 530 if (param.entityName.length() == 0) { 532 param.entityName = service.defaultEntityName; 533 } 534 535 if (param.fieldName.length() == 0 && param.entityName.length() > 0) { 537 param.fieldName = param.name; 538 } 539 540 this.addValidators(attribute, param); 542 service.addParam(param); 543 } 544 545 ModelParam def = null; 547 548 def = new ModelParam(); 550 def.name = ModelService.RESPONSE_MESSAGE; 551 def.type = "String"; 552 def.mode = "OUT"; 553 def.optional = true; 554 def.internal = true; 555 service.addParam(def); 556 def = new ModelParam(); 558 def.name = ModelService.ERROR_MESSAGE; 559 def.type = "String"; 560 def.mode = "OUT"; 561 def.optional = true; 562 def.internal = true; 563 service.addParam(def); 564 def = new ModelParam(); 566 def.name = ModelService.ERROR_MESSAGE_LIST; 567 def.type = "java.util.List"; 568 def.mode = "OUT"; 569 def.optional = true; 570 def.internal = true; 571 service.addParam(def); 572 def = new ModelParam(); 574 def.name = ModelService.SUCCESS_MESSAGE; 575 def.type = "String"; 576 def.mode = "OUT"; 577 def.optional = true; 578 def.internal = true; 579 service.addParam(def); 580 def = new ModelParam(); 582 def.name = ModelService.SUCCESS_MESSAGE_LIST; 583 def.type = "java.util.List"; 584 def.mode = "OUT"; 585 def.optional = true; 586 def.internal = true; 587 service.addParam(def); 588 def = new ModelParam(); 590 def.name = "userLogin"; 591 def.type = "org.ofbiz.entity.GenericValue"; 592 def.mode = "INOUT"; 593 def.optional = true; 594 def.internal = true; 595 service.addParam(def); 596 def = new ModelParam(); 598 def.name = "locale"; 599 def.type = "java.util.Locale"; 600 def.mode = "INOUT"; 601 def.optional = true; 602 def.internal = true; 603 service.addParam(def); 604 } 605 606 protected void createOverrideDefs(Element baseElement, ModelService service) { 607 List paramElements = UtilXml.childElementList(baseElement, "override"); 608 Iterator paramIter = paramElements.iterator(); 609 610 while (paramIter.hasNext()) { 611 Element attribute = (Element ) paramIter.next(); 612 String name = UtilXml.checkEmpty(attribute.getAttribute("name")); 613 ModelParam param = service.getParam(name); 614 boolean directToParams = true; 615 if (param == null) { 616 if (service.implServices.size() > 0 && !service.inheritedParameters) { 617 directToParams = false; 620 param = new ModelParam(); 621 param.name = name; 622 } else { 623 Debug.logWarning("No parameter found for override parameter named: " + name + " in service " + service.name, module); 624 } 625 } 626 627 if (param != null) { 628 if (attribute.getAttribute("type") != null && attribute.getAttribute("type").length() > 0) { 630 param.type = UtilXml.checkEmpty(attribute.getAttribute("type")); 631 } 632 if (attribute.getAttribute("mode") != null && attribute.getAttribute("mode").length() > 0) { 633 param.mode = UtilXml.checkEmpty(attribute.getAttribute("mode")); 634 } 635 if (attribute.getAttribute("entity-name") != null && attribute.getAttribute("entity-name").length() > 0) { 636 param.entityName = UtilXml.checkEmpty(attribute.getAttribute("entity-name")); 637 } 638 if (attribute.getAttribute("field-name") != null && attribute.getAttribute("field-name").length() > 0) { 639 param.fieldName = UtilXml.checkEmpty(attribute.getAttribute("field-name")); 640 } 641 if (attribute.getAttribute("form-label") != null && attribute.getAttribute("form-label").length() > 0) { 642 param.formLabel = UtilXml.checkEmpty(attribute.getAttribute("form-label")); 643 } 644 if (attribute.getAttribute("optional") != null && attribute.getAttribute("optional").length() > 0) { 645 param.optional = "true".equalsIgnoreCase(attribute.getAttribute("optional")); param.overrideOptional = true; 647 } 648 if (attribute.getAttribute("form-display") != null && attribute.getAttribute("form-display").length() > 0) { 649 param.formDisplay = !"false".equalsIgnoreCase(attribute.getAttribute("form-display")); param.overrideFormDisplay = true; 651 } 652 653 this.addValidators(attribute, param); 655 656 if (directToParams) { 657 service.addParam(param); 658 } else { 659 service.overrideParameters.add(param); 660 } 661 } 662 } 663 } 664 665 protected void addValidators(Element attribute, ModelParam param) { 666 List validateElements = UtilXml.childElementList(attribute, "type-validate"); 667 if (validateElements != null && validateElements.size() > 0) { 668 param.validators = FastList.newInstance(); 670 671 Iterator i = validateElements.iterator(); 672 Element validate = (Element ) i.next(); 673 String methodName = validate.getAttribute("method"); 674 String className = validate.getAttribute("class"); 675 676 Element fail = UtilXml.firstChildElement(validate, "fail-message"); 677 if (fail != null) { 678 String message = fail.getAttribute("message"); 679 param.addValidator(className, methodName, message); 680 } else { 681 fail = UtilXml.firstChildElement(validate, "fail-property"); 682 if (fail != null) { 683 String resource = fail.getAttribute("resource"); 684 String property = fail.getAttribute("property"); 685 param.addValidator(className, methodName, resource, property); 686 } 687 } 688 } 689 } 690 691 protected Document getDocument(URL url) { 692 if (url == null) 693 return null; 694 Document document = null; 695 696 try { 697 document = UtilXml.readXmlDocument(url, true); 698 } catch (SAXException sxe) { 699 Exception x = sxe; 701 702 if (sxe.getException() != null) 703 x = sxe.getException(); 704 x.printStackTrace(); 705 } catch (ParserConfigurationException pce) { 706 pce.printStackTrace(); 708 } catch (IOException ioe) { 709 ioe.printStackTrace(); 710 } 711 712 return document; 713 } 714 } 715 | Popular Tags |