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