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.jms;
018:
019: import java.io.InputStream;
020: import java.lang.reflect.Constructor;
021: import java.util.Iterator;
022: import java.util.Properties;
023:
024: import javax.jbi.servicedesc.ServiceEndpoint;
025: import javax.jms.ConnectionFactory;
026: import javax.jms.Destination;
027: import javax.resource.spi.ActivationSpec;
028: import javax.resource.spi.BootstrapContext;
029: import javax.resource.spi.ResourceAdapter;
030: import javax.wsdl.Definition;
031: import javax.wsdl.Port;
032: import javax.wsdl.Service;
033:
034: import org.apache.servicemix.common.ExchangeProcessor;
035: import org.apache.servicemix.common.ExternalEndpoint;
036: import org.apache.servicemix.jbi.security.auth.AuthenticationService;
037: import org.apache.servicemix.jbi.security.keystore.KeystoreManager;
038: import org.apache.servicemix.soap.SoapEndpoint;
039: import org.apache.servicemix.store.Store;
040: import org.apache.servicemix.store.StoreFactory;
041:
042: /**
043: *
044: * @author gnodet
045: * @version $Revision: 580069 $
046: * @org.apache.xbean.XBean element="endpoint"
047: * description="A jms endpoint"
048: *
049: */
050: public class JmsEndpoint extends SoapEndpoint implements
051: JmsEndpointType {
052:
053: //
054: // Jms informations
055: //
056: protected String initialContextFactory;
057: protected String jndiProviderURL;
058: protected String destinationStyle;
059: protected String jndiConnectionFactoryName;
060: protected String jndiDestinationName;
061: protected String jmsProviderDestinationName;
062: protected String jndiReplyToName;
063: protected String jmsProviderReplyToName;
064:
065: protected boolean useMsgIdInResponse;
066: //
067: // Spring configuration
068: //
069: protected ConnectionFactory connectionFactory;
070: protected Destination destination;
071: protected String processorName;
072: protected JmsMarshaler marshaler;
073: //
074: // JCA config
075: //
076: protected ResourceAdapter resourceAdapter;
077: protected ActivationSpec activationSpec;
078: protected BootstrapContext bootstrapContext;
079: protected boolean synchronous;
080: protected boolean rollbackOnError;
081:
082: // Other configuration flags
083: protected boolean needJavaIdentifiers;
084:
085: /**
086: * The store to keep pending exchanges
087: */
088: protected Store store;
089: protected StoreFactory storeFactory;
090:
091: public JmsEndpoint() {
092: marshaler = new DefaultJmsMarshaler(this );
093: }
094:
095: /**
096: * The BootstrapContext to use for a JCA consumer endpoint.
097: *
098: * @return the bootstrapContext
099: */
100: public BootstrapContext getBootstrapContext() {
101: return bootstrapContext;
102: }
103:
104: /**
105: * @param bootstrapContext the bootstrapContext to set
106: */
107: public void setBootstrapContext(BootstrapContext bootstrapContext) {
108: this .bootstrapContext = bootstrapContext;
109: }
110:
111: /**
112: * For a JCA consumer endpoint, indicates if the JBI exchange
113: * should be sent synchronously or asynchronously.
114: * This changes the transaction boundary.
115: *
116: * @return the synchronous
117: */
118: public boolean isSynchronous() {
119: return synchronous;
120: }
121:
122: /**
123: * @param synchronous the synchronous to set
124: */
125: public void setSynchronous(boolean synchronous) {
126: this .synchronous = synchronous;
127: }
128:
129: /**
130: * @return the rollbackOnError
131: */
132: public boolean isRollbackOnError() {
133: return rollbackOnError;
134: }
135:
136: /**
137: * @param rollbackOnError the rollbackOnError to set
138: */
139: public void setRollbackOnError(boolean rollbackOnError) {
140: this .rollbackOnError = rollbackOnError;
141: }
142:
143: /**
144: * The ActivatioSpec to use on this JCA consumer endpoint.
145: *
146: * @return the activationSpec
147: */
148: public ActivationSpec getActivationSpec() {
149: return activationSpec;
150: }
151:
152: /**
153: * @param activationSpec the activationSpec to set
154: */
155: public void setActivationSpec(ActivationSpec activationSpec) {
156: this .activationSpec = activationSpec;
157: }
158:
159: /**
160: * The ResourceAdapter to use on this JCA consumer endpoint.
161: *
162: * @return the resourceAdapter
163: */
164: public ResourceAdapter getResourceAdapter() {
165: return resourceAdapter;
166: }
167:
168: /**
169: * @param resourceAdapter the resourceAdapter to set
170: */
171: public void setResourceAdapter(ResourceAdapter resourceAdapter) {
172: this .resourceAdapter = resourceAdapter;
173: }
174:
175: /**
176: * The class name of the JNDI InitialContextFactory to use.
177: *
178: * @return Returns the initialContextFactory.
179: */
180: public String getInitialContextFactory() {
181: return initialContextFactory;
182: }
183:
184: /**
185: * @param initialContextFactory The initialContextFactory to set.
186: */
187: public void setInitialContextFactory(String initialContextFactory) {
188: this .initialContextFactory = initialContextFactory;
189: }
190:
191: /**
192: * The name of the destination create by a call to
193: * <code>Session.createQueue</code> or <code>Session.createTopic</code>.
194: * This property is used when <code>destination</code> and
195: * <code>jndiDestinationName</code> are
196: * both <code>null</code>.
197: *
198: * @return Returns the jmsProviderDestinationName.
199: */
200: public String getJmsProviderDestinationName() {
201: return jmsProviderDestinationName;
202: }
203:
204: /**
205: * @param jmsProviderDestinationName The jmsProviderDestinationName to set.
206: */
207: public void setJmsProviderDestinationName(
208: String jmsProviderDestinationName) {
209: this .jmsProviderDestinationName = jmsProviderDestinationName;
210: }
211:
212: /**
213: * The name of the JMS Reply-to destination to lookup in JNDI.
214: * Optional: a temporary queue will be used
215: * if a replyTo is not provided.
216: *
217: * @return Returns the jndiReplyToName.
218: */
219: public String getJndiReplyToName() {
220: return jndiReplyToName;
221: }
222:
223: /**
224: * @param jndiReplyToName The jndiReplyToName to set.
225: */
226: public void setJndiReplyToName(String jndiReplyToName) {
227: this .jndiReplyToName = jndiReplyToName;
228: }
229:
230: /**
231: * The name of the reply destination create by a call to
232: * <code>Session.createQueue</code> or <code>Session.createTopic</code>.
233: * This property is used when <code>jndiReplyToName</code> is
234: * <code>null</code>. Optional: a temporary queue will be used
235: * if a replyTo is not provided.
236: *
237: * @return Returns the jmsProviderReplyToName.
238: */
239: public String getJmsProviderReplyToName() {
240: return jmsProviderReplyToName;
241: }
242:
243: /**
244: * @param jmsProviderReplyToName The jmsProviderReplyToName to set.
245: */
246: public void setJmsProviderReplyToName(String jmsProviderReplyToName) {
247: this .jmsProviderReplyToName = jmsProviderReplyToName;
248: }
249:
250: /**
251: * The name of the JMS ConnectionFactory to lookup in JNDI.
252: * Used if <code>connectionFactory</code> is <code>null</code>
253: *
254: * @return Returns the jndiConnectionFactoryName.
255: */
256: public String getJndiConnectionFactoryName() {
257: return jndiConnectionFactoryName;
258: }
259:
260: /**
261: * @param jndiConnectionFactoryName The jndiConnectionFactoryName to set.
262: */
263: public void setJndiConnectionFactoryName(
264: String jndiConnectionFactoryName) {
265: this .jndiConnectionFactoryName = jndiConnectionFactoryName;
266: }
267:
268: /**
269: * The name of the JMS Destination to lookup in JNDI.
270: * Used if <code>destination</code> is <code>null</code>.
271: *
272: * @return Returns the jndiDestinationName.
273: */
274: public String getJndiDestinationName() {
275: return jndiDestinationName;
276: }
277:
278: /**
279: * @param jndiDestinationName The jndiDestinationName to set.
280: */
281: public void setJndiDestinationName(String jndiDestinationName) {
282: this .jndiDestinationName = jndiDestinationName;
283: }
284:
285: /**
286: * The provider URL used to create the JNDI context.
287: *
288: * @return Returns the jndiProviderURL.
289: */
290: public String getJndiProviderURL() {
291: return jndiProviderURL;
292: }
293:
294: /**
295: * @param jndiProviderURL The jndiProviderURL to set.
296: */
297: public void setJndiProviderURL(String jndiProviderURL) {
298: this .jndiProviderURL = jndiProviderURL;
299: }
300:
301: /**
302: * Used to select the destination type used with the jmsProviderDestinationName.
303: * Can be <code>queue</code> or <code>topic</code>.
304: *
305: * @return Returns the destinationStyle.
306: */
307: public String getDestinationStyle() {
308: return destinationStyle;
309: }
310:
311: /**
312: * @param destinationStyle The destinationStyle to set.
313: */
314: public void setDestinationStyle(String destinationStyle) {
315: this .destinationStyle = destinationStyle;
316: }
317:
318: /**
319: * A configured ConnectionFactory to use on this endpoint.
320: *
321: * @return Returns the connectionFactory.
322: */
323: public ConnectionFactory getConnectionFactory() {
324: return connectionFactory;
325: }
326:
327: /**
328: * @param connectionFactory The connectionFactory to set.
329: */
330: public void setConnectionFactory(ConnectionFactory connectionFactory) {
331: this .connectionFactory = connectionFactory;
332: }
333:
334: /**
335: * A configured Destination to use on this endpoint.
336: *
337: * @return Returns the destination.
338: */
339: public Destination getDestination() {
340: return destination;
341: }
342:
343: /**
344: * @param destination The destination to set.
345: */
346: public void setDestination(Destination destination) {
347: this .destination = destination;
348: }
349:
350: /**
351: * @return if jms properties should be spec compliant
352: */
353: public boolean isNeedJavaIdentifiers() {
354: return needJavaIdentifiers;
355: }
356:
357: /**
358: * @param needJavaIdentifiers if jms properties should be spec compliant
359: */
360: public void setNeedJavaIdentifiers(boolean needJavaIdentifiers) {
361: this .needJavaIdentifiers = needJavaIdentifiers;
362: }
363:
364: /**
365: * The role of this endpoint.
366: * Must be <code>consumer</code> or <code>provider</code>.
367: *
368: * @org.apache.xbean.Property alias="role"
369: * @param role
370: */
371: public void setRoleAsString(String role) {
372: super .setRoleAsString(role);
373: }
374:
375: /**
376: * @return Returns the store.
377: */
378: public Store getStore() {
379: return store;
380: }
381:
382: /**
383: * @param store The store to set.
384: */
385: public void setStore(Store store) {
386: this .store = store;
387: }
388:
389: /**
390: * @return Returns the storeFactory.
391: */
392: public StoreFactory getStoreFactory() {
393: return storeFactory;
394: }
395:
396: /**
397: * @param storeFactory The storeFactory to set.
398: */
399: public void setStoreFactory(StoreFactory storeFactory) {
400: this .storeFactory = storeFactory;
401: }
402:
403: protected ExchangeProcessor createProviderProcessor() {
404: return createProcessor("provider");
405: }
406:
407: protected ExchangeProcessor createConsumerProcessor() {
408: return createProcessor("consumer");
409: }
410:
411: protected ExchangeProcessor createProcessor(String type) {
412: try {
413: String procName = processorName;
414: if (processorName == null) {
415: procName = getConfiguration().getProcessorName();
416: }
417: String uri = "META-INF/services/org/apache/servicemix/jms/"
418: + procName;
419: InputStream in = loadResource(uri);
420: Properties props = new Properties();
421: props.load(in);
422: String className = props.getProperty(type);
423: Class cl = loadClass(className);
424: Constructor cns = cl
425: .getConstructor(new Class[] { getClass() });
426: return (ExchangeProcessor) cns
427: .newInstance(new Object[] { this });
428: } catch (Exception e) {
429: throw new RuntimeException(
430: "Could not create processor of type " + type
431: + " and name " + processorName, e);
432: }
433: }
434:
435: /**
436: * Attempts to load the class on the current thread context class loader or
437: * the class loader which loaded us
438: */
439: protected Class loadClass(String name)
440: throws ClassNotFoundException {
441: ClassLoader contextClassLoader = Thread.currentThread()
442: .getContextClassLoader();
443: if (contextClassLoader != null) {
444: try {
445: return contextClassLoader.loadClass(name);
446: } catch (ClassNotFoundException e) {
447: //thread context class loader didn't work out
448: }
449: }
450: return getClass().getClassLoader().loadClass(name);
451: }
452:
453: /**
454: * Loads the resource from the given URI
455: */
456: protected InputStream loadResource(String uri) {
457: // lets try the thread context class loader first
458: InputStream in = Thread.currentThread().getContextClassLoader()
459: .getResourceAsStream(uri);
460: if (in == null) {
461: in = getClass().getClassLoader().getResourceAsStream(uri);
462: if (in == null) {
463: logger.debug("Could not find resource: " + uri);
464: }
465: }
466: return in;
467: }
468:
469: protected ServiceEndpoint createExternalEndpoint() {
470: return new ExternalEndpoint(getServiceUnit().getComponent()
471: .getEPRElementName(), getLocationURI(), getService(),
472: getEndpoint(), getInterfaceName());
473: }
474:
475: protected String getLocationURI() {
476: // Need to return a real URI
477: return getService() + "#" + getEndpoint();
478: }
479:
480: protected void overrideDefinition(Definition def) {
481: Service svc = null;
482: Port port = null;
483: if (targetService != null && targetEndpoint != null) {
484: svc = def.getService(targetService);
485: port = (svc != null) ? svc.getPort(targetEndpoint) : null;
486: } else if (targetService != null) {
487: svc = def.getService(targetService);
488: if (svc != null) {
489: Iterator it = svc.getPorts().values().iterator();
490: port = (it.hasNext()) ? (Port) it.next() : null;
491: }
492: } else if (targetInterfaceName != null) {
493: Iterator it = def.getServices().values().iterator();
494: svc = it.hasNext() ? (Service) it.next() : null;
495: if (svc != null) {
496: it = svc.getPorts().values().iterator();
497: port = (it.hasNext()) ? (Port) it.next() : null;
498: }
499: } else {
500: svc = def.getService(service);
501: port = (svc != null) ? svc.getPort(endpoint) : null;
502: }
503: if (port != null) {
504: port.getExtensibilityElements().clear();
505: /*
506: if (isSoap()) {
507: SOAPAddress address = new SOAPAddressImpl();
508: address.setLocationURI(getLocationURI());
509: port.addExtensibilityElement(address);
510: def.addNamespace("soap", "http://schemas.xmlsoap.org/wsdl/soap/");
511: } else {
512: HTTPAddress address = new HTTPAddressImpl();
513: address.setLocationURI(getLocationURI());
514: port.addExtensibilityElement(address);
515: def.addNamespace("http", "http://schemas.xmlsoap.org/wsdl/http/");
516: }
517: */
518: // TODO: add binding information
519: svc.getPorts().clear();
520: svc.addPort(port);
521: definition = def;
522: }
523: }
524:
525: public String toString() {
526: return "JMSEndpoint[service: " + service + ", " + "endpoint: "
527: + endpoint + ", " + "address: " + jndiDestinationName
528: + "(" + destinationStyle + "), " + "soap: " + soap
529: + "]";
530: }
531:
532: /**
533: * Specifies the processor family to use for this endpoint.
534: * Can be:
535: * <ul>
536: * <li><code>multiplexing</code> (default)</li>
537: * <li><code>standard</code></li>
538: * <li><code>jca</code></li>
539: * </ul>
540: *
541: * @return Returns the processorName.
542: */
543: public String getProcessorName() {
544: return processorName;
545: }
546:
547: /**
548: * @param processorName The processorName to set.
549: */
550: public void setProcessorName(String processorName) {
551: this .processorName = processorName;
552: }
553:
554: public JmsConfiguration getConfiguration() {
555: JmsComponent component = (JmsComponent) getServiceUnit()
556: .getComponent();
557: return component.getConfiguration();
558: }
559:
560: public AuthenticationService getAuthenticationService() {
561: JmsComponent component = (JmsComponent) getServiceUnit()
562: .getComponent();
563: return component.getAuthenticationService();
564: }
565:
566: public KeystoreManager getKeystoreManager() {
567: JmsComponent component = (JmsComponent) getServiceUnit()
568: .getComponent();
569: return component.getKeystoreManager();
570: }
571:
572: /**
573: * Determines whether for a request/response pattern, the message id of the request message
574: * should be used as the correlation id in the response or the correlation id of the request.
575: * @return
576: */
577: public boolean isUseMsgIdInResponse() {
578: return useMsgIdInResponse;
579: }
580:
581: public void setUseMsgIdInResponse(boolean useMsgIdInResponse) {
582: this .useMsgIdInResponse = useMsgIdInResponse;
583: }
584:
585: public JmsMarshaler getMarshaler() {
586: return marshaler;
587: }
588:
589: public void setMarshaler(JmsMarshaler marshaler) {
590: this.marshaler = marshaler;
591: }
592:
593: }
|