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.components.util;
018
019 import javax.jbi.component.Component;
020 import javax.jbi.component.ComponentLifeCycle;
021 import javax.jbi.component.ServiceUnitManager;
022 import javax.jbi.messaging.DeliveryChannel;
023 import javax.jbi.messaging.InOnly;
024 import javax.jbi.messaging.InOptionalOut;
025 import javax.jbi.messaging.InOut;
026 import javax.jbi.messaging.MessageExchange;
027 import javax.jbi.messaging.MessageExchangeFactory;
028 import javax.jbi.messaging.MessagingException;
029 import javax.jbi.messaging.NormalizedMessage;
030 import javax.jbi.messaging.RobustInOnly;
031 import javax.jbi.servicedesc.ServiceEndpoint;
032 import javax.xml.namespace.QName;
033
034 import org.w3c.dom.Document;
035 import org.w3c.dom.DocumentFragment;
036
037 import org.apache.servicemix.JbiConstants;
038 import org.apache.servicemix.jbi.NoInMessageAvailableException;
039
040 /**
041 * A useful base class for developers wishing to implement a JBI Component.
042 *
043 * @version $Revision: 564374 $
044 */
045 public abstract class ComponentSupport extends PojoSupport implements Component {
046
047 private ComponentLifeCycle lifeCycle;
048 private ServiceUnitManager serviceManager;
049 private MessageTransformer messageTransformer = CopyTransformer.getInstance();
050
051 protected ComponentSupport() {
052 }
053
054
055 protected ComponentSupport(QName service, String endpoint) {
056 super(service, endpoint);
057 }
058
059 /**
060 * @return the lifecycel control implementation
061 */
062 public ComponentLifeCycle getLifeCycle() {
063 synchronized (this) {
064 if (lifeCycle == null) {
065 lifeCycle = createComponentLifeCycle();
066 }
067 }
068 return lifeCycle;
069 }
070
071 /**
072 * @return the ServiceUnitManager or null if there isn't one
073 */
074 public ServiceUnitManager getServiceUnitManager() {
075 initializeServiceUnitManager();
076 return serviceManager;
077 }
078
079 /**
080 * @param fragment
081 * @return the description of the specified reference
082 */
083 public ServiceEndpoint resolveEndpointReference(DocumentFragment fragment) {
084 return null;
085 }
086
087 /**
088 * Retrieves a DOM representation containing metadata which describes the
089 * service provided by this component, through the given endpoint. The
090 * result can use WSDL 1.1 or WSDL 2.0.
091 *
092 * @param endpoint the service endpoint.
093 * @return the description for the specified service endpoint.
094 */
095
096 public Document getServiceDescription(ServiceEndpoint endpoint) {
097 return null;
098 }
099
100 /**
101 * This method is called by JBI to check if this component, in the role of
102 * provider of the service indicated by the given exchange, can actually
103 * perform the operation desired.
104 *
105 * @param endpoint the endpoint to be used by the consumer; must be
106 * non-null.
107 * @param exchange the proposed message exchange to be performed; must be
108 * non-null.
109 * @return <code>true</code> if this provider component can perform the
110 * given exchange with the described consumer.
111 */
112 public boolean isExchangeWithConsumerOkay(ServiceEndpoint endpoint,
113 MessageExchange exchange) {
114 return true;
115 }
116
117 /**
118 * This method is called by JBI to check if this component, in the role of
119 * consumer of the service indicated by the given exchange, can actually
120 * interact with the provider properly. The provider is described by the
121 * given endpoint and the service description supplied by that endpoint.
122 *
123 * @param endpoint the endpoint to be used by the provider; must be
124 * non-null.
125 * @param exchange the proposed message exchange to be performed; must be
126 * non-null.
127 * @return <code>true</code> if this consumer component can interact with
128 * the described provider to perform the given exchange.
129 */
130 public boolean isExchangeWithProviderOkay(ServiceEndpoint endpoint,
131 MessageExchange exchange) {
132 return true;
133 }
134
135 // Implementation methods
136 //-------------------------------------------------------------------------
137
138 protected synchronized void initializeServiceUnitManager() {
139 if (this.serviceManager == null) {
140 this.serviceManager = createServiceUnitManager();
141 }
142 }
143
144 protected ServiceUnitManager createServiceUnitManager() {
145 return new ServiceUnitManagerSupport();
146 }
147
148 protected ComponentLifeCycle createComponentLifeCycle() {
149 return this;
150 }
151
152
153 /**
154 * Returns the in message or throws an exception if there is no in message.
155 */
156 protected NormalizedMessage getInMessage(MessageExchange exchange) throws NoInMessageAvailableException {
157 NormalizedMessage message = exchange.getMessage("in");
158 if (message == null) {
159 throw new NoInMessageAvailableException(exchange);
160 }
161 return message;
162 }
163
164 public MessageTransformer getMessageTransformer() {
165 return messageTransformer;
166 }
167
168 public void setMessageTransformer(MessageTransformer transformer) {
169 this.messageTransformer = transformer;
170 }
171
172 /**
173 * Performs an invocation where the service, operation or interface name could be specified
174 *
175 * @param exchange
176 * @param in
177 * @param service
178 * @param interfaceName
179 * @param operation
180 */
181 public void invoke(MessageExchange exchange, NormalizedMessage in,
182 QName service, QName interfaceName, QName operation) throws MessagingException {
183 InOnly outExchange = createInOnlyExchange(service, interfaceName, operation);
184 forwardToExchange(exchange, outExchange, in, operation);
185 }
186
187 /**
188 * Creates a new InOnly exchange for the given service, interface and/or operation (any of which can be null).
189 */
190 public InOnly createInOnlyExchange(QName service, QName interfaceName, QName operation) throws MessagingException {
191 DeliveryChannel channel = getDeliveryChannel();
192 MessageExchangeFactory factory = null;
193 if (service != null) {
194 factory = channel.createExchangeFactoryForService(service);
195 } else if (interfaceName != null) {
196 factory = channel.createExchangeFactory(interfaceName);
197 } else {
198 factory = getExchangeFactory();
199 }
200 InOnly outExchange = factory.createInOnlyExchange();
201 if (service != null) {
202 outExchange.setService(service);
203 }
204 if (interfaceName != null) {
205 outExchange.setInterfaceName(interfaceName);
206 }
207 if (operation != null) {
208 outExchange.setOperation(operation);
209 }
210 return outExchange;
211 }
212
213 public InOnly createInOnlyExchange(QName service, QName interfaceName,
214 QName operation, MessageExchange beforeExchange) throws MessagingException {
215 InOnly inOnly = createInOnlyExchange(service, interfaceName, operation);
216 propagateCorrelationId(beforeExchange, inOnly);
217 return inOnly;
218 }
219
220 /**
221 * Creates a new InOut exchange for the given service, interface and/or operation (any of which can be null).
222 */
223 public InOut createInOutExchange(QName service, QName interfaceName, QName operation) throws MessagingException {
224 DeliveryChannel channel = getDeliveryChannel();
225 MessageExchangeFactory factory = null;
226 if (service != null) {
227 factory = channel.createExchangeFactoryForService(service);
228 } else if (interfaceName != null) {
229 factory = channel.createExchangeFactory(interfaceName);
230 } else {
231 factory = getExchangeFactory();
232 }
233 InOut outExchange = factory.createInOutExchange();
234 if (service != null) {
235 outExchange.setService(service);
236 }
237 if (interfaceName != null) {
238 outExchange.setInterfaceName(interfaceName);
239 }
240 if (operation != null) {
241 outExchange.setOperation(operation);
242 }
243 return outExchange;
244 }
245
246 public InOut creatInOutExchange(QName service, QName interfaceName,
247 QName operation, MessageExchange srcExchange) throws MessagingException {
248 InOut inOut = createInOutExchange(service, interfaceName, operation);
249 propagateCorrelationId(srcExchange, inOut);
250 return inOut;
251 }
252
253 /**
254 * Creates an InOnly exchange and propagates the correlation id from the given exchange
255 * to the newly created exchange
256 * @param srcExchange
257 * @return InOnly
258 * @throws MessagingException
259 */
260 public InOnly createInOnlyExchange(MessageExchange srcExchange) throws MessagingException {
261 MessageExchangeFactory factory = getExchangeFactory();
262 InOnly inOnly = factory.createInOnlyExchange();
263
264 propagateCorrelationId(srcExchange, inOnly);
265
266 return inOnly;
267 }
268
269 /**
270 * Creates an InOptionalOut exchange and propagates the correlation id from the given exchange
271 * to the newly created exchange
272 * @param srcExchange
273 * @return InOptionalOut
274 * @throws MessagingException
275 */
276 public InOptionalOut createInOptionalOutExchange(MessageExchange srcExchange) throws MessagingException {
277 MessageExchangeFactory factory = getExchangeFactory();
278 InOptionalOut inOptionalOut = factory.createInOptionalOutExchange();
279
280 propagateCorrelationId(srcExchange, inOptionalOut);
281
282 return inOptionalOut;
283 }
284
285 /**
286 * Creates an InOut exchange and propagates the correlation id from the given exchange
287 * to the newly created exchange
288 * @param srcExchange
289 * @return InOut
290 * @throws MessagingException
291 */
292 public InOut createInOutExchange(MessageExchange srcExchange) throws MessagingException {
293 MessageExchangeFactory factory = getExchangeFactory();
294 InOut inOut = factory.createInOutExchange();
295
296 propagateCorrelationId(srcExchange, inOut);
297
298 return inOut;
299 }
300
301 /**
302 * Creates an RobustInOnly exchange and propagates the correlation id from the given exchange
303 * to the newly created exchange
304 * @param srcExchange
305 * @return RobustInOnly the created exchange
306 * @throws MessagingException
307 */
308 public RobustInOnly createRobustInOnlyExchange(MessageExchange srcExchange) throws MessagingException {
309 MessageExchangeFactory factory = getExchangeFactory();
310 RobustInOnly robustInOnly = factory.createRobustInOnlyExchange();
311
312 propagateCorrelationId(srcExchange, robustInOnly);
313
314 return robustInOnly;
315 }
316
317 /**
318 * Propagates the correlation id from an exchange to a newly created exchange
319 * @param source Exchange which already exists
320 * @param dest Newly created exchange which should get the correlation id
321 */
322 public void propagateCorrelationId(MessageExchange source, MessageExchange dest) {
323 if (source == null || dest == null) {
324 return;
325 }
326 String correlationId = (String) source.getProperty(JbiConstants.CORRELATION_ID);
327 if (correlationId != null) {
328 dest.setProperty(JbiConstants.CORRELATION_ID, correlationId);
329 } else {
330 dest.setProperty(JbiConstants.CORRELATION_ID, source.getExchangeId());
331 }
332 }
333
334 protected void forwardToExchange(MessageExchange exchange, InOnly outExchange,
335 NormalizedMessage in, QName operationName) throws MessagingException {
336 if (operationName != null) {
337 exchange.setOperation(operationName);
338 }
339 forwardToExchange(exchange, outExchange, in);
340 }
341
342 protected void forwardToExchange(MessageExchange exchange, InOnly outExchange, NormalizedMessage in) throws MessagingException {
343 NormalizedMessage out = outExchange.createMessage();
344 outExchange.setInMessage(out);
345 getMessageTransformer().transform(exchange, in, out);
346 getDeliveryChannel().send(outExchange);
347 }
348 }