summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/implementation-bpel-runtime/src/main/java/org/apache/tuscany/sca/implementation/bpel/ode/BPELODEDeployFile.java
blob: fe1e2d620b5887ed9704bc5edd62467207c33e1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * 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