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    }