1 package org.jbpm.bpel.xml; 2 3 import java.io.ByteArrayInputStream ; 4 import java.io.IOException ; 5 import java.util.Arrays ; 6 import java.util.HashMap ; 7 import java.util.HashSet ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Map ; 11 import java.util.Set ; 12 13 import javax.wsdl.Definition; 14 import javax.wsdl.Message; 15 import javax.wsdl.Operation; 16 import javax.wsdl.OperationType; 17 import javax.wsdl.PortType; 18 import javax.wsdl.WSDLException; 19 import javax.wsdl.xml.WSDLReader; 20 import javax.xml.namespace.QName ; 21 import javax.xml.parsers.DocumentBuilder ; 22 import javax.xml.transform.Transformer ; 23 import javax.xml.transform.TransformerException ; 24 import javax.xml.transform.dom.DOMResult ; 25 import javax.xml.transform.dom.DOMSource ; 26 27 import org.apache.commons.collections.Predicate; 28 import org.apache.commons.collections.iterators.FilterIterator; 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.w3c.dom.Attr ; 32 import org.w3c.dom.Document ; 33 import org.w3c.dom.Element ; 34 import org.w3c.dom.Node ; 35 import org.xml.sax.InputSource ; 36 import org.xml.sax.SAXException ; 37 38 import org.jbpm.bpel.data.def.ElementTypeInfo; 39 import org.jbpm.bpel.data.def.MessageTypeInfo; 40 import org.jbpm.bpel.data.def.SchemaTypeInfo; 41 import org.jbpm.bpel.data.def.Snippet; 42 import org.jbpm.bpel.data.def.VariableDefinition; 43 import org.jbpm.bpel.data.def.VariableTypeInfo; 44 import org.jbpm.bpel.data.def.Snippet.Use; 45 import org.jbpm.bpel.def.Activity; 46 import org.jbpm.bpel.def.AlarmHandler; 47 import org.jbpm.bpel.def.BpelDefinition; 48 import org.jbpm.bpel.def.CompositeActivity; 49 import org.jbpm.bpel.def.FaultHandler; 50 import org.jbpm.bpel.def.Import; 51 import org.jbpm.bpel.def.ImportsDefinition; 52 import org.jbpm.bpel.def.MessageHandler; 53 import org.jbpm.bpel.def.Scope; 54 import org.jbpm.bpel.def.ScopeHandler; 55 import org.jbpm.bpel.def.Import.Type; 56 import org.jbpm.bpel.service.def.Correlation; 57 import org.jbpm.bpel.service.def.CorrelationSetDefinition; 58 import org.jbpm.bpel.service.def.Correlations; 59 import org.jbpm.bpel.service.def.PartnerLinkDefinition; 60 import org.jbpm.bpel.service.def.Receiver; 61 import org.jbpm.bpel.service.def.Correlation.Initiate; 62 import org.jbpm.bpel.timer.def.Alarm; 63 import org.jbpm.bpel.wsdl.def.PartnerLinkType; 64 import org.jbpm.bpel.wsdl.def.Property; 65 import org.jbpm.bpel.wsdl.def.PropertyAlias; 66 import org.jbpm.bpel.wsdl.def.PartnerLinkType.Role; 67 import org.jbpm.bpel.wsdl.util.WsdlUtil; 68 import org.jbpm.bpel.xml.util.NodeUtil; 69 import org.jbpm.jpdl.par.ProcessArchive; 70 import org.jbpm.jpdl.xml.Problem; 71 72 import com.ibm.wsdl.util.xml.DOMUtils; 73 74 79 public class BpelReader { 80 81 private Map activityReaders; 82 private DocumentBuilder builder; 83 private Transformer bpelUpgrader; 84 private ProblemHandler problemHandler = new ProblemCollector(); 85 86 private static final BpelReader INSTANCE = new BpelReader(); 87 private static final String BPEL_1_1_TEMPLATE = "bpel-1-1-converter.xsl"; 88 private static final Log log = LogFactory.getLog(BpelReader.class); 89 90 protected BpelReader() { 91 initializeActivityParsers(); 92 builder = NodeUtil.getDocumentBuilder(); 93 bpelUpgrader = NodeUtil.createUpgrader(BpelReader.class.getResource(BPEL_1_1_TEMPLATE)); 94 } 95 96 101 public void read(BpelDefinition processDefinition, InputSource input) { 102 try { 103 String location = input.getSystemId(); 105 ErrorHandlerAdapter validationHandler = new ErrorHandlerAdapter(getProblemHandler()); 106 builder.setErrorHandler(validationHandler); 107 Document bpelDocument = builder.parse(input); 108 if( !validationHandler.hasErrors() ) { 109 ImportWsdlLocator wsdlLocator = null; 110 if (location != null) { 111 wsdlLocator = new ImportWsdlLocator(location); 112 wsdlLocator.setProblemHandler(getProblemHandler()); 113 processDefinition.setLocation(location); 114 } 115 read(processDefinition, bpelDocument.getDocumentElement(), wsdlLocator); 116 } 117 } 118 catch (SAXException e) { 119 getProblemHandler().add( 120 new Problem( Problem.LEVEL_ERROR, "bpel document contains invalid xml", e) ); 121 } 122 catch (IOException e) { 123 getProblemHandler().add( 124 new Problem( Problem.LEVEL_ERROR, "bpel document is not readable", e) ); 125 } 126 } 127 128 133 public void read(BpelDefinition processDefinition, ProcessArchive archive) { 134 String location = processDefinition.getLocation(); 135 byte[] bpelEntry = archive.removeEntry(location); 136 if (bpelEntry == null) { 137 getProblemHandler().add( 138 new Problem(Problem.LEVEL_ERROR, "bpel document not found") ); 139 return; 140 } 141 try { 142 ErrorHandlerAdapter validationHandler = new ErrorHandlerAdapter(getProblemHandler()); 143 builder.setErrorHandler(validationHandler); 144 Document bpelDocument = builder.parse(new ByteArrayInputStream (bpelEntry)); 145 if( !validationHandler.hasErrors() ) { 146 ImportWsdlLocator wsdlLocator = new ArchiveWsdlLocator(location, archive); 147 wsdlLocator.setProblemHandler(getProblemHandler()); 148 read(processDefinition, bpelDocument.getDocumentElement(), wsdlLocator); 149 } 150 } 151 catch (SAXException e) { 152 getProblemHandler().add( 153 new Problem( Problem.LEVEL_ERROR, "bpel document contains invalid xml", e) ); 154 } 155 catch (IOException e) { 156 getProblemHandler().add( 157 new Problem( Problem.LEVEL_ERROR, "bpel document is not readable", e) ); 158 } 159 } 160 161 protected void read(BpelDefinition process, Element processElem, ImportWsdlLocator wsdlLocator) { 162 if (!BpelConstants.NS_BPWS.equals(processElem.getNamespaceURI())) { 163 Document newProcessDoc = builder.newDocument(); 165 ErrorListenerAdapter transformHandler = new ErrorListenerAdapter(getProblemHandler()); 166 bpelUpgrader.setErrorListener(transformHandler); 167 try { 168 bpelUpgrader.transform( 169 new DOMSource (processElem.getOwnerDocument()), new DOMResult (newProcessDoc)); 170 } 171 catch (TransformerException e) { 172 transformHandler.error(e); 173 } 174 if(transformHandler.hasErrors()) return; 176 log.debug("upgraded bpel document: " + process.getLocation()); 177 processElem = newProcessDoc.getDocumentElement(); 178 } 179 180 readTopLevelAttributes(processElem, process); 182 ImportsDefinition imports = process.getImports(); 184 readImports(processElem, imports, wsdlLocator); 185 if( wsdlLocator.hasErrors() ) return; 187 188 try { 189 registerPropertyAliases(imports); 191 readScope(processElem, process.getScope()); 193 } 194 catch(BpelException e) { 195 getProblemHandler().add( new Problem(Problem.LEVEL_ERROR, "bpel process is invalid.", e) ); 196 } 197 } 198 199 public void registerPropertyAliases(ImportsDefinition importsDef) { 200 List imports = importsDef.getImports(); 201 if (imports == null) return; 203 BpelDefinition process = (BpelDefinition) importsDef.getProcessDefinition(); 205 String queryLanguage = process != null ? process.getQueryLanguage() : BpelConstants.URN_XPATH_1_0; 206 for (int i = 0, n = imports.size(); i < n; i++) { 208 Import imp = (Import) imports.get(i); 209 if (imp.getType().equals(Type.WSDL)) { 210 registerPropertyAliases(importsDef, (Definition) imp.getDocument(), queryLanguage); 211 } 212 } 213 } 214 215 private void registerPropertyAliases(ImportsDefinition importsDef, Definition def, String queryLanguage) { 216 Iterator extensionIt = def.getExtensibilityElements().iterator(); 218 while (extensionIt.hasNext()) { 219 Object extension = extensionIt.next(); 220 if (extension instanceof PropertyAlias) { 221 PropertyAlias alias = (PropertyAlias) extension; 222 Snippet query = alias.getQuery(); 224 if (query.getLanguage() == null) { 225 query.setLanguage(queryLanguage); 226 } 227 try { 228 query.parseScript(); 229 } 230 catch(BpelException e) { 231 Problem problem = new Problem(Problem.LEVEL_ERROR, 232 "unable to parse property alias query", e); 233 problem.setResource(def.getDocumentBaseURI()); 234 getProblemHandler().add(problem); 235 } 236 MessageTypeInfo message = importsDef.getMessageTypeInfo(alias.getMessage().getQName()); 238 message.addPropertyAlias(alias); 239 } 240 } 241 Iterator importsIter = def.getImports().values().iterator(); 243 while (importsIter.hasNext()) { 244 List imports = (List ) importsIter.next(); 245 for (int i = 0, n = imports.size(); i < n; i++) { 246 javax.wsdl.Import imp = (javax.wsdl.Import) imports.get(i); 247 registerPropertyAliases(importsDef, imp.getDefinition(), queryLanguage); 248 } 249 } 250 } 251 252 253 255 public void readTopLevelAttributes(Element processElem, BpelDefinition process) { 256 process.setName(processElem.getAttribute(BpelConstants.ATTR_NAME)); 258 process.setTargetNamespace(processElem.getAttribute(BpelConstants.ATTR_TARGET_NAMESPACE)); 259 process.setQueryLanguage(NodeUtil.getAttribute(processElem, BpelConstants.ATTR_QUERY_LANGUAGE)); 261 process.setExpressionLanguage(NodeUtil.getAttribute(processElem, BpelConstants.ATTR_EXPRESSION_LANGUAGE)); 262 Attr suppressAttr = processElem.getAttributeNode(BpelConstants.ATTR_SUPPRESS_JOIN_FAILURE); 264 Boolean suppressValue = readTBoolean(suppressAttr, Boolean.FALSE); 265 process.getScope().setSuppressJoinFailure(suppressValue); 266 Attr abstractAttr = processElem.getAttributeNode(BpelConstants.ATTR_ABSTRACT_PROCESS); 268 Boolean abstractValue = readTBoolean(abstractAttr, Boolean.FALSE); 269 process.setAbstractProcess(abstractValue.booleanValue()); 270 Attr compensationAttr = processElem.getAttributeNode(BpelConstants.ATTR_INSTANCE_COMPENSATION); 272 Boolean compensationValue = readTBoolean(compensationAttr, Boolean.FALSE); 273 process.setEnableInstanceCompensation(compensationValue.booleanValue()); 274 } 275 276 public void readImports(Element processElem, ImportsDefinition imports, 277 ImportWsdlLocator wsdlLocator) { 278 Iterator importElemIt = NodeUtil.getElements(processElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_IMPORT); 279 while (importElemIt.hasNext()) { 280 Import imp = readImport((Element ) importElemIt.next()); 281 if (Import.Type.WSDL.equals(imp.getType())) { 282 readWsdlDocument(imp, wsdlLocator); 283 } 284 imports.addImport(imp); 285 } 286 } 287 288 public Import readImport(Element importElem) { 289 Import imp = new Import(); 290 imp.setNamespace(importElem.getAttribute(BpelConstants.ATTR_NAMESPACE)); 291 imp.setLocation(importElem.getAttribute(BpelConstants.ATTR_LOCATION)); 292 imp.setType(Import.Type.valueOf(importElem.getAttribute(BpelConstants.ATTR_IMPORT_TYPE))); 293 return imp; 294 } 295 296 public void readWsdlDocument(Import imp, ImportWsdlLocator wsdlLocator) { 297 String location = imp.getLocation(); 298 wsdlLocator.resolveBaseURI(location); 299 WSDLReader reader = WsdlUtil.getFactory().newWSDLReader(); 300 Definition def; 302 try { 303 log.debug("read wsdl document: " + location); 304 def = reader.readWSDL(wsdlLocator); 305 if (!def.getTargetNamespace().equals(imp.getNamespace())) { 307 Problem problem = new Problem(Problem.LEVEL_ERROR, 308 "imported definitions do not belong to the import's namespace"); 309 problem.setResource(def.getDocumentBaseURI()); 310 getProblemHandler().add(problem); 311 } 312 imp.setDocument(def); 313 } 314 catch (WSDLException e) { 315 Problem problem = new Problem(Problem.LEVEL_ERROR, "could not read wsdl document", e); 316 problem.setResource(location); 317 getProblemHandler().add(problem); 318 } 319 } 320 321 322 324 public Boolean readTBoolean(Attr attribute, Boolean defaultValue) { 325 if (attribute == null) { 326 return defaultValue; 327 } 328 String text = attribute.getValue(); 329 return Boolean.valueOf( BpelConstants.YES.equalsIgnoreCase(text) ); 330 } 331 332 public Snippet readExpression(Element enclosingElement, CompositeActivity parent, Use use) { 333 Snippet expr = new Snippet(); 335 expr.setText(DOMUtils.getChildCharacterData(enclosingElement)); 336 expr.setNamespaces(NodeUtil.getNamespaceDeclarations(enclosingElement)); 337 expr.setUse(use); 338 String language = NodeUtil.getAttribute(enclosingElement, BpelConstants.ATTR_EXPRESSION_LANGUAGE); 340 if (language == null) { 341 BpelDefinition process = parent.getBpelDefinition(); 342 if (use == Use.EXPRESSION || use == Use.JOIN_CONDITION) { 343 language = process.getExpressionLanguage(); 344 } 345 else if (use == Use.QUERY || use == Use.PROPERTY_ALIAS) { 346 language = process.getQueryLanguage(); 347 } 348 } 349 expr.setLanguage(language); 350 try { 352 expr.parseScript(); 353 return expr; 354 } 355 catch (BpelException e) { 356 getProblemHandler().add( 357 new Problem( Problem.LEVEL_ERROR, "unable to read expression.", e) ); 358 return null; 359 } 360 } 361 362 public Snippet readExpression(Element enclosingElement, CompositeActivity parent) { 363 return readExpression(enclosingElement, parent, Use.EXPRESSION); 364 } 365 366 368 public void readScope(Element scopeElem, Scope scope) { 369 Element variablesElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_VARIABLES ); 371 if (variablesElem != null ) scope.setVariables ( readVariables(variablesElem, scope) ); 372 373 Element partnerLinksElem = NodeUtil.getElement( scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_PARTNER_LINKS ); 375 if (partnerLinksElem != null ) scope.setPartnerLinks( readPartnerLinks(partnerLinksElem, scope) ); 376 377 Element setsElem = NodeUtil.getElement( scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION_SETS ); 379 if (setsElem != null ) scope.setCorrelationSets( readCorrelationSets(setsElem, scope) ); 380 381 Element activityElem = getActivityElement(scopeElem); 383 readActivity(activityElem, scope); 384 385 Element faultHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_FAULT_HANDLERS ); 387 if( faultHandlerElem != null ) readFaultHandlers(faultHandlerElem, scope); 388 389 Element compHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_COMPENSATION_HANDLER ); 391 if( compHandlerElem != null ) readHandler(compHandlerElem, scope, Scope.COMPENSATION); 392 393 Element eventHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_EVENT_HANDLERS ); 395 if( eventHandlerElem != null ) readEventHandlers(eventHandlerElem, scope); 396 397 Element termHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_TERMINATION_HANDLER ); 399 if( termHandlerElem != null ) readHandler(termHandlerElem, scope, Scope.TERMINATION); 400 } 401 402 public void readHandler(Element element, Scope scope, Scope.HandlerType type) { 403 ScopeHandler handler = new ScopeHandler(); 404 scope.setHandler(type, handler); 405 Element activityElement = getActivityElement(element); 406 handler.setActivity(readActivity(activityElement, handler)); 407 } 408 409 public void readFaultHandlers(Element faultHandlerElem, Scope scope) { 410 Element catchAllElem = NodeUtil.getElement(faultHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CATCH_ALL ); 412 if( catchAllElem != null ) { 413 readHandler(catchAllElem, scope, Scope.CATCH_ALL); 414 } 415 416 Iterator catchElemIt = NodeUtil.getElements(faultHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CATCH); 417 while (catchElemIt.hasNext()) { 418 Element catchElement = (Element ) catchElemIt.next(); 419 readFaultHandler( catchElement, scope ); 420 } 421 } 422 423 public void readFaultHandler(Element catchElement, Scope scope) { 424 FaultHandler faultHandler = new FaultHandler(); 425 scope.addFaultHandler(faultHandler); 426 Element activityElement = getActivityElement(catchElement); 427 faultHandler.setActivity(readActivity(activityElement, faultHandler)); 428 429 435 436 String faultNameStr = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_NAME); 437 if( faultNameStr != null) { 438 QName faultName = NodeUtil.getQName(faultNameStr, catchElement); 439 faultHandler.setFaultName(faultName); 440 } 441 String variableName = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_VARIABLE); 442 boolean hasName = faultHandler.getFaultName() != null; 443 if( variableName == null && !hasName) { 444 getProblemHandler().add( 445 new LocalizedProblem( Problem.LEVEL_ERROR, 446 "catch must specify either a faultName or a faultVariable", catchElement ) ); 447 return; 448 } 449 VariableTypeInfo faultTypeInfo = null; 450 ImportsDefinition imports = scope.getBpelDefinition().getImports(); 451 String faultMessageType = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_MESSAGE_TYPE); 452 String faultElement = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_ELEMENT); 453 if( faultMessageType != null ) { 454 if(faultElement != null) { 456 getProblemHandler().add( 457 new LocalizedProblem( Problem.LEVEL_ERROR, 458 "faultMessageType and faultElement can't be both present", catchElement ) ); 459 } 460 faultTypeInfo = getMessageTypeInfo(catchElement, faultMessageType, imports); 461 } 462 else if( faultElement != null ) { 463 faultTypeInfo = getElementTypeInfo(catchElement, faultElement, imports); 465 } 466 467 if(variableName != null) { 468 if(faultTypeInfo == null) { 470 throw new BpelException("catch must specify either a faultMessageType or a faultElement", catchElement); 471 } 472 VariableDefinition variable = new VariableDefinition(variableName); 473 variable.setTypeInfo(faultTypeInfo); 474 faultHandler.setFaultVariable(variable); 475 } 476 } 477 478 public void readEventHandlers(Element eventHandlerElem, Scope scope) { 479 Iterator eventElemIt = NodeUtil.getElements(eventHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_ON_EVENT); 481 while (eventElemIt.hasNext()) { 482 Element eventElem = (Element ) eventElemIt.next(); 483 MessageHandler handler = new MessageHandler(); 484 scope.addMessageHandler(handler); 485 String messageType = NodeUtil.getAttribute(eventElem, BpelConstants.ATTR_MESSAGE_TYPE); 487 if(messageType != null) { 488 VariableDefinition variable = new VariableDefinition(); 489 String name = NodeUtil.getAttribute(eventElem, BpelConstants.ATTR_VARIABLE); 491 variable.setName(name); 492 VariableTypeInfo typeInfo = getMessageTypeInfo(eventElem, messageType, scope.getBpelDefinition().getImports()); 494 variable.setTypeInfo(typeInfo); 495 handler.setVariableDefinition(variable); 496 } 497 Element setsElem = NodeUtil.getElement( eventElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION_SETS ); 499 if (setsElem != null ) handler.setCorrelationSets( readCorrelationSets(setsElem, scope) ); 500 Element activityElem = getActivityElement(eventElem); 502 readActivity(activityElem, handler); 503 Receiver receiver = readReceiver(eventElem, handler); 505 receiver.setInboundMessageActivity( handler ); 506 handler.setReceiver(receiver); 507 } 508 Iterator alarmElemIt = NodeUtil.getElements(eventHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_ON_ALARM); 510 while (alarmElemIt.hasNext()) { 511 AlarmHandler handler = new AlarmHandler(); 512 scope.addAlarmHandler(handler); 513 Element alarmElem = (Element ) alarmElemIt.next(); 514 Element activityElem = getActivityElement(alarmElem); 515 readActivity(activityElem, handler); 516 Alarm alarm = readAlarm(alarmElem, handler); 517 alarm.setAlarmActivity(handler); 518 handler.setAlarm(alarm); 519 } 520 } 521 522 public Map readVariables(Element variablesElem, CompositeActivity parent) { 523 Map variables = new HashMap (); 524 ImportsDefinition imports = parent.getBpelDefinition().getImports(); 525 Iterator variableElemIt = NodeUtil.getElements(variablesElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_VARIABLE); 526 while (variableElemIt.hasNext()) { 527 Element variableElem = (Element ) variableElemIt.next(); 528 VariableDefinition variable = readVariable(variableElem, imports); 529 String variableName = variable.getName(); 530 if( variables.containsKey(variableName) ) { 531 getProblemHandler().add( 532 new LocalizedProblem( Problem.LEVEL_ERROR, "duplicate local name", variableElem ) ); 533 } 534 else { 535 variables.put(variableName, variable); 536 } 537 } 538 return variables; 539 } 540 541 public VariableDefinition readVariable(Element variableElem, ImportsDefinition imports) { 542 VariableDefinition variable = new VariableDefinition(); 543 String name = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_NAME); 545 variable.setName(name); 546 VariableTypeInfo typeInfo = getTypeInfo(variableElem, imports); 548 variable.setTypeInfo(typeInfo); 549 return variable; 550 } 551 552 private VariableTypeInfo getTypeInfo(Element variableElem, ImportsDefinition imports) { 553 VariableTypeInfo typeInfo; 554 555 String type = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_TYPE); 556 String messageType = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_MESSAGE_TYPE); 557 String element = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_ELEMENT); 558 559 if (messageType != null) { 560 if (type != null || element != null) { 561 getProblemHandler().add( 562 new LocalizedProblem( Problem.LEVEL_ERROR, "more than one type specifier is used", variableElem ) ); 563 } 564 typeInfo = getMessageTypeInfo(variableElem, messageType, imports); 565 } 566 567 else if (type != null) { 568 if (element != null) { 569 getProblemHandler().add( 570 new LocalizedProblem( Problem.LEVEL_ERROR, "more than one type specifier is used", variableElem ) ); 571 } 572 typeInfo = getSchemaTypeInfo(variableElem, type, imports); 573 } 574 else if (element != null) { 575 typeInfo = getElementTypeInfo(variableElem, element, imports); 576 } 577 else { 578 throw new BpelException("no type specifier is used", variableElem); 579 } 580 return typeInfo; 581 } 582 583 private MessageTypeInfo getMessageTypeInfo(Element parent, String messageType, ImportsDefinition imports) { 584 QName qname = NodeUtil.getQName(messageType, parent); 585 MessageTypeInfo typeInfo = imports.getMessageTypeInfo(qname); 586 if (typeInfo == null) { 587 throw new BpelException("message type " + messageType + " not found", parent); 588 } 589 return typeInfo; 590 } 591 592 private ElementTypeInfo getElementTypeInfo(Element parent, String elementType, ImportsDefinition imports) { 593 QName qname = NodeUtil.getQName(elementType, parent); 594 ElementTypeInfo typeInfo = imports.getElementTypeInfo(qname); 595 if (typeInfo == null) { 596 throw new BpelException("element type " + elementType + " not found", parent); 597 } 598 return typeInfo; 599 } 600 601 private SchemaTypeInfo getSchemaTypeInfo(Element parent, String schemaType, ImportsDefinition imports) { 602 QName qname = NodeUtil.getQName(schemaType, parent); 603 SchemaTypeInfo typeInfo = imports.getSchemaTypeInfo(qname); 604 if (typeInfo == null) { 605 throw new BpelException("schema type " + schemaType + " not found", parent); 606 } 607 return typeInfo; 608 } 609 610 612 public Map readCorrelationSets(Element setsElem, CompositeActivity superState) { 613 Map correlationSets = new HashMap (); 614 ImportsDefinition imports = superState.getBpelDefinition().getImports(); 615 Iterator setElemIt = NodeUtil.getElements(setsElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION_SET); 616 while (setElemIt.hasNext()) { 617 Element setElem = (Element ) setElemIt.next(); 618 CorrelationSetDefinition set = readCorrelationSet(setElem, imports); 619 String setName = set.getName(); 620 if (correlationSets.containsKey(setName)) { 621 getProblemHandler().add( 622 new LocalizedProblem( Problem.LEVEL_ERROR, "duplicate local name", setElem ) ); 623 } 624 else { 625 correlationSets.put(setName, set); 626 } 627 } 628 return correlationSets; 629 } 630 631 public CorrelationSetDefinition readCorrelationSet(Element setElem, ImportsDefinition imports) { 632 CorrelationSetDefinition set = new CorrelationSetDefinition(); 633 String [] propertyNames = setElem.getAttribute(BpelConstants.ATTR_PROPERTIES).split("\\s"); 635 for (int p = 0; p < propertyNames.length; p++) { 636 String propertyName = propertyNames[p]; 637 Property property = imports.getProperty(NodeUtil.getQName(propertyName, setElem)); 638 if (property == null) { 639 throw new BpelException("property not found: " + propertyName, setElem); 640 } 641 set.addProperty(property); 642 } 643 set.setName(setElem.getAttribute(BpelConstants.ATTR_NAME)); 645 return set; 646 } 647 648 public Map readPartnerLinks(Element partnerLinksElem, CompositeActivity parent) { 649 Map partnerLinks = new HashMap (); 650 Iterator partnerLinkElemIt = NodeUtil.getElements(partnerLinksElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_PARTNER_LINK); 651 while (partnerLinkElemIt.hasNext()) { 652 Element partnerLinkElem = (Element ) partnerLinkElemIt.next(); 653 PartnerLinkDefinition partnerLink = readPartnerLink(partnerLinkElem, parent); 654 String plinkName = partnerLink.getName(); 655 if ( partnerLinks.containsKey(plinkName) ) { 656 getProblemHandler().add( 657 new LocalizedProblem( Problem.LEVEL_ERROR, "duplicate local name", partnerLinkElem ) ); 658 } 659 else { 660 partnerLinks.put(plinkName, partnerLink); 661 } 662 } 663 return partnerLinks; 664 } 665 666 public PartnerLinkDefinition readPartnerLink(Element partnerLinkElem, CompositeActivity parent) { 667 PartnerLinkDefinition partnerLink = new PartnerLinkDefinition(); 668 String typeName = partnerLinkElem.getAttribute(BpelConstants.ATTR_PARTNER_LINK_TYPE); 670 QName typeQName = NodeUtil.getQName(typeName, partnerLinkElem); 671 PartnerLinkType type = parent.getBpelDefinition().getImports().getPartnerLinkType(typeQName); 672 if (type == null) { 673 throw new BpelException("partner link type not found", partnerLinkElem); 674 } 675 partnerLink.setPartnerLinkType(type); 676 677 String myRoleName = NodeUtil.getAttribute(partnerLinkElem, BpelConstants.ATTR_MY_ROLE); 678 String partnerRoleName = NodeUtil.getAttribute(partnerLinkElem, BpelConstants.ATTR_PARTNER_ROLE); 679 680 boolean partnerRoleIsFirst; 682 Role role = type.getFirstRole(); 683 String roleName = role.getName(); 684 if (roleName.equals(myRoleName)) { 685 partnerLink.setMyRole(role); 686 partnerRoleIsFirst = false; 687 } 688 else if (roleName.equals(partnerRoleName)) { 689 partnerLink.setPartnerRole(role); 690 partnerRoleIsFirst = true; 691 } 692 else { 693 throw new BpelException("neither myRole nor partnerRole match the first role", partnerLinkElem); 694 } 695 role = type.getSecondRole(); 697 if (role != null) { 698 roleName = role.getName(); 699 if (partnerRoleIsFirst) { 700 if (!roleName.equals(myRoleName)) { 701 throw new BpelException("partnerRole matches the first role, " + 702 "but myRole does not match the second one", partnerLinkElem); 703 } 704 partnerLink.setMyRole(role); 705 } 706 else { 707 if (!roleName.equals(partnerRoleName)) { 708 throw new BpelException("myRole matches the first role, " + 709 "but partnerRole does not match the second one", partnerLinkElem); 710 } 711 partnerLink.setPartnerRole(role); 712 } 713 } 714 else if (partnerRoleIsFirst ? myRoleName != null : partnerRoleName != null) { 715 throw new BpelException("both myRole and partnerRole are specified, " + 716 "but there is only one role", partnerLinkElem); 717 } 718 partnerLink.setId(partnerLink.hashCode()); 720 partnerLink.setName(partnerLinkElem.getAttribute(BpelConstants.ATTR_NAME)); 722 return partnerLink; 723 } 724 725 public Receiver readReceiver(Element receiverElem, CompositeActivity parent) { 726 Receiver receiver = new Receiver(); 727 String plinkName = receiverElem.getAttribute( BpelConstants.ATTR_PARTNER_LINK ); 729 PartnerLinkDefinition partnerLink = parent.findPartnerLink(plinkName); 730 if (partnerLink == null) { 731 getProblemHandler().add( 732 new LocalizedProblem( Problem.LEVEL_ERROR, "partner link not found", receiverElem ) ); 733 return null; 734 } 735 receiver.setPartnerLink( partnerLink ); 736 PortType portType = getPortType(receiverElem, partnerLink.getMyRole()); 738 Operation operation = getOperation(receiverElem, portType); 740 receiver.setOperation( operation ); 741 VariableDefinition variable = getVariable(receiverElem, BpelConstants.ATTR_VARIABLE, parent, 743 operation.getInput().getMessage()); 744 receiver.setVariable( variable ); 745 receiver.setMessageExchange(receiverElem.getAttribute(BpelConstants.ATTR_MESSAGE_EXCHANGE)); 747 Element correlationsElement = NodeUtil.getElement(receiverElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATIONS ); 749 if (correlationsElement != null) { 750 receiver.setCorrelations(readCorrelations(correlationsElement, parent, variable)); 751 } 752 receiver.setId(receiver.hashCode()); 754 return receiver; 755 } 756 757 public Correlations readCorrelations(Element correlationsElem, CompositeActivity parent, VariableDefinition variable) { 758 Correlations correlations = new Correlations(); 759 Iterator correlationElemIt = NodeUtil.getElements(correlationsElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION); 760 while (correlationElemIt.hasNext()) { 761 Correlation correlation = readCorrelation((Element ) correlationElemIt.next(), parent); 762 checkVariableProperties(variable, correlation.getSet()); 763 correlations.addCorrelation(correlation); 764 } 765 return correlations; 766 } 767 768 public Correlation readCorrelation(Element correlationElem, CompositeActivity parent) { 769 Correlation correlation = new Correlation(); 770 CorrelationSetDefinition set = parent.findCorrelationSet(correlationElem.getAttribute(BpelConstants.ATTR_SET)); 772 if (set == null) { 773 throw new BpelException("correlation set not found", correlationElem); 774 } 775 correlation.setSet(set); 776 correlation.setInitiate(Initiate.valueOf(NodeUtil.getAttribute(correlationElem, BpelConstants.ATTR_INITIATE))); 778 return correlation; 779 } 780 781 PortType getPortType(Element serviceElem, Role role) { 782 PortType implicitPortType = role.getPortType(); 783 String portTypeName = NodeUtil.getAttribute(serviceElem, BpelConstants.ATTR_PORT_TYPE ); 784 if (portTypeName != null) { 785 QName portTypeQName = NodeUtil.getQName(portTypeName, serviceElem); 786 if ( !portTypeQName.equals(implicitPortType.getQName()) ) 787 getProblemHandler().add( 788 new LocalizedProblem( Problem.LEVEL_ERROR, 789 "port type does not match the port type expected by the partner link", serviceElem) ); 790 } 791 return implicitPortType; 792 } 793 794 Operation getOperation(Element serviceElem, PortType portType) { 795 String operationName = serviceElem.getAttribute( BpelConstants.ATTR_OPERATION ); 796 Operation op; 797 try { 798 op = portType.getOperation( operationName, null, null ); 799 } 800 catch (RuntimeException e) { 801 throw new BpelException("overloaded operations are not supported", serviceElem); 802 } 803 if (op == null) { 804 throw new BpelException("operation not found", serviceElem); 805 } 806 OperationType opType = op.getStyle(); 807 if (opType.equals(OperationType.SOLICIT_RESPONSE) || 808 opType.equals(OperationType.NOTIFICATION)) { 809 getProblemHandler().add( 810 new LocalizedProblem( Problem.LEVEL_ERROR, 811 "operation style not supported: " + opType, serviceElem) ); 812 } 813 return op; 814 } 815 816 VariableDefinition getVariable(Element serviceElem, String variableAttr, CompositeActivity parent, 817 Message operationMessage) { 818 String variableName = NodeUtil.getAttribute(serviceElem, variableAttr ); 820 if (variableName == null) { 821 throw new BpelException(variableAttr + " attribute is missing", serviceElem); 822 } 823 VariableDefinition variable = parent.findVariable(variableName); 825 if( variable == null ) { 826 throw new BpelException(variableAttr + " not found", serviceElem); 827 } 828 else if( !variable.getTypeInfo().getName().equals(operationMessage.getQName()) ) { 830 getProblemHandler().add( 831 new LocalizedProblem(Problem.LEVEL_ERROR, "type of " + variableAttr + 832 " is not applicable for the operation", serviceElem) ); 833 } 834 835 return variable; 836 } 837 838 void checkVariableProperties(VariableDefinition variable, CorrelationSetDefinition set) { 839 Set msgProperties = new HashSet (); 840 Map aliases = variable.getTypeInfo().getPropertyAliases(); 841 if (aliases != null) { 842 Iterator aliasIt = aliases.values().iterator(); 843 while (aliasIt.hasNext()) { 844 PropertyAlias alias = (PropertyAlias) aliasIt.next(); 845 msgProperties.add(alias.getProperty()); 846 } 847 } 848 Iterator setPropertyIt = set.getProperties().iterator(); 849 while (setPropertyIt.hasNext()) { 850 Property setProperty = (Property) setPropertyIt.next(); 851 if (!msgProperties.contains(setProperty)) { 852 getProblemHandler().add( 853 new Problem( Problem.LEVEL_ERROR, "property " + setProperty.getQName() + 854 " does not appear in variable " + variable.getName()) ); 855 } 856 } 857 } 858 859 861 public Alarm readAlarm(Element element, CompositeActivity parent) { 862 Alarm alarm = new Alarm(); 863 Element repeatElement = NodeUtil.getElement(element, BpelConstants.NS_BPWS, BpelConstants.ELEM_REPEAT); 864 if(repeatElement != null) { 865 alarm.setRepeatEvery(readExpression(repeatElement, parent)); 866 alarm.setAlarmKind(Alarm.AlarmKind.CYCLIC); 867 } 868 869 Element forElement = NodeUtil.getElement(element, BpelConstants.NS_BPWS, BpelConstants.ELEM_FOR); 870 if(forElement != null) { 871 alarm.setFor(readExpression(forElement, parent)); 872 873 if(!Alarm.AlarmKind.CYCLIC.equals(alarm.getAlarmKind())) { 874 alarm.setAlarmKind(Alarm.AlarmKind.DURATION); 875 } 876 } 877 878 Element untilElement = NodeUtil.getElement(element, BpelConstants.NS_BPWS, BpelConstants.ELEM_UNTIL); 879 if(untilElement != null) { 880 alarm.setUntil(readExpression(untilElement, parent)); 881 882 if(!Alarm.AlarmKind.CYCLIC.equals(alarm.getAlarmKind())) { 883 alarm.setAlarmKind(Alarm.AlarmKind.DEADLINE); 884 } 885 } 886 887 if(alarm.getAlarmKind() == null) 888 getProblemHandler().add( 889 new LocalizedProblem( Problem.LEVEL_ERROR, "alarm expression is missing", element ) ); 890 891 return alarm; 892 } 893 894 896 public Activity readActivity(Element activityElem, CompositeActivity parent) { 897 String name = activityElem.getLocalName(); 898 ActivityReader parser = (ActivityReader) activityReaders.get(name); 899 if (parser == null) { 900 throw new BpelException("no reader registered for activity", activityElem); 901 } 902 return parser.read(activityElem, parent); 903 } 904 905 protected Element getActivityElement(Element parent) { 906 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { 907 if (ActivityElementPredicate.evaluate(child)) { 908 return (Element ) child; 909 } 910 } 911 return null; 912 } 913 914 protected Iterator getActivityElements(Element parent) { 915 return new FilterIterator(NodeUtil.getNodes(parent), new ActivityElementPredicate()); 916 } 917 918 public ActivityReader getActivityReader(String name) { 919 return (ActivityReader) activityReaders.get(name); 920 } 921 922 public void registerActivityReader(String name, ActivityReader reader) { 923 reader.setBpelReader(this); 924 activityReaders.put(name, reader); 925 } 926 927 protected void initializeActivityParsers() { 928 activityReaders = new HashMap (); 929 registerActivityReader(BpelConstants.ELEM_RECEIVE, new ReceiveReader()); 930 registerActivityReader(BpelConstants.ELEM_REPLY, new ReplyReader()); 931 registerActivityReader(BpelConstants.ELEM_INVOKE, new InvokeReader()); 932 registerActivityReader(BpelConstants.ELEM_EMPTY, new EmptyReader()); 933 registerActivityReader(BpelConstants.ELEM_ASSIGN, new AssignReader()); 934 registerActivityReader(BpelConstants.ELEM_THROW, new ThrowReader()); 935 registerActivityReader(BpelConstants.ELEM_EXIT, new ExitReader()); 936 registerActivityReader(BpelConstants.ELEM_WAIT, new WaitReader()); 937 registerActivityReader(BpelConstants.ELEM_SEQUENCE, new SequenceReader()); 938 registerActivityReader(BpelConstants.ELEM_SWITCH, new SwitchReader()); 939 registerActivityReader(BpelConstants.ELEM_WHILE, new WhileReader()); 940 registerActivityReader(BpelConstants.ELEM_PICK, new PickReader()); 941 registerActivityReader(BpelConstants.ELEM_FLOW, new FlowReader()); 942 registerActivityReader(BpelConstants.ELEM_SCOPE, new ScopeReader()); 943 registerActivityReader(BpelConstants.ELEM_COMPENSATE, new CompensateReader()); 944 registerActivityReader(BpelConstants.ELEM_VALIDATE, new ValidateReader()); 945 } 946 947 protected ProblemHandler getProblemHandler() { 948 if(problemHandler == null) { 949 problemHandler = new DefaultProblemHandler(); 950 } 951 return problemHandler; 952 } 953 954 public void setProblemHandler(ProblemHandler problemHandler) { 955 this.problemHandler = problemHandler; 956 } 957 958 public static BpelReader getInstance() { 959 return INSTANCE; 960 } 961 962 private static class ActivityElementPredicate implements Predicate { 963 964 private static final Set activityNames = new HashSet (Arrays.asList(BpelConstants.BPEL_2_ACTIVITIES)); 965 966 967 public boolean evaluate(Object arg) { 968 return evaluate((Node ) arg); 969 } 970 971 static boolean evaluate(Node node) { 972 return node.getNodeType() == Node.ELEMENT_NODE 974 && BpelConstants.NS_BPWS.equals(node.getNamespaceURI()) 976 && activityNames.contains(node.getLocalName()); 978 } 979 } 980 } 981 | Popular Tags |