You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tuscany.apache.org by Matthieu Riou <ma...@offthelip.org> on 2008/05/19 20:23:20 UTC

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

On Mon, May 19, 2008 at 9:11 AM, Mike Edwards <
mike.edwards.inglenook@gmail.com> wrote:

> Folks,
>
> I am interested in getting rid of the need to have a physical deploy.xml
> file in the directory with a BPEL process file.
>
> Can I supply the same information to the ODE runtime through some other
> means, such as method parameters or some in-memory mechanism?
>

The short answer is: yes, you can. The long answer is... a bit longer :)


>
> For the SCA integration, the SCA runtime has all the information contained
> in the deploy.xml file, but in another form.  It would be great to relieve
> the developers from the need to create this file.
>

Let me explain a bit how that works. The ODE runtime doesn't know anything
about the file system, descriptors or even BPEL files. It just knows that
something is supposed to call it, passing an interface implementation
(ProcessConf [1]) that provides everything it needs (and a bit more
actually). It's so dumb that it doesn't even know which processes it should
know about, so every time the server is restarted, it expects to be called
again with the same process definition information.

Parrallely in ODE we have a process store that handles all the nitty gritty
details of knowing where is what in which version and remembering it. The
process store doesn't know about the runtime and the runtime doesn't know
about the store. The advantage is that, in theory, you could pick different
clustering models (one store / multiple servers, multiple stores / multiple
servers) depending on how you want things to be arranged. The other
advantage is that you can get rid of the store altogether if you have all
the necessary information.

When a new process is deployed (or undeployed, or retired, or ...), the
store just produces an event. Same thing when the whole server is restarted,
the store produces several events for each process the runtime should know
about. These events are just relayed by the Integration Layer that binds the
store and the runtime and implements external communication (all the
interfaces Luciano has implemented).

Getting back to Tuscany, what I'm thinking is that we should remove the
store (and its events) from the equation. Tuscany would just let the runtime
know when when a process is available by calling
BpelServer.register(ProcessConf), providing its own implementation of
ProcessConf. The current Tuscany integration layer already has a reference
to the BpelServer, so that's easy. The caveat is that in this case, Tuscany
will also need to compile the .bpel file to provide the CBP (Compiled
Business Process) but that's fairly painless (see
DeploymentUnitDir.compile(File) [2]).

The net advantage of this for Tuscany will be a much better integration and
much more control over the process lifecycle. So let me know what you think
and I can help with your ProcessConf implementation.

Cheers,
Matthieu

[1]
http://svn.apache.org/repos/asf/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java
[2]
http://svn.apache.org/repos/asf/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/DeploymentUnitDir.java


>
> Yours,  Mike Edwards
> Apache Tuscany team.
>

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Matthieu Riou <ma...@offthelip.org>.
On Fri, May 23, 2008 at 9:03 AM, Mike Edwards <
mike.edwards.inglenook@gmail.com> wrote:

> Matthieu Riou wrote:
>
>> What mike says. I should just add that picking the right process version
>> depending on what's already executing is handled by the runtime. The only
>> thing that it will need is to know what is the definition for all the
>> process versions that are still around (haven't been undeployed). You just
>> need to keep these artifacts around and feed them to the engine (by
>> calling
>> register) as long as they're needed.
>>
>> If you want, I can code the method that compiles the BPEL file if you give
>> me a signature that gets the file as parameter (I don't know how you would
>> look it up in the filesystem).
>>
>> Cheers,
>> Matthieu
>>
>>
>>
>>> Yours optimistically,
>>>
>>> Mike.
>>>
>>>  Matthieu,
>
> I'd appreciate it if you could pass your eyes over my implementation of a
> ProcessConf, inline below.
>
> There are a few questions that I have:
>
> 1) ProcessConfImpl from the ODE code has more public methods than are
> present in the ProcessConf interface.  What are they used for - and by which
> code?
>

Those are only used by the store implementation or by a test case for one of
them. You don't need to worry about those as you won't have a store
implementation.


>
> 2) What is getDefinitionforService(...) supposed to return?  The problem is
> over the interpretation of the name "Service" - what kind of service is
> this?  A service from the WSDL?  A service as listed in the deploy.xml file?
>  And what definition are we talking about - the definition of the Service in
> the WSDL file, or the definition of the portType at which the service
> points?
>

It returns the WSDL object model associated with a given WSDL service
qualified name. When something gets deployed, we scan all the WSDL documents
and associate them with the services they define. This method is basically
used by the engine to get the definition of the services that you defined in
the deploy.xml. It can then pass this definition on to the integration layer
when it wants a service to get activated.


>
> 3) What are Properties as returned by getProperties()?
>

We have a set of custom name/value properties that can be defined in the
deploy.xml that people can use to attribute some custom values to their
process definitions. This is mostly used in the management API so that a
graphical tool listing all process definitions could for example filter them
by department. Those are somewhat different to what SCA properties for BPEL
are, so I'm not sure what would be the best way to declare this in Tuscany.
Perhaps some additional property elements in the componentType definition?
In any case, it's not crucial for now.


>
> I'd appreciate any assistance you can give....
>

Looking through your code, it looks pretty good. We'll need better error
reporting on the compilation but I've seen you already have a todo tag here
so nothing to add. We'll also probably need versioning soon, it's a pretty
common in BPEL when you incrementally deploy new processes but for a first
implementation, we can definitely live with it.

Looks pretty nice overall, thanks a lot for your work!

Matthieu


>
> Yours,  Mike.
>
>
> /*
>  * 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.InputStream;
> import java.io.FileInputStream;
> import java.io.IOException;
> import java.net.URI;
> import java.net.URL;
> import java.util.Date;
> import java.util.List;
> import java.util.Collection;
> import java.util.Map;
> import java.util.HashMap;
> import java.util.Arrays;
>
> import javax.wsdl.Definition;
> import javax.wsdl.PortType;
> import javax.xml.namespace.QName;
>
> import org.apache.ode.bpel.evt.BpelEvent.TYPE;
> import org.apache.ode.bpel.iapi.Endpoint;
> import org.apache.ode.bpel.iapi.ProcessConf;
> import org.apache.ode.bpel.iapi.ProcessState;
> import org.apache.ode.bpel.compiler.BpelC;
> import org.w3c.dom.Node;
>
> import org.apache.tuscany.sca.implementation.bpel.BPELImplementation;
> import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
> import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
> import org.apache.tuscany.sca.assembly.Reference;
> import org.apache.tuscany.sca.assembly.Service;
>
> public class TuscanyProcessConfImpl implements ProcessConf {
>
>        private BPELImplementation implementation;
>        private Map<String, Endpoint> invokeEndpoints = null;
>        private Map<String, Endpoint> provideEndpoints = null;
>        private Map<QName, Node> properties = null;
>        private ProcessState processState;
>
>        private final String TUSCANY_NAMESPACE = "http://tuscany.apache.org
> ";
>
>        /**
>         * Constructor for the ProcessConf implementation
>         * @param theImplementation the BPEL implementation for which this
> is the ProcessConf
>         */
>        public TuscanyProcessConfImpl( BPELImplementation theImplementation
> ) {
>                this.implementation = theImplementation;
>
>                processState = ProcessState.ACTIVE;
>
>                // Compile the process
>                compile( getBPELFile() );
>        } // end TuscanyProcessConfImpl constructor
>
>        /**
>         * Returns the URI for the directory containing the BPEL process
>         */
>        public URI getBaseURI() {
>                File theDir = getDirectory();
>                return theDir.toURI();
>        }
>
>        /**
>         * Returns a String containing the (local) name of the file
> containing the BPEL process
>         */
>        public String getBpelDocument() {
>                URL processURL =
> implementation.getProcessDefinition().getLocation();
>                try {
>                    return getRelativePath( getDirectory(), new File(
> processURL.toURI() ));
>                } catch (Exception e) {
>                        System.out.println( "Unable to resolve relative path
> of BPEL process" + processURL );
>                        return null;
>                } // end try
>        } // end getBpelDocument
>
>        /**
>         * Returns an InputStream containing the Compiled BPEL Process (CBP)
>         */
>        public InputStream getCBPInputStream() {
>                // 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 =
> implementation.getProcessDefinition().getName().getLocalPart() + ".cbp";
>                File cbpFile = new File( getDirectory(), cbpFileName );
>                if( cbpFile.exists() ) {
>                        // Create an InputStream from the cbp file...
>                        try {
>                            return new FileInputStream( cbpFile );
>                        } catch ( Exception e ) {
>                                System.out.println("Unable to open the cbp
> file for BPEL process: " +
>
>  implementation.getProcessDefinition().getName());
>                        } // end try
>                } else {
>                        // Cannot find the cbp file
>                        System.out.println("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
>
>        /**
>         * Return the WSDL Definition for a given PortType
>         * @param portTypeName - the QName of the PortType
>         */
>        public Definition getDefinitionForPortType( QName 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;
>        }
>
>        /**
>         * 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 );
>                // TODO Auto-generated method stub
>                return null;
>        }
>
>        /**
>         * Returns the date of deployment of the process
>         * - for SCA returns the current time
>         */
>        public Date getDeployDate() {
>                return new Date();
>        }
>
>        /**
>         * Returns userid of deployer
>         * - always "SCA Tuscany" for Tuscany...
>         */
>        public String getDeployer() {
>                return "SCA Tuscany";
>        }
>
>        /**
>         * Returns a list of the files in the directory containing the BPEL
> Process
>         */
>        public List<File> getFiles() {
>                File theDir = getDirectory();
>                List<File> theFiles = Arrays.asList( (File[])
> theDir.listFiles() );
>                // TODO recurse into subdirectories
>                return theFiles;
>        }
>
>        /**
>         * Returns a Map containing all the "invoke endpoints" - for which
> read "SCA references"
>         * The map is keyed by partnerLink name and holds Endpoint objects
>         *
>         * TODO deal with service callbacks on bidirectional services
>         */
>        public Map<String, Endpoint> getInvokeEndpoints() {
>                if( invokeEndpoints == null ) {
>                        Map<String, Endpoint> invokeEndpoints = new
> HashMap<String, Endpoint>();
>                        // Get a collection of the references
>                        List<Reference> theReferences =
> implementation.getReferences();
>                        // Create an endpoint for each reference, using the
> reference name as the "service"
>                        // name, combined with http://tuscany.apache.org to
> make a QName
>                        for( Reference reference : theReferences ) {
>                                invokeEndpoints.put( reference.getName(),
>                                                new Endpoint( new QName(
> TUSCANY_NAMESPACE, reference.getName() ), "ReferencePort"));
>                        } // end for
>                } // end if
>                return invokeEndpoints;
>        } // end getInvokeEndpoints
>
>        /**
>         * Returns the name of the directory containing the BPEL files
>         */
>        public String getPackage() {
>                File theDir = getDirectory();
>                return theDir.getName();
>        } // end getPackage
>
>        /**
>         * Return the BPEL Process ID - which is the same as the Process
> QName
>         */
>        public QName getProcessId() {
>                return getType();
>        } // end getProcessID
>
>        /**
>         * TODO - What are properties?
>         */
>        public Map<QName, Node> getProperties() {
>                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() {
>                if( provideEndpoints == null ) {
>                        provideEndpoints = new HashMap<String, Endpoint>();
>                        // Get a collection of the references
>                        List<Service> theServices =
> implementation.getServices();
>                        // Create an endpoint for each reference, using the
> reference name as the "service"
>                        // name, combined with http://tuscany.apache.org to
> make a QName
>                        for( Service service : theServices ) {
>                                provideEndpoints.put( service.getName(),
>                                                new Endpoint( new QName(
> TUSCANY_NAMESPACE, service.getName() ), "ServicePort"));
>                        } // end for
>                } // end if
>                return provideEndpoints;
>        } // end getProvideEndpoints
>
>        /**
>         * Return the process state
>         */
>        public ProcessState getState() {
>                return processState;
>        }
>
>        /**
>         * Returns the QName of the BPEL process
>         */
>        public QName getType() {
>                return implementation.getProcess();
>        }
>
>        /**
>         * Gets the process Version number
>         * - current code does not have versions for BPEL prcesses
>         */
>        public long getVersion() {
>                return 0;
>        }
>
>        /**
>         * Returns true if the supplied event type is enabled for any of the
> scopes in the provided
>         * List
>         * @param scopeNames - list of BPEL process Scope names
>         * @param type - the event type
>         */
>        public boolean isEventEnabled(List<String> scopeNames, TYPE type) {
>                // TODO - this will need an analysis of the content of the
> BPEL process
>                // TODO Auto-generated method stub
>                return false;
>        }
>
>        /**
>         * Returns whether the process is persisted in the store
>         *
>         * Returns true for SCA configuration as the BPEL process is in the
> Domain config
>         */
>        public boolean isTransient() {
>                return true;
>        } // 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() );
>
>        // Run the compiler and generate the CBP file into the given
> directory
>        try {
>            compiler.compile( bpelFile );
>        } catch (IOException e) {
>            System.out.println("Compile error in " + bpelFile + e);
>            // TODO - need better exception handling here
>        } // end try
>    } // end compile
>
>        /**
>         * 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() {
>                File theProcess = new File(
> implementation.getProcessDefinition().getURI() );
>                return theProcess;
>        } // 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
>
> } // end class TuscanyProcessConfImpl
>
>
>

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Matthieu Riou <ma...@offthelip.org>.
On Fri, May 23, 2008 at 9:03 AM, Mike Edwards <
mike.edwards.inglenook@gmail.com> wrote:

> Matthieu Riou wrote:
>
>> What mike says. I should just add that picking the right process version
>> depending on what's already executing is handled by the runtime. The only
>> thing that it will need is to know what is the definition for all the
>> process versions that are still around (haven't been undeployed). You just
>> need to keep these artifacts around and feed them to the engine (by
>> calling
>> register) as long as they're needed.
>>
>> If you want, I can code the method that compiles the BPEL file if you give
>> me a signature that gets the file as parameter (I don't know how you would
>> look it up in the filesystem).
>>
>> Cheers,
>> Matthieu
>>
>>
>>
>>> Yours optimistically,
>>>
>>> Mike.
>>>
>>>  Matthieu,
>
> I'd appreciate it if you could pass your eyes over my implementation of a
> ProcessConf, inline below.
>
> There are a few questions that I have:
>
> 1) ProcessConfImpl from the ODE code has more public methods than are
> present in the ProcessConf interface.  What are they used for - and by which
> code?
>

Those are only used by the store implementation or by a test case for one of
them. You don't need to worry about those as you won't have a store
implementation.


>
> 2) What is getDefinitionforService(...) supposed to return?  The problem is
> over the interpretation of the name "Service" - what kind of service is
> this?  A service from the WSDL?  A service as listed in the deploy.xml file?
>  And what definition are we talking about - the definition of the Service in
> the WSDL file, or the definition of the portType at which the service
> points?
>

It returns the WSDL object model associated with a given WSDL service
qualified name. When something gets deployed, we scan all the WSDL documents
and associate them with the services they define. This method is basically
used by the engine to get the definition of the services that you defined in
the deploy.xml. It can then pass this definition on to the integration layer
when it wants a service to get activated.


>
> 3) What are Properties as returned by getProperties()?
>

We have a set of custom name/value properties that can be defined in the
deploy.xml that people can use to attribute some custom values to their
process definitions. This is mostly used in the management API so that a
graphical tool listing all process definitions could for example filter them
by department. Those are somewhat different to what SCA properties for BPEL
are, so I'm not sure what would be the best way to declare this in Tuscany.
Perhaps some additional property elements in the componentType definition?
In any case, it's not crucial for now.


>
> I'd appreciate any assistance you can give....
>

Looking through your code, it looks pretty good. We'll need better error
reporting on the compilation but I've seen you already have a todo tag here
so nothing to add. We'll also probably need versioning soon, it's a pretty
common in BPEL when you incrementally deploy new processes but for a first
implementation, we can definitely live with it.

Looks pretty nice overall, thanks a lot for your work!

Matthieu


>
> Yours,  Mike.
>
>
> /*
>  * 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.InputStream;
> import java.io.FileInputStream;
> import java.io.IOException;
> import java.net.URI;
> import java.net.URL;
> import java.util.Date;
> import java.util.List;
> import java.util.Collection;
> import java.util.Map;
> import java.util.HashMap;
> import java.util.Arrays;
>
> import javax.wsdl.Definition;
> import javax.wsdl.PortType;
> import javax.xml.namespace.QName;
>
> import org.apache.ode.bpel.evt.BpelEvent.TYPE;
> import org.apache.ode.bpel.iapi.Endpoint;
> import org.apache.ode.bpel.iapi.ProcessConf;
> import org.apache.ode.bpel.iapi.ProcessState;
> import org.apache.ode.bpel.compiler.BpelC;
> import org.w3c.dom.Node;
>
> import org.apache.tuscany.sca.implementation.bpel.BPELImplementation;
> import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
> import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
> import org.apache.tuscany.sca.assembly.Reference;
> import org.apache.tuscany.sca.assembly.Service;
>
> public class TuscanyProcessConfImpl implements ProcessConf {
>
>        private BPELImplementation implementation;
>        private Map<String, Endpoint> invokeEndpoints = null;
>        private Map<String, Endpoint> provideEndpoints = null;
>        private Map<QName, Node> properties = null;
>        private ProcessState processState;
>
>        private final String TUSCANY_NAMESPACE = "http://tuscany.apache.org
> ";
>
>        /**
>         * Constructor for the ProcessConf implementation
>         * @param theImplementation the BPEL implementation for which this
> is the ProcessConf
>         */
>        public TuscanyProcessConfImpl( BPELImplementation theImplementation
> ) {
>                this.implementation = theImplementation;
>
>                processState = ProcessState.ACTIVE;
>
>                // Compile the process
>                compile( getBPELFile() );
>        } // end TuscanyProcessConfImpl constructor
>
>        /**
>         * Returns the URI for the directory containing the BPEL process
>         */
>        public URI getBaseURI() {
>                File theDir = getDirectory();
>                return theDir.toURI();
>        }
>
>        /**
>         * Returns a String containing the (local) name of the file
> containing the BPEL process
>         */
>        public String getBpelDocument() {
>                URL processURL =
> implementation.getProcessDefinition().getLocation();
>                try {
>                    return getRelativePath( getDirectory(), new File(
> processURL.toURI() ));
>                } catch (Exception e) {
>                        System.out.println( "Unable to resolve relative path
> of BPEL process" + processURL );
>                        return null;
>                } // end try
>        } // end getBpelDocument
>
>        /**
>         * Returns an InputStream containing the Compiled BPEL Process (CBP)
>         */
>        public InputStream getCBPInputStream() {
>                // 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 =
> implementation.getProcessDefinition().getName().getLocalPart() + ".cbp";
>                File cbpFile = new File( getDirectory(), cbpFileName );
>                if( cbpFile.exists() ) {
>                        // Create an InputStream from the cbp file...
>                        try {
>                            return new FileInputStream( cbpFile );
>                        } catch ( Exception e ) {
>                                System.out.println("Unable to open the cbp
> file for BPEL process: " +
>
>  implementation.getProcessDefinition().getName());
>                        } // end try
>                } else {
>                        // Cannot find the cbp file
>                        System.out.println("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
>
>        /**
>         * Return the WSDL Definition for a given PortType
>         * @param portTypeName - the QName of the PortType
>         */
>        public Definition getDefinitionForPortType( QName 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;
>        }
>
>        /**
>         * 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 );
>                // TODO Auto-generated method stub
>                return null;
>        }
>
>        /**
>         * Returns the date of deployment of the process
>         * - for SCA returns the current time
>         */
>        public Date getDeployDate() {
>                return new Date();
>        }
>
>        /**
>         * Returns userid of deployer
>         * - always "SCA Tuscany" for Tuscany...
>         */
>        public String getDeployer() {
>                return "SCA Tuscany";
>        }
>
>        /**
>         * Returns a list of the files in the directory containing the BPEL
> Process
>         */
>        public List<File> getFiles() {
>                File theDir = getDirectory();
>                List<File> theFiles = Arrays.asList( (File[])
> theDir.listFiles() );
>                // TODO recurse into subdirectories
>                return theFiles;
>        }
>
>        /**
>         * Returns a Map containing all the "invoke endpoints" - for which
> read "SCA references"
>         * The map is keyed by partnerLink name and holds Endpoint objects
>         *
>         * TODO deal with service callbacks on bidirectional services
>         */
>        public Map<String, Endpoint> getInvokeEndpoints() {
>                if( invokeEndpoints == null ) {
>                        Map<String, Endpoint> invokeEndpoints = new
> HashMap<String, Endpoint>();
>                        // Get a collection of the references
>                        List<Reference> theReferences =
> implementation.getReferences();
>                        // Create an endpoint for each reference, using the
> reference name as the "service"
>                        // name, combined with http://tuscany.apache.org to
> make a QName
>                        for( Reference reference : theReferences ) {
>                                invokeEndpoints.put( reference.getName(),
>                                                new Endpoint( new QName(
> TUSCANY_NAMESPACE, reference.getName() ), "ReferencePort"));
>                        } // end for
>                } // end if
>                return invokeEndpoints;
>        } // end getInvokeEndpoints
>
>        /**
>         * Returns the name of the directory containing the BPEL files
>         */
>        public String getPackage() {
>                File theDir = getDirectory();
>                return theDir.getName();
>        } // end getPackage
>
>        /**
>         * Return the BPEL Process ID - which is the same as the Process
> QName
>         */
>        public QName getProcessId() {
>                return getType();
>        } // end getProcessID
>
>        /**
>         * TODO - What are properties?
>         */
>        public Map<QName, Node> getProperties() {
>                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() {
>                if( provideEndpoints == null ) {
>                        provideEndpoints = new HashMap<String, Endpoint>();
>                        // Get a collection of the references
>                        List<Service> theServices =
> implementation.getServices();
>                        // Create an endpoint for each reference, using the
> reference name as the "service"
>                        // name, combined with http://tuscany.apache.org to
> make a QName
>                        for( Service service : theServices ) {
>                                provideEndpoints.put( service.getName(),
>                                                new Endpoint( new QName(
> TUSCANY_NAMESPACE, service.getName() ), "ServicePort"));
>                        } // end for
>                } // end if
>                return provideEndpoints;
>        } // end getProvideEndpoints
>
>        /**
>         * Return the process state
>         */
>        public ProcessState getState() {
>                return processState;
>        }
>
>        /**
>         * Returns the QName of the BPEL process
>         */
>        public QName getType() {
>                return implementation.getProcess();
>        }
>
>        /**
>         * Gets the process Version number
>         * - current code does not have versions for BPEL prcesses
>         */
>        public long getVersion() {
>                return 0;
>        }
>
>        /**
>         * Returns true if the supplied event type is enabled for any of the
> scopes in the provided
>         * List
>         * @param scopeNames - list of BPEL process Scope names
>         * @param type - the event type
>         */
>        public boolean isEventEnabled(List<String> scopeNames, TYPE type) {
>                // TODO - this will need an analysis of the content of the
> BPEL process
>                // TODO Auto-generated method stub
>                return false;
>        }
>
>        /**
>         * Returns whether the process is persisted in the store
>         *
>         * Returns true for SCA configuration as the BPEL process is in the
> Domain config
>         */
>        public boolean isTransient() {
>                return true;
>        } // 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() );
>
>        // Run the compiler and generate the CBP file into the given
> directory
>        try {
>            compiler.compile( bpelFile );
>        } catch (IOException e) {
>            System.out.println("Compile error in " + bpelFile + e);
>            // TODO - need better exception handling here
>        } // end try
>    } // end compile
>
>        /**
>         * 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() {
>                File theProcess = new File(
> implementation.getProcessDefinition().getURI() );
>                return theProcess;
>        } // 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
>
> } // end class TuscanyProcessConfImpl
>
>
>

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Mike Edwards <mi...@gmail.com>.
Matthieu Riou wrote:
> What mike says. I should just add that picking the right process version
> depending on what's already executing is handled by the runtime. The only
> thing that it will need is to know what is the definition for all the
> process versions that are still around (haven't been undeployed). You just
> need to keep these artifacts around and feed them to the engine (by calling
> register) as long as they're needed.
> 
> If you want, I can code the method that compiles the BPEL file if you give
> me a signature that gets the file as parameter (I don't know how you would
> look it up in the filesystem).
> 
> Cheers,
> Matthieu
> 
> 
>>
>> Yours optimistically,
>>
>> Mike.
>>
Matthieu,

I'd appreciate it if you could pass your eyes over my implementation of a ProcessConf, inline below.

There are a few questions that I have:

1) ProcessConfImpl from the ODE code has more public methods than are present in the ProcessConf 
interface.  What are they used for - and by which code?

2) What is getDefinitionforService(...) supposed to return?  The problem is over the interpretation 
of the name "Service" - what kind of service is this?  A service from the WSDL?  A service as listed 
in the deploy.xml file?  And what definition are we talking about - the definition of the Service in 
the WSDL file, or the definition of the portType at which the service points?

3) What are Properties as returned by getProperties()?

I'd appreciate any assistance you can give....

Yours,  Mike.


/*
  * 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.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;

import javax.wsdl.Definition;
import javax.wsdl.PortType;
import javax.xml.namespace.QName;

import org.apache.ode.bpel.evt.BpelEvent.TYPE;
import org.apache.ode.bpel.iapi.Endpoint;
import org.apache.ode.bpel.iapi.ProcessConf;
import org.apache.ode.bpel.iapi.ProcessState;
import org.apache.ode.bpel.compiler.BpelC;
import org.w3c.dom.Node;

import org.apache.tuscany.sca.implementation.bpel.BPELImplementation;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.Service;

public class TuscanyProcessConfImpl implements ProcessConf {
	
	private BPELImplementation implementation;
	private Map<String, Endpoint> invokeEndpoints = null;
	private Map<String, Endpoint> provideEndpoints = null;
	private Map<QName, Node> properties = null;
	private ProcessState processState;
	
	private final String TUSCANY_NAMESPACE = "http://tuscany.apache.org";
	
	/**
	 * Constructor for the ProcessConf implementation
	 * @param theImplementation the BPEL implementation for which this is the ProcessConf
	 */
	public TuscanyProcessConfImpl( BPELImplementation theImplementation ) {
		this.implementation = theImplementation;
		
		processState = ProcessState.ACTIVE;
		
		// Compile the process
		compile( getBPELFile() );
	} // end TuscanyProcessConfImpl constructor

	/**
	 * Returns the URI for the directory containing the BPEL process
	 */
	public URI getBaseURI() {
		File theDir = getDirectory();
		return theDir.toURI();
	}

	/**
	 * Returns a String containing the (local) name of the file containing the BPEL process
	 */
	public String getBpelDocument() {
		URL processURL = implementation.getProcessDefinition().getLocation();
		try {
		    return getRelativePath( getDirectory(), new File( processURL.toURI() ));
		} catch (Exception e) {
			System.out.println( "Unable to resolve relative path of BPEL process" + processURL );
			return null;
		} // end try
	} // end getBpelDocument

	/**
	 * Returns an InputStream containing the Compiled BPEL Process (CBP)
	 */
	public InputStream getCBPInputStream() {
		// 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 = implementation.getProcessDefinition().getName().getLocalPart() + ".cbp";
		File cbpFile = new File( getDirectory(), cbpFileName );
		if( cbpFile.exists() ) {
			// Create an InputStream from the cbp file...
			try {
			    return new FileInputStream( cbpFile );
			} catch ( Exception e ) {
				System.out.println("Unable to open the cbp file for BPEL process: " +
						implementation.getProcessDefinition().getName());
			} // end try
		} else {
			// Cannot find the cbp file
			System.out.println("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
	
	/**
	 * Return the WSDL Definition for a given PortType
	 * @param portTypeName - the QName of the PortType
	 */
	public Definition getDefinitionForPortType( QName 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;
	}

	/**
	 * 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 );
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Returns the date of deployment of the process
	 * - for SCA returns the current time
	 */
	public Date getDeployDate() {
		return new Date();
	}

	/**
	 * Returns userid of deployer
	 * - always "SCA Tuscany" for Tuscany...
	 */
	public String getDeployer() {
		return "SCA Tuscany";
	}

	/**
	 * Returns a list of the files in the directory containing the BPEL Process
	 */
	public List<File> getFiles() {
		File theDir = getDirectory();
		List<File> theFiles = Arrays.asList( (File[]) theDir.listFiles() );
		// TODO recurse into subdirectories
		return theFiles;
	}

	/**
	 * Returns a Map containing all the "invoke endpoints" - for which read "SCA references"
	 * The map is keyed by partnerLink name and holds Endpoint objects
	 *
	 * TODO deal with service callbacks on bidirectional services
	 */
	public Map<String, Endpoint> getInvokeEndpoints() {
		if( invokeEndpoints == null ) {
			Map<String, Endpoint> invokeEndpoints = new HashMap<String, Endpoint>();
			// Get a collection of the references
			List<Reference> theReferences = implementation.getReferences();
			// Create an endpoint for each reference, using the reference name as the "service"
			// name, combined with http://tuscany.apache.org to make a QName
			for( Reference reference : theReferences ) {
				invokeEndpoints.put( reference.getName(),
						new Endpoint( new QName( TUSCANY_NAMESPACE, reference.getName() ), "ReferencePort"));
			} // end for
		} // end if
		return invokeEndpoints;
	} // end getInvokeEndpoints

	/**
	 * Returns the name of the directory containing the BPEL files
	 */
	public String getPackage() {
		File theDir = getDirectory();
		return theDir.getName();
	} // end getPackage

	/**
	 * Return the BPEL Process ID - which is the same as the Process QName
	 */
	public QName getProcessId() {
		return getType();
	} // end getProcessID

	/**
	 * TODO - What are properties?
	 */
	public Map<QName, Node> getProperties() {
		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() {
		if( provideEndpoints == null ) {
			provideEndpoints = new HashMap<String, Endpoint>();
			// Get a collection of the references
			List<Service> theServices = implementation.getServices();
			// Create an endpoint for each reference, using the reference name as the "service"
			// name, combined with http://tuscany.apache.org to make a QName
			for( Service service : theServices ) {
				provideEndpoints.put( service.getName(),
						new Endpoint( new QName( TUSCANY_NAMESPACE, service.getName() ), "ServicePort"));
			} // end for
		} // end if
		return provideEndpoints;
	} // end getProvideEndpoints

	/**
	 * Return the process state
	 */
	public ProcessState getState() {
		return processState;
	}

	/**
	 * Returns the QName of the BPEL process
	 */
	public QName getType() {
		return implementation.getProcess();
	}

	/**
	 * Gets the process Version number
	 * - current code does not have versions for BPEL prcesses
	 */
	public long getVersion() {
		return 0;
	}

	/**
	 * Returns true if the supplied event type is enabled for any of the scopes in the provided
	 * List
	 * @param scopeNames - list of BPEL process Scope names
	 * @param type - the event type
	 */
	public boolean isEventEnabled(List<String> scopeNames, TYPE type) {
		// TODO - this will need an analysis of the content of the BPEL process
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Returns whether the process is persisted in the store
	 *
	 * Returns true for SCA configuration as the BPEL process is in the Domain config
	 */
	public boolean isTransient() {
		return true;
	} // 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() );

         // Run the compiler and generate the CBP file into the given directory
         try {
             compiler.compile( bpelFile );
         } catch (IOException e) {
             System.out.println("Compile error in " + bpelFile + e);
             // TODO - need better exception handling here
         } // end try
     } // end compile
	
	/**
	 * 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() {
		File theProcess = new File( implementation.getProcessDefinition().getURI() );
		return theProcess;
	} // 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

} // end class TuscanyProcessConfImpl



Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Mike Edwards <mi...@gmail.com>.
Matthieu Riou wrote:
> What mike says. I should just add that picking the right process version
> depending on what's already executing is handled by the runtime. The only
> thing that it will need is to know what is the definition for all the
> process versions that are still around (haven't been undeployed). You just
> need to keep these artifacts around and feed them to the engine (by calling
> register) as long as they're needed.
> 
> If you want, I can code the method that compiles the BPEL file if you give
> me a signature that gets the file as parameter (I don't know how you would
> look it up in the filesystem).
> 
> Cheers,
> Matthieu
> 
> 
>>
>> Yours optimistically,
>>
>> Mike.
>>
Matthieu,

I'd appreciate it if you could pass your eyes over my implementation of a ProcessConf, inline below.

There are a few questions that I have:

1) ProcessConfImpl from the ODE code has more public methods than are present in the ProcessConf 
interface.  What are they used for - and by which code?

2) What is getDefinitionforService(...) supposed to return?  The problem is over the interpretation 
of the name "Service" - what kind of service is this?  A service from the WSDL?  A service as listed 
in the deploy.xml file?  And what definition are we talking about - the definition of the Service in 
the WSDL file, or the definition of the portType at which the service points?

3) What are Properties as returned by getProperties()?

I'd appreciate any assistance you can give....

Yours,  Mike.


/*
  * 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.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;

import javax.wsdl.Definition;
import javax.wsdl.PortType;
import javax.xml.namespace.QName;

import org.apache.ode.bpel.evt.BpelEvent.TYPE;
import org.apache.ode.bpel.iapi.Endpoint;
import org.apache.ode.bpel.iapi.ProcessConf;
import org.apache.ode.bpel.iapi.ProcessState;
import org.apache.ode.bpel.compiler.BpelC;
import org.w3c.dom.Node;

import org.apache.tuscany.sca.implementation.bpel.BPELImplementation;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.Service;

public class TuscanyProcessConfImpl implements ProcessConf {
	
	private BPELImplementation implementation;
	private Map<String, Endpoint> invokeEndpoints = null;
	private Map<String, Endpoint> provideEndpoints = null;
	private Map<QName, Node> properties = null;
	private ProcessState processState;
	
	private final String TUSCANY_NAMESPACE = "http://tuscany.apache.org";
	
	/**
	 * Constructor for the ProcessConf implementation
	 * @param theImplementation the BPEL implementation for which this is the ProcessConf
	 */
	public TuscanyProcessConfImpl( BPELImplementation theImplementation ) {
		this.implementation = theImplementation;
		
		processState = ProcessState.ACTIVE;
		
		// Compile the process
		compile( getBPELFile() );
	} // end TuscanyProcessConfImpl constructor

	/**
	 * Returns the URI for the directory containing the BPEL process
	 */
	public URI getBaseURI() {
		File theDir = getDirectory();
		return theDir.toURI();
	}

	/**
	 * Returns a String containing the (local) name of the file containing the BPEL process
	 */
	public String getBpelDocument() {
		URL processURL = implementation.getProcessDefinition().getLocation();
		try {
		    return getRelativePath( getDirectory(), new File( processURL.toURI() ));
		} catch (Exception e) {
			System.out.println( "Unable to resolve relative path of BPEL process" + processURL );
			return null;
		} // end try
	} // end getBpelDocument

	/**
	 * Returns an InputStream containing the Compiled BPEL Process (CBP)
	 */
	public InputStream getCBPInputStream() {
		// 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 = implementation.getProcessDefinition().getName().getLocalPart() + ".cbp";
		File cbpFile = new File( getDirectory(), cbpFileName );
		if( cbpFile.exists() ) {
			// Create an InputStream from the cbp file...
			try {
			    return new FileInputStream( cbpFile );
			} catch ( Exception e ) {
				System.out.println("Unable to open the cbp file for BPEL process: " +
						implementation.getProcessDefinition().getName());
			} // end try
		} else {
			// Cannot find the cbp file
			System.out.println("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
	
	/**
	 * Return the WSDL Definition for a given PortType
	 * @param portTypeName - the QName of the PortType
	 */
	public Definition getDefinitionForPortType( QName 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;
	}

	/**
	 * 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 );
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Returns the date of deployment of the process
	 * - for SCA returns the current time
	 */
	public Date getDeployDate() {
		return new Date();
	}

	/**
	 * Returns userid of deployer
	 * - always "SCA Tuscany" for Tuscany...
	 */
	public String getDeployer() {
		return "SCA Tuscany";
	}

	/**
	 * Returns a list of the files in the directory containing the BPEL Process
	 */
	public List<File> getFiles() {
		File theDir = getDirectory();
		List<File> theFiles = Arrays.asList( (File[]) theDir.listFiles() );
		// TODO recurse into subdirectories
		return theFiles;
	}

	/**
	 * Returns a Map containing all the "invoke endpoints" - for which read "SCA references"
	 * The map is keyed by partnerLink name and holds Endpoint objects
	 *
	 * TODO deal with service callbacks on bidirectional services
	 */
	public Map<String, Endpoint> getInvokeEndpoints() {
		if( invokeEndpoints == null ) {
			Map<String, Endpoint> invokeEndpoints = new HashMap<String, Endpoint>();
			// Get a collection of the references
			List<Reference> theReferences = implementation.getReferences();
			// Create an endpoint for each reference, using the reference name as the "service"
			// name, combined with http://tuscany.apache.org to make a QName
			for( Reference reference : theReferences ) {
				invokeEndpoints.put( reference.getName(),
						new Endpoint( new QName( TUSCANY_NAMESPACE, reference.getName() ), "ReferencePort"));
			} // end for
		} // end if
		return invokeEndpoints;
	} // end getInvokeEndpoints

	/**
	 * Returns the name of the directory containing the BPEL files
	 */
	public String getPackage() {
		File theDir = getDirectory();
		return theDir.getName();
	} // end getPackage

	/**
	 * Return the BPEL Process ID - which is the same as the Process QName
	 */
	public QName getProcessId() {
		return getType();
	} // end getProcessID

	/**
	 * TODO - What are properties?
	 */
	public Map<QName, Node> getProperties() {
		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() {
		if( provideEndpoints == null ) {
			provideEndpoints = new HashMap<String, Endpoint>();
			// Get a collection of the references
			List<Service> theServices = implementation.getServices();
			// Create an endpoint for each reference, using the reference name as the "service"
			// name, combined with http://tuscany.apache.org to make a QName
			for( Service service : theServices ) {
				provideEndpoints.put( service.getName(),
						new Endpoint( new QName( TUSCANY_NAMESPACE, service.getName() ), "ServicePort"));
			} // end for
		} // end if
		return provideEndpoints;
	} // end getProvideEndpoints

	/**
	 * Return the process state
	 */
	public ProcessState getState() {
		return processState;
	}

	/**
	 * Returns the QName of the BPEL process
	 */
	public QName getType() {
		return implementation.getProcess();
	}

	/**
	 * Gets the process Version number
	 * - current code does not have versions for BPEL prcesses
	 */
	public long getVersion() {
		return 0;
	}

	/**
	 * Returns true if the supplied event type is enabled for any of the scopes in the provided
	 * List
	 * @param scopeNames - list of BPEL process Scope names
	 * @param type - the event type
	 */
	public boolean isEventEnabled(List<String> scopeNames, TYPE type) {
		// TODO - this will need an analysis of the content of the BPEL process
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Returns whether the process is persisted in the store
	 *
	 * Returns true for SCA configuration as the BPEL process is in the Domain config
	 */
	public boolean isTransient() {
		return true;
	} // 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() );

         // Run the compiler and generate the CBP file into the given directory
         try {
             compiler.compile( bpelFile );
         } catch (IOException e) {
             System.out.println("Compile error in " + bpelFile + e);
             // TODO - need better exception handling here
         } // end try
     } // end compile
	
	/**
	 * 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() {
		File theProcess = new File( implementation.getProcessDefinition().getURI() );
		return theProcess;
	} // 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

} // end class TuscanyProcessConfImpl



Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Matthieu Riou <ma...@offthelip.org>.
On Tue, May 20, 2008 at 2:12 PM, Mike Edwards <
mike.edwards.inglenook@gmail.com> wrote:

> Luciano Resende wrote:
>
>> So, in the case where we replace the ODE Process Store module with one
>> implemented by Tuscany, is this new module going to be responsible for
>> handling all the versioning and matching a running process instance
>> with the right BPEL process version ?
>>
>> Also, can the modules that handle deploy.xml and process store be
>> implemented separately (e.g Tuscany would handle deploy.xml but still
>> use ode process store module) ?
>>
>> Thanks
>> Luciano
>>
> Luciano,
>
> My reading of Matthieu's note is that what is necessary is simply that
> Tuscany must implement a ProcessConf class, rather than the whole process
> store.  That can be prepared entirely from information which Tuscany has to
> hand, although as Matthieu points out, there are complex details within the
> ProcessConf implementation that will require us to re-use some ODE modules
> that compile the BPEL process file, but he says that doing that will not be
> too hard ;-)
>
> With Tuscany, the Process Store is not needed since Tuscany has the Domain
> configuration to drive things.
>

What mike says. I should just add that picking the right process version
depending on what's already executing is handled by the runtime. The only
thing that it will need is to know what is the definition for all the
process versions that are still around (haven't been undeployed). You just
need to keep these artifacts around and feed them to the engine (by calling
register) as long as they're needed.

If you want, I can code the method that compiles the BPEL file if you give
me a signature that gets the file as parameter (I don't know how you would
look it up in the filesystem).

Cheers,
Matthieu


>
>
> Yours optimistically,
>
> Mike.
>

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Matthieu Riou <ma...@offthelip.org>.
On Tue, May 20, 2008 at 2:12 PM, Mike Edwards <
mike.edwards.inglenook@gmail.com> wrote:

> Luciano Resende wrote:
>
>> So, in the case where we replace the ODE Process Store module with one
>> implemented by Tuscany, is this new module going to be responsible for
>> handling all the versioning and matching a running process instance
>> with the right BPEL process version ?
>>
>> Also, can the modules that handle deploy.xml and process store be
>> implemented separately (e.g Tuscany would handle deploy.xml but still
>> use ode process store module) ?
>>
>> Thanks
>> Luciano
>>
> Luciano,
>
> My reading of Matthieu's note is that what is necessary is simply that
> Tuscany must implement a ProcessConf class, rather than the whole process
> store.  That can be prepared entirely from information which Tuscany has to
> hand, although as Matthieu points out, there are complex details within the
> ProcessConf implementation that will require us to re-use some ODE modules
> that compile the BPEL process file, but he says that doing that will not be
> too hard ;-)
>
> With Tuscany, the Process Store is not needed since Tuscany has the Domain
> configuration to drive things.
>

What mike says. I should just add that picking the right process version
depending on what's already executing is handled by the runtime. The only
thing that it will need is to know what is the definition for all the
process versions that are still around (haven't been undeployed). You just
need to keep these artifacts around and feed them to the engine (by calling
register) as long as they're needed.

If you want, I can code the method that compiles the BPEL file if you give
me a signature that gets the file as parameter (I don't know how you would
look it up in the filesystem).

Cheers,
Matthieu


>
>
> Yours optimistically,
>
> Mike.
>

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Mike Edwards <mi...@gmail.com>.
Luciano Resende wrote:
> So, in the case where we replace the ODE Process Store module with one
> implemented by Tuscany, is this new module going to be responsible for
> handling all the versioning and matching a running process instance
> with the right BPEL process version ?
> 
> Also, can the modules that handle deploy.xml and process store be
> implemented separately (e.g Tuscany would handle deploy.xml but still
> use ode process store module) ?
> 
> Thanks
> Luciano
Luciano,

My reading of Matthieu's note is that what is necessary is simply that Tuscany must implement a 
ProcessConf class, rather than the whole process store.  That can be prepared entirely from 
information which Tuscany has to hand, although as Matthieu points out, there are complex details 
within the ProcessConf implementation that will require us to re-use some ODE modules that compile 
the BPEL process file, but he says that doing that will not be too hard ;-)

With Tuscany, the Process Store is not needed since Tuscany has the Domain configuration to drive 
things.


Yours optimistically,

Mike.

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Mike Edwards <mi...@gmail.com>.
Luciano Resende wrote:
> So, in the case where we replace the ODE Process Store module with one
> implemented by Tuscany, is this new module going to be responsible for
> handling all the versioning and matching a running process instance
> with the right BPEL process version ?
> 
> Also, can the modules that handle deploy.xml and process store be
> implemented separately (e.g Tuscany would handle deploy.xml but still
> use ode process store module) ?
> 
> Thanks
> Luciano
Luciano,

My reading of Matthieu's note is that what is necessary is simply that Tuscany must implement a 
ProcessConf class, rather than the whole process store.  That can be prepared entirely from 
information which Tuscany has to hand, although as Matthieu points out, there are complex details 
within the ProcessConf implementation that will require us to re-use some ODE modules that compile 
the BPEL process file, but he says that doing that will not be too hard ;-)

With Tuscany, the Process Store is not needed since Tuscany has the Domain configuration to drive 
things.


Yours optimistically,

Mike.

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Luciano Resende <lu...@gmail.com>.
So, in the case where we replace the ODE Process Store module with one
implemented by Tuscany, is this new module going to be responsible for
handling all the versioning and matching a running process instance
with the right BPEL process version ?

Also, can the modules that handle deploy.xml and process store be
implemented separately (e.g Tuscany would handle deploy.xml but still
use ode process store module) ?

Thanks
Luciano

On Mon, May 19, 2008 at 11:23 AM, Matthieu Riou <ma...@offthelip.org> wrote:
> On Mon, May 19, 2008 at 9:11 AM, Mike Edwards <
> mike.edwards.inglenook@gmail.com> wrote:
>
>> Folks,
>>
>> I am interested in getting rid of the need to have a physical deploy.xml
>> file in the directory with a BPEL process file.
>>
>> Can I supply the same information to the ODE runtime through some other
>> means, such as method parameters or some in-memory mechanism?
>>
>
> The short answer is: yes, you can. The long answer is... a bit longer :)
>
>
>>
>> For the SCA integration, the SCA runtime has all the information contained
>> in the deploy.xml file, but in another form.  It would be great to relieve
>> the developers from the need to create this file.
>>
>
> Let me explain a bit how that works. The ODE runtime doesn't know anything
> about the file system, descriptors or even BPEL files. It just knows that
> something is supposed to call it, passing an interface implementation
> (ProcessConf [1]) that provides everything it needs (and a bit more
> actually). It's so dumb that it doesn't even know which processes it should
> know about, so every time the server is restarted, it expects to be called
> again with the same process definition information.
>
> Parrallely in ODE we have a process store that handles all the nitty gritty
> details of knowing where is what in which version and remembering it. The
> process store doesn't know about the runtime and the runtime doesn't know
> about the store. The advantage is that, in theory, you could pick different
> clustering models (one store / multiple servers, multiple stores / multiple
> servers) depending on how you want things to be arranged. The other
> advantage is that you can get rid of the store altogether if you have all
> the necessary information.
>
> When a new process is deployed (or undeployed, or retired, or ...), the
> store just produces an event. Same thing when the whole server is restarted,
> the store produces several events for each process the runtime should know
> about. These events are just relayed by the Integration Layer that binds the
> store and the runtime and implements external communication (all the
> interfaces Luciano has implemented).
>
> Getting back to Tuscany, what I'm thinking is that we should remove the
> store (and its events) from the equation. Tuscany would just let the runtime
> know when when a process is available by calling
> BpelServer.register(ProcessConf), providing its own implementation of
> ProcessConf. The current Tuscany integration layer already has a reference
> to the BpelServer, so that's easy. The caveat is that in this case, Tuscany
> will also need to compile the .bpel file to provide the CBP (Compiled
> Business Process) but that's fairly painless (see
> DeploymentUnitDir.compile(File) [2]).
>
> The net advantage of this for Tuscany will be a much better integration and
> much more control over the process lifecycle. So let me know what you think
> and I can help with your ProcessConf implementation.
>
> Cheers,
> Matthieu
>
> [1]
> http://svn.apache.org/repos/asf/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java
> [2]
> http://svn.apache.org/repos/asf/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/DeploymentUnitDir.java
>
>
>>
>> Yours,  Mike Edwards
>> Apache Tuscany team.
>>
>



-- 
Luciano Resende
Apache Tuscany Committer
http://people.apache.org/~lresende
http://lresende.blogspot.com/

Re: Eliminating the need for deploy.xml - Tuscany SCA / ODE integration

Posted by Luciano Resende <lu...@gmail.com>.
So, in the case where we replace the ODE Process Store module with one
implemented by Tuscany, is this new module going to be responsible for
handling all the versioning and matching a running process instance
with the right BPEL process version ?

Also, can the modules that handle deploy.xml and process store be
implemented separately (e.g Tuscany would handle deploy.xml but still
use ode process store module) ?

Thanks
Luciano

On Mon, May 19, 2008 at 11:23 AM, Matthieu Riou <ma...@offthelip.org> wrote:
> On Mon, May 19, 2008 at 9:11 AM, Mike Edwards <
> mike.edwards.inglenook@gmail.com> wrote:
>
>> Folks,
>>
>> I am interested in getting rid of the need to have a physical deploy.xml
>> file in the directory with a BPEL process file.
>>
>> Can I supply the same information to the ODE runtime through some other
>> means, such as method parameters or some in-memory mechanism?
>>
>
> The short answer is: yes, you can. The long answer is... a bit longer :)
>
>
>>
>> For the SCA integration, the SCA runtime has all the information contained
>> in the deploy.xml file, but in another form.  It would be great to relieve
>> the developers from the need to create this file.
>>
>
> Let me explain a bit how that works. The ODE runtime doesn't know anything
> about the file system, descriptors or even BPEL files. It just knows that
> something is supposed to call it, passing an interface implementation
> (ProcessConf [1]) that provides everything it needs (and a bit more
> actually). It's so dumb that it doesn't even know which processes it should
> know about, so every time the server is restarted, it expects to be called
> again with the same process definition information.
>
> Parrallely in ODE we have a process store that handles all the nitty gritty
> details of knowing where is what in which version and remembering it. The
> process store doesn't know about the runtime and the runtime doesn't know
> about the store. The advantage is that, in theory, you could pick different
> clustering models (one store / multiple servers, multiple stores / multiple
> servers) depending on how you want things to be arranged. The other
> advantage is that you can get rid of the store altogether if you have all
> the necessary information.
>
> When a new process is deployed (or undeployed, or retired, or ...), the
> store just produces an event. Same thing when the whole server is restarted,
> the store produces several events for each process the runtime should know
> about. These events are just relayed by the Integration Layer that binds the
> store and the runtime and implements external communication (all the
> interfaces Luciano has implemented).
>
> Getting back to Tuscany, what I'm thinking is that we should remove the
> store (and its events) from the equation. Tuscany would just let the runtime
> know when when a process is available by calling
> BpelServer.register(ProcessConf), providing its own implementation of
> ProcessConf. The current Tuscany integration layer already has a reference
> to the BpelServer, so that's easy. The caveat is that in this case, Tuscany
> will also need to compile the .bpel file to provide the CBP (Compiled
> Business Process) but that's fairly painless (see
> DeploymentUnitDir.compile(File) [2]).
>
> The net advantage of this for Tuscany will be a much better integration and
> much more control over the process lifecycle. So let me know what you think
> and I can help with your ProcessConf implementation.
>
> Cheers,
> Matthieu
>
> [1]
> http://svn.apache.org/repos/asf/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java
> [2]
> http://svn.apache.org/repos/asf/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/DeploymentUnitDir.java
>
>
>>
>> Yours,  Mike Edwards
>> Apache Tuscany team.
>>
>



-- 
Luciano Resende
Apache Tuscany Committer
http://people.apache.org/~lresende
http://lresende.blogspot.com/