001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.soap;
018
019 import java.net.URI;
020 import java.util.Collections;
021 import java.util.HashMap;
022 import java.util.Iterator;
023 import java.util.List;
024 import java.util.Map;
025
026 import javax.jbi.component.ComponentContext;
027 import javax.jbi.messaging.MessageExchange.Role;
028 import javax.jbi.servicedesc.ServiceEndpoint;
029 import javax.wsdl.Definition;
030 import javax.wsdl.Import;
031 import javax.wsdl.Types;
032 import javax.wsdl.WSDLException;
033 import javax.wsdl.extensions.ExtensibilityElement;
034 import javax.wsdl.extensions.ExtensionRegistry;
035 import javax.wsdl.extensions.schema.Schema;
036 import javax.wsdl.extensions.schema.SchemaImport;
037 import javax.wsdl.factory.WSDLFactory;
038 import javax.wsdl.xml.WSDLReader;
039 import javax.wsdl.xml.WSDLWriter;
040 import javax.xml.namespace.QName;
041
042 import org.apache.servicemix.common.Endpoint;
043 import org.apache.servicemix.common.ExchangeProcessor;
044 import org.apache.servicemix.common.wsdl1.JbiExtension;
045 import org.apache.servicemix.common.xbean.XBeanServiceUnit;
046 import org.apache.servicemix.jbi.security.auth.AuthenticationService;
047 import org.apache.servicemix.jbi.security.keystore.KeystoreManager;
048 import org.apache.servicemix.soap.handlers.addressing.AddressingHandler;
049 import org.springframework.core.io.Resource;
050 import org.w3c.dom.Document;
051
052 import com.ibm.wsdl.Constants;
053
054 public abstract class SoapEndpoint extends Endpoint {
055
056 protected ServiceEndpoint activated;
057 protected ExchangeProcessor processor;
058 protected Role role;
059 protected URI defaultMep;
060 protected boolean soap;
061 protected String soapVersion;
062 protected Resource wsdlResource;
063 protected QName defaultOperation;
064 protected QName targetInterfaceName;
065 protected QName targetService;
066 protected String targetEndpoint;
067 protected List policies;
068 protected Map wsdls = new HashMap();
069
070 public SoapEndpoint() {
071 policies = Collections.singletonList(new AddressingHandler());
072 }
073
074 public AuthenticationService getAuthenticationService() {
075 return null;
076 }
077
078 public KeystoreManager getKeystoreManager() {
079 return null;
080 }
081
082 /**
083 * @return the policies
084 */
085 public List getPolicies() {
086 return policies;
087 }
088 /**
089 * @param policies the policies to set
090 */
091 public void setPolicies(List policies) {
092 this.policies = policies;
093 }
094 /**
095 * @return Returns the defaultMep.
096 */
097 public URI getDefaultMep() {
098 return defaultMep;
099 }
100 /**
101 * @param defaultMep The defaultMep to set.
102 */
103 public void setDefaultMep(URI defaultMep) {
104 this.defaultMep = defaultMep;
105 }
106 /**
107 * @return Returns the defaultOperation.
108 */
109 public QName getDefaultOperation() {
110 return defaultOperation;
111 }
112 /**
113 * @param defaultOperation The defaultOperation to set.
114 */
115 public void setDefaultOperation(QName defaultOperation) {
116 this.defaultOperation = defaultOperation;
117 }
118 /**
119 * @return Returns the role.
120 */
121 public Role getRole() {
122 return role;
123 }
124 /**
125 * @param role The role to set.
126 */
127 public void setRole(Role role) {
128 this.role = role;
129 }
130 /**
131 * @return Returns the soap.
132 */
133 public boolean isSoap() {
134 return soap;
135 }
136 /**
137 * @param soap The soap to set.
138 */
139 public void setSoap(boolean soap) {
140 this.soap = soap;
141 }
142 /**
143 * @return Returns the soapVersion.
144 */
145 public String getSoapVersion() {
146 return soapVersion;
147 }
148 /**
149 * @param soapVersion The soapVersion to set.
150 */
151 public void setSoapVersion(String soapVersion) {
152 this.soapVersion = soapVersion;
153 }
154 /**
155 * @return Returns the targetEndpoint.
156 */
157 public String getTargetEndpoint() {
158 return targetEndpoint;
159 }
160 /**
161 * @param targetEndpoint The targetEndpoint to set.
162 */
163 public void setTargetEndpoint(String targetEndpoint) {
164 this.targetEndpoint = targetEndpoint;
165 }
166 /**
167 * @return Returns the targetInterfaceName.
168 */
169 public QName getTargetInterfaceName() {
170 return targetInterfaceName;
171 }
172 /**
173 * @param targetInterfaceName The targetInterfaceName to set.
174 */
175 public void setTargetInterfaceName(QName targetInterfaceName) {
176 this.targetInterfaceName = targetInterfaceName;
177 }
178 /**
179 * @return Returns the targetServiceName.
180 */
181 public QName getTargetService() {
182 return targetService;
183 }
184 /**
185 * @param targetServiceName The targetServiceName to set.
186 */
187 public void setTargetService(QName targetServiceName) {
188 this.targetService = targetServiceName;
189 }
190 /**
191 * @return Returns the wsdlResource.
192 */
193 public Resource getWsdlResource() {
194 return wsdlResource;
195 }
196 /**
197 * @param wsdlResource The wsdlResource to set.
198 */
199 public void setWsdlResource(Resource wsdlResource) {
200 this.wsdlResource = wsdlResource;
201 }
202 /**
203 * @org.apache.xbean.Property alias="role"
204 * @param role
205 */
206 public void setRoleAsString(String role) {
207 if (role == null) {
208 throw new IllegalArgumentException("Role must be specified");
209 } else if (JbiExtension.ROLE_CONSUMER.equals(role)) {
210 setRole(Role.CONSUMER);
211 } else if (JbiExtension.ROLE_PROVIDER.equals(role)) {
212 setRole(Role.PROVIDER);
213 } else {
214 throw new IllegalArgumentException("Unrecognized role: " + role);
215 }
216 }
217
218 /**
219 * Load the wsdl for this endpoint.
220 */
221 protected void loadWsdl() {
222 // Load WSDL from the resource
223 if (description == null && wsdlResource != null) {
224 ClassLoader cl = Thread.currentThread().getContextClassLoader();
225 try {
226 Thread.currentThread().setContextClassLoader(serviceUnit.getConfigurationClassLoader());
227 WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
228 reader.setFeature(Constants.FEATURE_VERBOSE, false);
229 Definition def = reader.readWSDL(wsdlResource.getURL().toString());
230 overrideDefinition(def);
231 } catch (Exception e) {
232 logger.warn("Could not load description from resource", e);
233 } finally {
234 Thread.currentThread().setContextClassLoader(cl);
235 }
236 }
237 // If the endpoint is a consumer, try to find
238 // the proxied endpoint description
239 if (description == null && definition == null && getRole() == Role.CONSUMER) {
240 retrieveProxiedEndpointDefinition();
241 }
242 // If the wsdl definition is provided,
243 // convert it to a DOM document
244 if (description == null && definition != null) {
245 try {
246 description = WSDLFactory.newInstance().newWSDLWriter().getDocument(definition);
247 } catch (Exception e) {
248 logger.warn("Could not create document from wsdl description", e);
249 }
250 }
251 // If the dom description is provided
252 // convert it to a WSDL definition
253 if (definition == null && description != null) {
254 try {
255 definition = WSDLFactory.newInstance().newWSDLReader().readWSDL(null, description);
256 } catch (Exception e) {
257 logger.warn("Could not create wsdl definition from dom document", e);
258 }
259 }
260 if (definition != null) {
261 try {
262 mapDefinition(definition);
263 } catch (Exception e) {
264 logger.warn("Could not map wsdl definition to documents", e);
265 }
266 }
267 }
268
269 /**
270 * Create a wsdl definition for a consumer endpoint.
271 * Loads the target endpoint definition and add http binding
272 * informations to it.
273 */
274 protected void retrieveProxiedEndpointDefinition() {
275 if (logger.isDebugEnabled()) {
276 logger.debug("Retrieving proxied endpoint definition");
277 }
278 try {
279 ComponentContext ctx = this.serviceUnit.getComponent().getComponentContext();
280 ServiceEndpoint ep = null;
281 if (targetService != null && targetEndpoint != null) {
282 ep = ctx.getEndpoint(targetService, targetEndpoint);
283 if (ep == null && logger.isDebugEnabled()) {
284 logger.debug("Could not retrieve endpoint targetService/targetEndpoint");
285 }
286 }
287 if (ep == null && targetService != null) {
288 ServiceEndpoint[] eps = ctx.getEndpointsForService(targetService);
289 if (eps != null && eps.length > 0) {
290 ep = eps[0];
291 }
292 if (ep == null && logger.isDebugEnabled()) {
293 logger.debug("Could not retrieve endpoint for targetService");
294 }
295 }
296 if (ep == null && targetInterfaceName != null) {
297 ServiceEndpoint[] eps = ctx.getEndpoints(targetInterfaceName);
298 if (eps != null && eps.length > 0) {
299 ep = eps[0];
300 }
301 if (ep == null && logger.isDebugEnabled()) {
302 logger.debug("Could not retrieve endpoint for targetInterfaceName");
303 }
304 }
305 if (ep == null && service != null && endpoint != null) {
306 ep = ctx.getEndpoint(service, endpoint);
307 if (ep == null && logger.isDebugEnabled()) {
308 logger.debug("Could not retrieve endpoint for service/endpoint");
309 }
310 }
311 if (ep != null) {
312 Document doc = ctx.getEndpointDescriptor(ep);
313 if (doc != null) {
314 WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
315 reader.setFeature(Constants.FEATURE_VERBOSE, false);
316 Definition def = reader.readWSDL(null, doc);
317 if (def != null) {
318 overrideDefinition(def);
319 }
320 }
321 }
322 } catch (Exception e) {
323 logger.debug("Unable to retrieve target endpoint descriptor", e);
324 }
325 }
326
327 /* (non-Javadoc)
328 * @see org.apache.servicemix.common.Endpoint#getProcessor()
329 */
330 public ExchangeProcessor getProcessor() {
331 return this.processor;
332 }
333
334 /* (non-Javadoc)
335 * @see org.servicemix.common.Endpoint#activate()
336 */
337 public void activate() throws Exception {
338 ComponentContext ctx = this.serviceUnit.getComponent().getComponentContext();
339 loadWsdl();
340 if (getRole() == Role.PROVIDER) {
341 activated = ctx.activateEndpoint(service, endpoint);
342 processor = createProviderProcessor();
343 } else {
344 activated = createExternalEndpoint();
345 ctx.registerExternalEndpoint(activated);
346 processor = createConsumerProcessor();
347 }
348 processor.start();
349 }
350
351 public void activateDynamic() throws Exception {
352 if (getRole() == Role.PROVIDER) {
353 processor = createProviderProcessor();
354 } else {
355 processor = createConsumerProcessor();
356 }
357 processor.start();
358 }
359
360 /* (non-Javadoc)
361 * @see org.servicemix.common.Endpoint#deactivate()
362 */
363 public void deactivate() throws Exception {
364 if (activated != null) {
365 ComponentContext ctx = this.serviceUnit.getComponent().getComponentContext();
366 if (getRole() == Role.PROVIDER) {
367 ServiceEndpoint ep = activated;
368 activated = null;
369 ctx.deactivateEndpoint(ep);
370 } else {
371 ServiceEndpoint ep = activated;
372 activated = null;
373 ctx.deregisterExternalEndpoint(ep);
374 }
375 }
376 processor.stop();
377 }
378
379 protected abstract void overrideDefinition(Definition def) throws Exception;
380
381 protected abstract ExchangeProcessor createProviderProcessor();
382
383 protected abstract ExchangeProcessor createConsumerProcessor();
384
385 protected abstract ServiceEndpoint createExternalEndpoint();
386
387 protected WSDLReader createWsdlReader() throws WSDLException {
388 WSDLFactory factory = WSDLFactory.newInstance();
389 ExtensionRegistry registry = factory.newPopulatedExtensionRegistry();
390 registerExtensions(registry);
391 WSDLReader reader = factory.newWSDLReader();
392 reader.setFeature(Constants.FEATURE_VERBOSE, false);
393 reader.setExtensionRegistry(registry);
394 return reader;
395 }
396
397 protected WSDLWriter createWsdlWriter() throws WSDLException {
398 WSDLFactory factory = WSDLFactory.newInstance();
399 ExtensionRegistry registry = factory.newPopulatedExtensionRegistry();
400 registerExtensions(registry);
401 WSDLWriter writer = factory.newWSDLWriter();
402 //writer.setExtensionRegistry(registry);
403 return writer;
404 }
405
406 protected void registerExtensions(ExtensionRegistry registry) {
407 JbiExtension.register(registry);
408 }
409
410
411 protected void mapDefinition(Definition def) throws WSDLException {
412 wsdls.put("main.wsdl", createWsdlWriter().getDocument(def));
413 mapImports(def);
414 }
415
416 protected void mapImports(Definition def) throws WSDLException {
417 // Add other imports to mapping
418 Map imports = def.getImports();
419 for (Iterator iter = imports.values().iterator(); iter.hasNext();) {
420 List imps = (List) iter.next();
421 for (Iterator iterator = imps.iterator(); iterator.hasNext();) {
422 Import imp = (Import) iterator.next();
423 Definition impDef = imp.getDefinition();
424 String impLoc = imp.getLocationURI();
425 if (impDef != null && impLoc != null && !URI.create(impLoc).isAbsolute()) {
426 wsdls.put(impLoc, createWsdlWriter().getDocument(impDef));
427 mapImports(impDef);
428 }
429 }
430 }
431 // Add schemas to mapping
432 Types types = def.getTypes();
433 if (types != null) {
434 for (Iterator it = types.getExtensibilityElements().iterator(); it.hasNext();) {
435 ExtensibilityElement ee = (ExtensibilityElement) it.next();
436 if (ee instanceof Schema) {
437 Schema schema = (Schema) ee;
438 Map schemaImports = schema.getImports();
439 for (Iterator iter = schemaImports.values().iterator(); iter.hasNext();) {
440 List imps = (List) iter.next();
441 for (Iterator iterator = imps.iterator(); iterator.hasNext();) {
442 SchemaImport schemaImport = (SchemaImport) iterator.next();
443 Schema schemaImp = schemaImport.getReferencedSchema();
444 String schemaLoc = schemaImport.getSchemaLocationURI();
445 if (schemaLoc != null && schemaImp != null && schemaImp.getElement() != null && !URI.create(schemaLoc).isAbsolute()) {
446 wsdls.put(schemaLoc, schemaImp.getElement());
447 }
448 }
449 }
450 }
451 }
452 }
453 }
454
455 /**
456 * @return Returns the wsdls.
457 */
458 public Map getWsdls() {
459 return wsdls;
460 }
461
462 }