/* * 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.tuscany.sca.implementation.bpel.ode; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; import javax.wsdl.Definition; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ode.bpel.compiler.BpelC; import org.apache.ode.bpel.evt.BpelEvent.TYPE; import org.apache.ode.bpel.iapi.Endpoint; import org.apache.ode.bpel.iapi.EndpointReference; import org.apache.ode.bpel.iapi.ProcessConf; import org.apache.ode.bpel.iapi.ProcessState; import org.apache.tuscany.sca.assembly.Base; import org.apache.tuscany.sca.assembly.ComponentProperty; import org.apache.tuscany.sca.assembly.ComponentReference; import org.apache.tuscany.sca.assembly.ComponentService; import org.apache.tuscany.sca.assembly.Reference; import org.apache.tuscany.sca.databinding.SimpleTypeMapper; import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; import org.apache.tuscany.sca.implementation.bpel.BPELImplementation; import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * A Tuscany implementation of the ODE Process Conf * * @version $Rev$ $Date$ */ public class TuscanyProcessConfImpl implements ProcessConf { private final Log __log = LogFactory.getLog(getClass()); private BPELImplementation implementation; private RuntimeComponent component; private Map<String, Endpoint> invokeEndpoints = null; private Map<String, Endpoint> provideEndpoints = null; private Map<QName, Node> properties = null; private ProcessState processState; private Date deployDate; private File theBPELFile; // Marks whether the BPEL file was rewritten (eg for initializer statements) private boolean rewritten = false; private final SimpleTypeMapper mapper = new SimpleTypeMapperImpl(); private final String TUSCANY_NAMESPACE = Base.SCA11_TUSCANY_NS; /** * Constructor for the ProcessConf implementation * @param theImplementation the BPEL implementation for which this is the ProcessConf * @param component - the SCA component which uses the implementation */ public TuscanyProcessConfImpl( BPELImplementation theImplementation, RuntimeComponent component ) { //System.out.println("New TuscanyProcessConfImpl..."); this.implementation = theImplementation; this.component = component; processState = ProcessState.ACTIVE; deployDate = new Date(); // Compile the process compile( getBPELFile() ); } // end TuscanyProcessConfImpl constructor public void stop() { // If the BPEL file was rewritten, destroy the rewritten version of it so that // it is not used again. Also delete the related compiled cbp file if( rewritten ) { try { String cbpName = theBPELFile.getCanonicalPath(); // Remove the "bpel_tmp" suffix and add "cbp" if ( cbpName.endsWith("bpel_tmp") ) { cbpName = cbpName.substring( 0, cbpName.length() - 8) + "cbp"; File cbpFile = new File( cbpName ); if ( cbpFile.exists() ) cbpFile.delete(); } // end if } catch (Exception e ) { // Do nothing with an exception } // end try theBPELFile.delete(); } // end if } // end method stop /** * Returns the URI for the directory containing the BPEL process */ public URI getBaseURI() { //System.out.println("getBaseURI called"); File theDir = getDirectory(); return theDir.toURI(); } /** * Returns a String containing the (local) name of the file containing the BPEL process */ public String getBpelDocument() { //System.out.println("getBPELDocument called"); try { String location = this.implementation.getProcessDefinition().getLocation(); URI locationURI = new URI(null, location, null); File processFile = new File(locationURI); return getRelativePath( getDirectory(), processFile); } catch (Exception e) { if(__log.isWarnEnabled()) { __log.warn("Unable to resolve relative path of BPEL process" + implementation.getProcessDefinition().getLocation(), e ); } return null; } // end try } // end getBpelDocument /** * Returns an InputStream containing the Compiled BPEL Process (CBP) */ public InputStream getCBPInputStream() { //System.out.println("getCBPInputStream called"); File cbpFile = getCBPFile(); if( cbpFile == null ) return null; if( cbpFile.exists() ) { // Create an InputStream from the cbp file... try { return new FileInputStream( cbpFile ); } catch ( Exception e ) { if(__log.isDebugEnabled()) { __log.debug("Unable to open the cbp file for BPEL process: " + implementation.getProcessDefinition().getName(), e); } } // end try } else { // Cannot find the cbp file if(__log.isWarnEnabled()){ __log.warn("Cannot find the cbp file for process: " + implementation.getProcessDefinition().getName()); } } // end if // TODO - need better exception handling if we can't open the cbp file for any reason return null; } // end getCBPInputStream /** * Gets the File object for the CBP file for this BPEL Process * @return - the File object for the CBP file */ private File getCBPFile() { // Find the CBP file - it has the same name as the BPEL process and lives in the same // directory as the process file String cbpFileName = null; try { String fileName = getRelativePath( getDirectory(), getBPELFile() ); cbpFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".cbp"; } catch (Exception e ) { // IOException trying to fetch the BPEL file name if(__log.isDebugEnabled()) { __log.debug("Unable to calculate the file name for BPEL process: " + implementation.getProcessDefinition().getName(), e); return null; } // end if } // end try File cbpFile = new File( getDirectory(), cbpFileName ); return cbpFile; } // end getCBPFile /** * Return the WSDL Definition for a given PortType * @param portTypeName - the QName of the PortType */ public Definition getDefinitionForPortType( QName portTypeName ) { //System.out.println("getDefinitionForPortType called for portType: " + portTypeName ); // Find the named PortType in the list of WSDL interfaces associated with this BPEL Process Collection<WSDLInterface> theInterfaces = implementation.getProcessDefinition().getInterfaces(); for( WSDLInterface wsdlInterface : theInterfaces ) { if ( wsdlInterface.getPortType().getQName().equals( portTypeName ) ) { // Extract and return the Definition associated with the WSDLDefinition... return wsdlInterface.getWsdlDefinition().getDefinition(); } // end if } // end for return null; } // end getDefinitionforPortType /** * Returns a WSDL Definition for a given Service QName * * 22/05/2008 - it is very unclear what this service QName is really meant to be. * From the handling of the deploy.xml file by the current ODE code, it seems that the key link * is from the Service QName to the PartnerLink name (done in the deploy.xml file). * * The curious part about this is that the QName for the service is ONLY defined in deploy.xml file * and does not appear to relate to anything else, except for the QName of the PartnerLink * * The PartnerLink name is the same as the name of the SCA service (or reference) which in turn points * at the PartnerLinkType which in turn points at an (WSDL) interface definition. */ public Definition getDefinitionForService(QName serviceQName ) { //System.out.println("getDefinitionForService called for Service: " + serviceQName ); if(__log.isDebugEnabled()){ __log.debug("getDefinitionforService called for service: " + serviceQName ); } // TODO Auto-generated method stub return null; } /** * Returns the date of deployment of the process * - for SCA returns the date at which this object was created */ public Date getDeployDate() { //System.out.println("getDeployDate called"); return deployDate; } /** * Returns userid of deployer * - always "SCA Tuscany" for Tuscany... */ public String getDeployer() { //System.out.println("getDeployer called"); return "SCA Tuscany"; } // end getDeployer /** * Returns a list of the files in the directory containing the BPEL Process */ public List<File> getFiles() { //System.out.println("getFiles called"); File theDir = getDirectory(); List<File> theFiles = Arrays.asList( (File[]) theDir.listFiles() ); // TODO recurse into subdirectories return theFiles; } // end getFiles /** * Returns a Map containing all the "invoke endpoints" - for which read "SCA references" * The map is keyed by partnerLink name and holds Endpoint objects * 0..1 multiplicity references are not included in the returned Map (it is as if the reference is not there...) * TODO deal with multiplicity 0..n and 1..n * TODO deal with service callbacks on bidirectional services */ public Map<String, Endpoint> getInvokeEndpoints() { if( invokeEndpoints == null ) { invokeEndpoints = new HashMap<String, Endpoint>(); // Get a collection of the component references - note that this includes "pseudo-references" for any // services that have a callback interface List<ComponentReference> theReferences = component.getReferences(); //List<Reference> theReferences = implementation.getReferences(); // Create an endpoint for each reference, using the reference name combined with // http://tuscany.apache.org to make a QName // Note that the key used for this put operation MUST be the name of one of the partnerLinks of the // BPEL process. The SCA reference MAY have an alias for the name (can be given using the sca-bpel:reference // element, if present) and this alias must not be used for( Reference reference : theReferences ) { String partnerlinkName = implementation.getReferencePartnerlinkName( reference.getName() ); // Check that there is at least 1 configured SCA endpointReference for the reference, since it is // possible for 0..1 multiplicity references to have no SCA endpointReferences configured List<org.apache.tuscany.sca.assembly.EndpointReference> eprs = reference.getEndpointReferences(); String eprCount = Integer.toString( eprs.size() ); invokeEndpoints.put( partnerlinkName, new Endpoint( new QName( TUSCANY_NAMESPACE, reference.getName() ), eprCount)); } // end for } // end if return invokeEndpoints; } // end getInvokeEndpoints /** * Returns the name of the directory containing the BPEL files */ public String getPackage() { //System.out.println("getPackage called"); File theDir = getDirectory(); return theDir.getName(); } // end getPackage /** * Return the BPEL Process ID - which is the Process QName appended "-versionnumber" */ public QName getProcessId() { //System.out.println("getProcessId called"); QName processType = getType(); QName processID = new QName( processType.getNamespaceURI(), processType.getLocalPart() + "-" + getVersion() ); return processID; } // end getProcessID /** * TODO - What are properties? */ public Map<QName, Node> getProperties() { //System.out.println("getProperties called"); if ( properties == null ) { properties = new HashMap<QName, Node>(); } // end if return properties; } // end getProperties /** * Returns a Map containing all the "provide endpoints" - for which read "SCA services" * The map is keyed by partnerLink name and holds Endpoint objects * * TODO deal with reference callbacks on bidirectional references */ public Map<String, Endpoint> getProvideEndpoints() { //System.out.println("getProvideEndpoints called"); if( provideEndpoints == null ) { provideEndpoints = new HashMap<String, Endpoint>(); String componentURI = component.getURI(); // Get a collection of the services - note that the Component services include additional // "pseudo-services" for each reference that has a callback... List<ComponentService> theServices = component.getServices(); // Create an endpoint for each service, using the service name combined with // http://tuscany.apache.org to make a QName // Note that the key used for this put operation MUST be the name of one of the partnerLinks of the // BPEL process. The SCA service MAY have an alias for the name (can be given using the sca-bpel:service // element, if present) and this alias must not be used for( ComponentService service : theServices ) { String partnerlinkName = implementation.getServicePartnerlinkName( service.getName() ); // MJE 14/07/2009 - added componentURI to the service name to get unique service name provideEndpoints.put( partnerlinkName, new Endpoint( new QName( TUSCANY_NAMESPACE, componentURI + service.getName() ), "ServicePort")); } // end for } // end if return provideEndpoints; } // end getProvideEndpoints /** * Return the process state */ public ProcessState getState() { //System.out.println("getState called"); return processState; } /** * Returns the QName of the BPEL process */ public QName getType() { //System.out.println("getType called"); return implementation.getProcess(); } /** * Gets the process Version number * - current code does not have versions for BPEL processes and always returns "1" */ public long getVersion() { //System.out.println("getVersion called"); return 1; } /** * Returns true if the supplied event type is enabled for any of the scopes in the provided * List. These events are "ODE Execution Events" and there is a definition of them on this * page: http://ode.apache.org/user-guide.html#UserGuide-ProcessDeployment * * Tuscany currently uses: * - instanceLifecycle events in order to establish the relationship of MessageExchange objects * to the BPEL Process instances * @param scopeNames - list of BPEL process Scope names * @param type - the event type */ public boolean isEventEnabled(List<String> scopeNames, TYPE type) { if( type == TYPE.dataHandling ) return false; if( type == TYPE.activityLifecycle ) return false; if( type == TYPE.scopeHandling ) return true; if( type == TYPE.instanceLifecycle ) return true; if( type == TYPE.correlation ) return true; return false; } // end isEventEnabled /** * Returns whether the process is persisted in the store * * Returns false for SCA configuration * - returning true causes problems in communicating with the BPEL process */ public boolean isTransient() { return false; } // end isTransient /** * Compiles a BPEL process file into a compiled form CBP file in the main directory * (ie same directory as the BPEL process file) * @param bpelFile - the BPEL process file */ private void compile( File bpelFile ) { // Set up the compiler BpelC compiler = BpelC.newBpelCompiler(); // Provide a null set of initial properties for now Map<QName, Node> processProps = new HashMap<QName, Node>(); Map<String, Object> compileProps = new HashMap<String, Object>(); compileProps.put( BpelC.PROCESS_CUSTOM_PROPERTIES, processProps ); compiler.setCompileProperties( compileProps ); compiler.setBaseDirectory( getDirectory() ); // Inject any property values bpelFile = injectPropertyValues( bpelFile ); // Run the compiler and generate the CBP file into the given directory try { compiler.compile( bpelFile ); } catch (IOException e) { if(__log.isDebugEnabled()) { __log.debug("Compile error in " + bpelFile, e); } // TODO - need better exception handling here } // end try } // end compile /** * Adds the values for SCA declared properties to the BPEL process. * The values for the properties are held in the SCA RuntimeComponent supplied to this * TuscanyProcessConfImpl. * The properties map to <variable/> declarations in the BPEL process that are specifically * marked with @sca-bpel:property="yes" * @param bpelFile the file containing the BPEL process * @return the (updated) file containing the BPEL process */ private File injectPropertyValues( File bpelFile ) { // Get the properties List<ComponentProperty> properties = component.getProperties(); // If there are no properties, we're done! if( properties.size() == 0 ) return bpelFile; Document bpelDOM = readDOMFromProcess( bpelFile ); for( ComponentProperty property : properties ) { //System.out.println("BPEL: Property - name = " + property.getName() ); insertSCAPropertyInitializer( bpelDOM, property ); } // end for File bpelFile2 = writeProcessFromDOM( bpelDOM, getTransformedBPELFile( bpelFile) ); if( bpelFile2 != null ) { theBPELFile = bpelFile2; rewritten = true; return bpelFile2; } // end if return bpelFile; } // end injectPropertyValues /** * Insert an initializer which supplies the value of an SCA property as specified by the * SCA Component using the BPEL process * @param bpelDOM - a DOM model representation of the BPEL process * @param property - an SCA ComponentProperty element for the property * This DOM model is updated, with an initializer being added for the BPEL variable * corresponding to the SCA property */ private void insertSCAPropertyInitializer( Document bpelDOM, ComponentProperty property ) { // Only insert a Property initializer where there is a value for the Property if( property.getValue() == null ) return; Element insertionElement = findInitializerInsertionPoint( bpelDOM ); if( insertionElement == null ) return; Element initializer = getInitializerSequence( bpelDOM, property ); if( initializer == null ) return; // Insert the initializer sequence as the next sibling element of the insertion point Element parent = (Element)insertionElement.getParentNode(); // Get the next sibling element, if there is one Node sibling = insertionElement.getNextSibling(); while( sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE ) { sibling = sibling.getNextSibling(); } // end while // Either insert at the end or before the next element if ( sibling == null ) { parent.appendChild( initializer ); } else { parent.insertBefore( initializer, sibling ); } // end if } // end insertSCAPropertyInitializer /** * Gets the variable initializer DOM sequence for a given property, in the context of a supplied * DOM model of the BPEL process * @param bpelDOM - DOM representation of the BPEL process * @param property - SCA Property which relates to one of the variables in the BPEL process * @return - a DOM model representation of the XML statements required to initialize the * BPEL variable with the value of the SCA property. */ private Element getInitializerSequence( Document bpelDOM, ComponentProperty property ) { // For an XML simple type (string, int, etc), the BPEL initializer sequence is: // <assign><copy><from><literal>value</literal></from><to variable="variableName"/></copy></assign> QName type = property.getXSDType(); if( type != null ) { if( mapper.isSimpleXSDType( type ) ) { // Simple types String NS_URI = bpelDOM.getDocumentElement().getNamespaceURI(); String valueText = getPropertyValueText( property.getValue() ); Element literalElement = bpelDOM.createElementNS(NS_URI, "literal"); literalElement.setTextContent(valueText); Element fromElement = bpelDOM.createElementNS(NS_URI, "from"); fromElement.appendChild(literalElement); Element toElement = bpelDOM.createElementNS(NS_URI, "to"); Attr variableAttribute = bpelDOM.createAttribute("variable"); variableAttribute.setValue( property.getName() ); toElement.setAttributeNode( variableAttribute ); Element copyElement = bpelDOM.createElementNS(NS_URI, "copy"); copyElement.appendChild(fromElement); copyElement.appendChild(toElement); Element assignElement = bpelDOM.createElementNS(NS_URI, "assign"); assignElement.appendChild(copyElement); return assignElement; } // end if // TODO Deal with Properties which have a non-simple type } else { // TODO Deal with Properties which have an element as the type } // end if return null; } // end method getInitializerSequence /** * Gets the text value of a property that is a simple type * @param propValue - the SCA Property value * @return - the text content of the Property value, as a String */ private String getPropertyValueText( Object propValue ) { String text = null; if( propValue instanceof Document ) { Element docElement = ((Document)propValue).getDocumentElement(); if( docElement != null ){ Element valueElement = (Element)docElement.getFirstChild(); if( valueElement != null ) { text = valueElement.getTextContent(); } // end if } // end if } // end if return text; } // end method getPropertyValueText private Element findInitializerInsertionPoint( Document bpelDOM ) { // The concept is to find the first Activity child element of the BPEL process document Element docElement = bpelDOM.getDocumentElement(); NodeList elements = docElement.getElementsByTagName("*"); Element element; for ( int i = 0 ; i < elements.getLength() ; i++ ) { element = (Element)elements.item(i); if( isInsertableActivityElement( element ) ) { return element; } // end if } // end for return null; } // end method findInitializerInsertionPoint /** * A WS-BPEL activity can be any of the following: * <receive> * <reply> * <invoke> * <assign> * <throw> * <exit> * <wait> * <empty> * <sequence> * <if> * <while> * <repeatUntil> * <forEach> * <pick> * <flow> * <scope> * <compensate> * <compensateScope> * <rethrow> * <validate> * <extensionActivity> * A WS-BPEL start activity is a <receive> or <pick> with @create_instance="yes" */ private static String SEQUENCE_ELEMENT = "sequence"; private static String REPLY_ELEMENT = "reply"; private static String INVOKE_ELEMENT = "invoke"; private static String ASSIGN_ELEMENT = "assign"; private static String PICK_ELEMENT = "pick"; private static String RECEIVE_ELEMENT = "receive"; private static String FLOW_ELEMENT = "flow"; private static String SCOPE_ELEMENT = "scope"; /** * Determine if an Element is a BPEL start activity element which can have an Assign * inserted following it * @param element - a DOM Element containing the BPEL activity * @return - true if the Element is a BPEL Activity element, false otherwise */ private boolean isInsertableActivityElement( Element element ) { String name = element.getTagName(); // For the present, only <receive/> and <pick/> elements with create_instance="yes" count // if( SEQUENCE_ELEMENT.equalsIgnoreCase(name) ) return true; String start = element.getAttribute("createInstance"); if( start == null ) return false; if( !"yes".equals(start) ) return false; if( RECEIVE_ELEMENT.equalsIgnoreCase(name) ) return true; if( PICK_ELEMENT.equalsIgnoreCase(name) ) return true; return false; } // end method isActivityElement /** * Reads a BPEL Process file into a DOM Document structure * @param bpelFile - a File object referencing the BPEL process document * @return - a DOM Document structure representing the same BPEL process */ private Document readDOMFromProcess( File bpelFile ) { try { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); docFactory.setXIncludeAware(true); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document bpelDOM = docBuilder.parse( bpelFile ); return bpelDOM; } catch (Exception e) { return null; } // end try } // end method /** * Writes a BPEL Process file from a DOM Document structure representing the Process * @param bpelDOM - the DOM Document representation of the BPEL process * @param file - a File object to which the BPEL Process is to be written * @return */ private File writeProcessFromDOM( Document bpelDOM, File file ) { try { // Prepare the DOM document for writing Source source = new DOMSource( bpelDOM ); // Prepare the output file Result result = new StreamResult(file); // Write the DOM document to the file Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.transform(source, result); } catch (TransformerConfigurationException e) { } catch (TransformerException e) { return null; } return file; } // end writeProcessFromDOM private File getTransformedBPELFile( File bpelFile ) { String name = bpelFile.getName(); File parent = bpelFile.getParentFile(); File bpelFile2 = null; try { bpelFile2 = File.createTempFile(name, ".bpel_tmp", parent); } catch (Exception e ){ } // end try return bpelFile2; } // end getTransformedBPELFile /** * Gets the directory containing the BPEL process * @return */ private File getDirectory() { File theDir = getBPELFile().getParentFile(); return theDir; } // end getDirectory /** * Gets the File containing the BPEL process definition * @return - the File object containing the BPEL process */ private File getBPELFile() { if( theBPELFile != null ) return theBPELFile; try { String location = this.implementation.getProcessDefinition().getLocation(); URI locationURI; if (location.indexOf('%') != -1) { locationURI = URI.create(location); } else { locationURI = new URI(null, location, null); } File theProcess = new File(locationURI); theBPELFile = theProcess; return theProcess; } catch( Exception e ) { if(__log.isDebugEnabled()) { __log.debug("Exception converting BPEL file URL to an URI: " + e ); } } // end try return null; } // end getBPELFile /** * Gets the relative path of a file against a directory in its hierarchy * @param base - the base directory * @param path - the file * @return * @throws IOException */ private String getRelativePath(File base, File path) throws IOException { String basePath = base.getCanonicalPath(); String filePath = path.getCanonicalPath(); if (!filePath.startsWith(basePath)) { throw new IOException("Invalid relative path: base=" + base + " path=" + path); } String relative = filePath.substring(basePath.length()); if (relative.startsWith(File.separator)) { relative = relative.substring(1); } return relative; } // end getRelativePath //----------------------------------------------------------------------------- // other public APIs which ProcessConfImpl displays which are not in ProcessConf interface public List<String> getMexInterceptors(QName processId) { // System.out.println("getMexInterceptors for processID: " + processId ); return null; } public void setTransient(boolean t) { // System.out.println("setTransient called with boolean: " + t ); } public List<Element> getExtensionElement(QName arg0) { return Collections.emptyList(); } // end of other public APIs //----------------------------------------------------------------------------- /** * Get the size in bytes of the CBP file * @return - this size in bytes of the CBP file, 0 if the file cannot be found */ public long getCBPFileSize() { File cbpFile = getCBPFile(); if( cbpFile == null ) return 0; return cbpFile.length(); } // end getCBPFileSize private final Set<CLEANUP_CATEGORY> successCategories = EnumSet.noneOf(CLEANUP_CATEGORY.class); private final Set<CLEANUP_CATEGORY> failureCategories = EnumSet.noneOf(CLEANUP_CATEGORY.class); public Set<CLEANUP_CATEGORY> getCleanupCategories(boolean instanceSucceeded) { if( instanceSucceeded ) return successCategories; else return failureCategories; } private final Map<String, String> emptyPropertyMap = new Hashtable<String, String>(); public Map<String, String> getEndpointProperties(EndpointReference epr) { return emptyPropertyMap; } private final Map<QName, Node> emptyProcessProperties = new Hashtable<QName, Node>(); public Map<QName, Node> getProcessProperties() { return emptyProcessProperties; } public boolean isCleanupCategoryEnabled(boolean instanceSucceeded, CLEANUP_CATEGORY category) { // TODO Currently returns false - should this be changed for some categories? return false; } public boolean isSharedService(QName serviceName) { // Tuscany does not share the service return false; } } // end class TuscanyProcessConfImpl