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.jbi.messaging;
018    
019    import java.net.URI;
020    import java.text.SimpleDateFormat;
021    import java.util.GregorianCalendar;
022    import java.util.concurrent.atomic.AtomicBoolean;
023    
024    import javax.jbi.messaging.InOnly;
025    import javax.jbi.messaging.InOptionalOut;
026    import javax.jbi.messaging.InOut;
027    import javax.jbi.messaging.MessageExchange;
028    import javax.jbi.messaging.MessageExchangeFactory;
029    import javax.jbi.messaging.MessagingException;
030    import javax.jbi.messaging.RobustInOnly;
031    import javax.jbi.servicedesc.ServiceEndpoint;
032    import javax.xml.namespace.QName;
033    
034    import org.apache.servicemix.JbiConstants;
035    import org.apache.servicemix.id.IdGenerator;
036    import org.apache.servicemix.jbi.framework.ComponentContextImpl;
037    
038    /**
039     * Resolver for URI patterns
040     * 
041     * @version $Revision: 564607 $
042     */
043    public class MessageExchangeFactoryImpl implements MessageExchangeFactory {
044    
045        private QName interfaceName;
046    
047        private QName serviceName;
048    
049        private QName operationName;
050    
051        private ServiceEndpoint endpoint;
052    
053        private IdGenerator idGenerator;
054    
055        private ComponentContextImpl context;
056    
057        private AtomicBoolean closed;
058    
059        /**
060         * Constructor for a factory
061         * 
062         * @param idGen
063         */
064        public MessageExchangeFactoryImpl(IdGenerator idGen, AtomicBoolean closed) {
065            this.idGenerator = idGen;
066            this.closed = closed;
067        }
068    
069        protected void checkNotClosed() throws MessagingException {
070            if (closed.get()) {
071                throw new MessagingException("DeliveryChannel has been closed.");
072            }
073        }
074    
075        /**
076         * Create an exchange from the specified pattern
077         * 
078         * @param pattern
079         * @return MessageExchange
080         * @throws MessagingException
081         */
082        public MessageExchange createExchange(URI pattern) throws MessagingException {
083            checkNotClosed();
084            MessageExchange result = null;
085            if (pattern != null) {
086                if (pattern.equals(MessageExchangeSupport.IN_ONLY) || pattern.equals(MessageExchangeSupport.WSDL2_IN_ONLY)) {
087                    result = createInOnlyExchange();
088                } else if (pattern.equals(MessageExchangeSupport.IN_OUT) || pattern.equals(MessageExchangeSupport.WSDL2_IN_OUT)) {
089                    result = createInOutExchange();
090                } else if (pattern.equals(MessageExchangeSupport.IN_OPTIONAL_OUT)
091                                || pattern.equals(MessageExchangeSupport.WSDL2_IN_OPTIONAL_OUT)) {
092                    result = createInOptionalOutExchange();
093                } else if (pattern.equals(MessageExchangeSupport.ROBUST_IN_ONLY)
094                                || pattern.equals(MessageExchangeSupport.WSDL2_ROBUST_IN_ONLY)) {
095                    result = createRobustInOnlyExchange();
096                }
097            }
098            if (result == null) {
099                throw new MessagingException("Do not understand pattern: " + pattern);
100            }
101            return result;
102        }
103    
104        /**
105         * create InOnly exchange
106         * 
107         * @return InOnly exchange
108         * @throws MessagingException
109         */
110        public InOnly createInOnlyExchange() throws MessagingException {
111            checkNotClosed();
112            InOnlyImpl result = new InOnlyImpl(getExchangeId());
113            setDefaults(result);
114            return result;
115        }
116    
117        /**
118         * create RobustInOnly exchange
119         * 
120         * @return RobsutInOnly exchange
121         * @throws MessagingException
122         */
123        public RobustInOnly createRobustInOnlyExchange() throws MessagingException {
124            checkNotClosed();
125            RobustInOnlyImpl result = new RobustInOnlyImpl(getExchangeId());
126            setDefaults(result);
127            return result;
128        }
129    
130        /**
131         * create InOut Exchange
132         * 
133         * @return InOut exchange
134         * @throws MessagingException
135         */
136        public InOut createInOutExchange() throws MessagingException {
137            checkNotClosed();
138            InOutImpl result = new InOutImpl(getExchangeId());
139            setDefaults(result);
140            return result;
141        }
142    
143        /**
144         * create InOptionalOut exchange
145         * 
146         * @return InOptionalOut exchange
147         * @throws MessagingException
148         */
149        public InOptionalOut createInOptionalOutExchange() throws MessagingException {
150            checkNotClosed();
151            InOptionalOutImpl result = new InOptionalOutImpl(getExchangeId());
152            setDefaults(result);
153            return result;
154        }
155    
156        /**
157         * Create an exchange that points at an endpoint that conforms to the
158         * declared capabilities, requirements, and policies of both the consumer
159         * and the provider.
160         * 
161         * @param svcName
162         * @param opName
163         *            the WSDL name of the operation to be performed
164         * @return a message exchange that is initialized with given interfaceName,
165         *         operationName, and the endpoint decided upon by JBI.
166         * @throws MessagingException
167         */
168        public MessageExchange createExchange(QName svcName, QName opName) throws MessagingException {
169            // TODO: look for the operation in the wsdl and infer the MEP
170            checkNotClosed();
171            InOptionalOutImpl me = new InOptionalOutImpl(getExchangeId());
172            setDefaults(me);
173            me.setService(svcName);
174            me.setOperation(opName);
175            return me;
176        }
177    
178        protected String getExchangeId() {
179            return idGenerator.generateId();
180        }
181    
182        /**
183         * @return endpoint
184         */
185        public ServiceEndpoint getEndpoint() {
186            return endpoint;
187        }
188    
189        /**
190         * set endpoint
191         * 
192         * @param endpoint
193         */
194        public void setEndpoint(ServiceEndpoint endpoint) {
195            this.endpoint = endpoint;
196        }
197    
198        /**
199         * @return interface name
200         */
201        public QName getInterfaceName() {
202            return interfaceName;
203        }
204    
205        /**
206         * set interface name
207         * 
208         * @param interfaceName
209         */
210        public void setInterfaceName(QName interfaceName) {
211            this.interfaceName = interfaceName;
212        }
213    
214        /**
215         * @return service name
216         */
217        public QName getServiceName() {
218            return serviceName;
219        }
220    
221        /**
222         * set service name
223         * 
224         * @param serviceName
225         */
226        public void setServiceName(QName serviceName) {
227            this.serviceName = serviceName;
228        }
229    
230        /**
231         * @return Returns the operationName.
232         */
233        public QName getOperationName() {
234            return operationName;
235        }
236    
237        /**
238         * @param operationName
239         *            The operationName to set.
240         */
241        public void setOperationName(QName operationName) {
242            this.operationName = operationName;
243        }
244    
245        /**
246         * Get the Context
247         * 
248         * @return the context
249         */
250        public ComponentContextImpl getContext() {
251            return context;
252        }
253    
254        /**
255         * Set the Context
256         * 
257         * @param context
258         */
259        public void setContext(ComponentContextImpl context) {
260            this.context = context;
261        }
262    
263        protected void setDefaults(MessageExchangeImpl exchange) {
264            exchange.setOperation(getOperationName());
265            if (endpoint != null) {
266                exchange.setEndpoint(getEndpoint());
267            } else {
268                exchange.setService(serviceName);
269                exchange.setInterfaceName(interfaceName);
270            }
271    
272            if (getContext() != null) {
273                exchange.setSourceContext(getContext());
274                PojoMarshaler marshaler = getContext().getActivationSpec().getMarshaler();
275                if (marshaler != null) {
276                    exchange.setMarshaler(marshaler);
277                }
278            }
279            exchange.setProperty(JbiConstants.DATESTAMP_PROPERTY_NAME, new PrettyCalendar());
280        }
281    
282        @SuppressWarnings("serial")
283        public static class PrettyCalendar extends GregorianCalendar {
284            public String toString() {
285                return new SimpleDateFormat().format(getTime());
286            }
287        }
288    }