/* * 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.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.net.URI; import java.util.List; import javax.xml.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tuscany.sca.assembly.ComponentType; import org.apache.tuscany.sca.assembly.Reference; import org.apache.tuscany.sca.assembly.Service; import org.apache.tuscany.sca.implementation.bpel.BPELImplementation; /** * A class that handles the deploy.xml file required for each BPEL process by the ODE runtime * @author Mike Edwards * * An explanation of the structure of the ODE deploy file: * * <deploy xmlns="http://www.apache.org/ode/schemas/dd/2007/03" * xmlns:tns="http://helloworld" * xmlns:tus="http://tuscany.apache.org/xmlns/sca/1.1"> * * <process name="tns:HelloWorld"> * <active>true</active> * <provide partnerLink="helloPartnerLink"> * <service name="tus:helloPartnerLink" port="HelloWorld"/> * </provide> * <invoke partnerLink="greetingsPartnerLink"> * <service name="tus:greetingsPartnerLink" port="Greetings"/> * </invoke> * </process> * </deploy> * * For SCA purposes: * * a) Each partner link in the BPEL process is declared using either a <provide.../> * (for a service) or using a <invoke.../> (for a reference). * * b) Each <provide/> and <invoke/> must use the partnerLink name, as declared in the * BPEL process. * * c) The <provide/> and <invoke/> elements each have a single child <service/> element. * The <service/> elements have name and port attributes. The NAME attribute MUST be set * to the same name as the partnerLink and MUST be prefixed by a prefix which references * the namespace "http://tuscany.apache.org" ("tus" in the example above). * The port attribute can be set to any name (it must be present but it is not actually * used for anything significant). * * When SCA loads a BPEL process to the ODE server, this file is read by the ODE server to * characterize the process. When SCA interacts with ODE at later points - either when a * service is being invoked or the process invokes a reference - it is the service @name * attribute that identifies the service or reference involved. * * @version */ public class BPELODEDeployFile { private final Log __log = LogFactory.getLog(getClass()); static final String DEPLOY_ELEMENT_START = "<deploy xmlns=\"http://www.apache.org/ode/schemas/dd/2007/03\""; static final String DEPLOY_ENDELEMENT = "</deploy>"; static final String PROCESS_NAMESPACE_DECL = "xmlns:tns="; static final String SERVICE_NAMESPACE = "xmlns:tus=\"http://tuscany.apache.org\""; static final String PROCESS_ELEMENT_START = "<process name=\"tns:"; static final String PROCESS_ELEMENT_END = "\">"; static final String PROCESS_ENDELEMENT = "</process>"; static final String ACTIVE_ELEMENT = "<active>true</active>"; static final String PROVIDE_ELEMENT_START = "<provide partnerLink=\""; static final String PROVIDE_ELEMENT_END = "\">"; static final String PROVIDE_ENDELEMENT = "</provide>"; static final String SERVICE_ELEMENT_START = "<service name=\"tus:"; static final String SERVICE_ELEMENT_PORT = "\" port=\""; static final String SERVICE_ELEMENT_END = "Port\"/>"; static final String INVOKE_ELEMENT_START = "<invoke partnerLink=\""; static final String INVOKE_ELEMENT_END = "\">"; static final String INVOKE_ENDELEMENT = "</invoke>"; static final String DEPLOY_FILENAME = "deploy.xml"; private BPELImplementation implementation; /** * Constructor - requires a BPELImplementation as a parameter * The ODE deploy.xml file is for this supplied BPELImplementation * @param theImplementation */ public BPELODEDeployFile( BPELImplementation theImplementation ) { implementation = theImplementation; } // end BPELODEDeployFile constructor /** * Writes the deploy file into the same directory as the BPEL process file, with the name * "deploy.xml" */ public void writeDeployfile() throws IOException { File theDirectory = getDirectory(); File deployFile = new File( theDirectory, DEPLOY_FILENAME ); new FileOutputStream( deployFile ); //if( !deployFile.canWrite() ) throw new IOException( "Unable to write to deploy file" + // deployFile.getPath() ); // Create a stream for the data and write the data to the file PrintStream theStream = new PrintStream( new FileOutputStream( deployFile ) ); try { constructDeployXML( theStream ); if( theStream.checkError() ) throw new IOException(); } catch (Exception e) { throw new IOException( "Unable to write data to deploy file" + deployFile.getPath() ); } finally { theStream.close(); } // end try } // end writeDeployFile /** * Creates the deploy.xml data and writes it to a supplied PrintStream * @param stream */ public void constructDeployXML( PrintStream stream ) { // <deploy + namespace... stream.println( DEPLOY_ELEMENT_START ); // namespace of the BPEL process QName process = implementation.getProcess(); String processNamespace = process.getNamespaceURI(); stream.println( PROCESS_NAMESPACE_DECL + "\"" + processNamespace + "\"" ); // namespace for the service name elements stream.println( SERVICE_NAMESPACE + ">" ); // <process> element stream.println( PROCESS_ELEMENT_START + process.getLocalPart() + PROCESS_ELEMENT_END ); // <active/> element stream.println( ACTIVE_ELEMENT ); ComponentType componentType = implementation.getComponentType(); List<Service> theServices = componentType.getServices(); // Loop over the <provide/> elements - one per service for ( Service service : theServices ) { String serviceName = service.getName(); // Provide element... stream.println( PROVIDE_ELEMENT_START + serviceName + PROVIDE_ELEMENT_END ); // Child service element... stream.println( SERVICE_ELEMENT_START + serviceName + SERVICE_ELEMENT_PORT + serviceName + SERVICE_ELEMENT_END ); stream.println( PROVIDE_ENDELEMENT ); } // end for // Loop over the <invoke/> elements - one per reference List<Reference> theReferences = componentType.getReferences(); for ( Reference reference : theReferences ) { String referenceName = reference.getName(); stream.println( INVOKE_ELEMENT_START + referenceName + INVOKE_ELEMENT_END ); // Child service element... stream.println( SERVICE_ELEMENT_START + referenceName + SERVICE_ELEMENT_PORT + referenceName + SERVICE_ELEMENT_END ); stream.println( INVOKE_ENDELEMENT ); } // end for // </process> element stream.println( PROCESS_ENDELEMENT ); // </deploy> stream.println( DEPLOY_ENDELEMENT ); } // end constructDeployXML /** * 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() { 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); 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 } // end class BPELODEDeployFile