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.eip;
018
019 import java.net.URL;
020 import java.util.Set;
021
022 import javax.activation.DataHandler;
023 import javax.jbi.JBIException;
024 import javax.jbi.messaging.ExchangeStatus;
025 import javax.jbi.messaging.MessageExchange;
026 import javax.jbi.messaging.MessagingException;
027 import javax.jbi.messaging.MessageExchange.Role;
028 import javax.jbi.messaging.NormalizedMessage;
029 import javax.jbi.servicedesc.ServiceEndpoint;
030 import javax.wsdl.Definition;
031 import javax.wsdl.WSDLException;
032 import javax.wsdl.factory.WSDLFactory;
033 import javax.wsdl.xml.WSDLReader;
034
035 import org.apache.servicemix.common.JbiConstants;
036 import org.apache.servicemix.common.endpoints.ProviderEndpoint;
037 import org.apache.servicemix.common.locks.LockManager;
038 import org.apache.servicemix.common.locks.impl.SimpleLockManager;
039 import org.apache.servicemix.eip.support.ExchangeTarget;
040 import org.apache.servicemix.jbi.marshaler.PojoMarshaler;
041 import org.apache.servicemix.store.Store;
042 import org.apache.servicemix.store.StoreFactory;
043 import org.apache.servicemix.store.memory.MemoryStoreFactory;
044 import org.apache.servicemix.timers.TimerManager;
045 import org.apache.servicemix.timers.impl.TimerManagerImpl;
046 import org.springframework.core.io.Resource;
047 import org.w3c.dom.Document;
048
049 import com.ibm.wsdl.Constants;
050
051 /**
052 * @author gnodet
053 * @version $Revision: 376451 $
054 */
055 public abstract class EIPEndpoint extends ProviderEndpoint {
056
057 /**
058 * The resource pointing to the WSDL for this endpoint
059 */
060 protected Resource wsdlResource;
061
062 /**
063 * The store to keep pending exchanges
064 */
065 protected Store store;
066 /**
067 * The store factory.
068 */
069 protected StoreFactory storeFactory;
070 /**
071 * The lock manager.
072 */
073 protected LockManager lockManager;
074 /**
075 * The timer manager.
076 */
077 protected TimerManager timerManager;
078
079 /**
080 * The ExchangeTarget to use to get the WSDL
081 */
082 protected ExchangeTarget wsdlExchangeTarget;
083
084 /**
085 * @return Returns the store.
086 */
087 public Store getStore() {
088 return store;
089 }
090 /**
091 * @param store The store to set.
092 */
093 public void setStore(Store store) {
094 this.store = store;
095 }
096 /**
097 * @return Returns the storeFactory.
098 */
099 public StoreFactory getStoreFactory() {
100 return storeFactory;
101 }
102 /**
103 * @param storeFactory The storeFactory to set.
104 */
105 public void setStoreFactory(StoreFactory storeFactory) {
106 this.storeFactory = storeFactory;
107 }
108 /**
109 * @return the lockManager
110 */
111 public LockManager getLockManager() {
112 return lockManager;
113 }
114 /**
115 * @param lockManager the lockManager to set
116 */
117 public void setLockManager(LockManager lockManager) {
118 this.lockManager = lockManager;
119 }
120 /**
121 * @return the timerManager
122 */
123 public TimerManager getTimerManager() {
124 return timerManager;
125 }
126 /**
127 * @param timerManager the timerManager to set
128 */
129 public void setTimerManager(TimerManager timerManager) {
130 this.timerManager = timerManager;
131 }
132
133 public void start() throws Exception {
134 super.start();
135 if (store == null) {
136 if (storeFactory == null) {
137 storeFactory = new MemoryStoreFactory();
138 }
139 store = storeFactory.open(getService().toString() + getEndpoint());
140 }
141 if (lockManager == null) {
142 lockManager = new SimpleLockManager();
143 }
144 if (timerManager == null) {
145 timerManager = new TimerManagerImpl();
146 }
147 timerManager.start();
148 }
149
150 public void stop() throws Exception {
151 if (timerManager != null) {
152 timerManager.stop();
153 }
154 super.stop();
155 }
156
157 /* (non-Javadoc)
158 * @see org.apache.servicemix.common.ExchangeProcessor#process(javax.jbi.messaging.MessageExchange)
159 */
160 public void process(MessageExchange exchange) throws Exception {
161 boolean txSync = exchange.isTransacted() && Boolean.TRUE.equals(exchange.getProperty(JbiConstants.SEND_SYNC));
162 if (txSync && exchange.getRole() == Role.PROVIDER && exchange.getStatus() == ExchangeStatus.ACTIVE) {
163 processSync(exchange);
164 } else {
165 processAsync(exchange);
166 }
167 }
168
169 /**
170 * @return Returns the description.
171 */
172 public Document getDescription() {
173 if (description == null) {
174 definition = getDefinition();
175 if (definition != null) {
176 try {
177 description = WSDLFactory.newInstance().newWSDLWriter().getDocument(definition);
178 } catch (WSDLException e) {
179 // Ignore
180 }
181 }
182 }
183 return description;
184 }
185
186 /**
187 * If the definition is not currently set, it tries to set it using
188 * the following sources in the order:
189 * description, wsdlResource, wsdlExchangeTarget
190 *
191 * @return Returns the definition.
192 */
193 public Definition getDefinition() {
194 if (definition == null) {
195 definition = getDefinitionFromDescription();
196 if (definition == null) {
197 definition = getDefinitionFromWsdlResource();
198 if (definition == null) {
199 definition = getDefinitionFromWsdlExchangeTarget();
200 }
201 }
202 }
203 return definition;
204 }
205
206 protected Definition getDefinitionFromDescription() {
207 if (description != null) {
208 try {
209 WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
210 reader.setFeature(Constants.FEATURE_VERBOSE, false);
211 return reader.readWSDL(null, description);
212 } catch (WSDLException ignore) {
213 // Ignore
214 }
215 }
216 return null;
217 }
218
219 protected Definition getDefinitionFromWsdlResource() {
220 if (wsdlResource != null) {
221 try {
222 URL resource = wsdlResource.getURL();
223 WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
224 reader.setFeature(Constants.FEATURE_VERBOSE, false);
225 return reader.readWSDL(null, resource.toString());
226 } catch (Throwable ignore) {
227 // Ignore
228 }
229 }
230 return null;
231 }
232
233 protected Definition getDefinitionFromWsdlExchangeTarget() {
234 if (wsdlExchangeTarget != null) {
235 try {
236 Document description = getDescriptionForExchangeTarget(wsdlExchangeTarget);
237 WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
238 reader.setFeature(Constants.FEATURE_VERBOSE, false);
239 return reader.readWSDL(null, description);
240 } catch (Throwable ignore) {
241 // Ignore
242 }
243 }
244 return null;
245 }
246
247 /**
248 * @return Returns the wsdl's Resource.
249 */
250 public Resource getWsdlResource() {
251 return wsdlResource;
252 }
253 public void setWsdlResource(Resource wsdlResource) {
254 this.wsdlResource = wsdlResource;
255 }
256
257 protected Document getDescriptionForExchangeTarget(ExchangeTarget match) throws JBIException {
258 ServiceEndpoint[] endpoints = getEndpointsForExchangeTarget(match);
259 if (endpoints == null || endpoints.length == 0) {
260 return null;
261 }
262 ServiceEndpoint endpoint = chooseFirstEndpointWithDescriptor(endpoints);
263 if (endpoint == null) {
264 return null;
265 }
266 return getContext().getEndpointDescriptor(endpoint);
267 }
268
269 /**
270 *
271 * @param match
272 * @return an ServiceEndpoint[] of all the endpoints that matched.
273 * @throws JBIException
274 */
275 protected ServiceEndpoint[] getEndpointsForExchangeTarget(ExchangeTarget match) throws JBIException {
276 ServiceEndpoint[] endpoints;
277 if (match.getEndpoint() != null && match.getService() != null) {
278 ServiceEndpoint endpoint = getContext().getEndpoint(match.getService(), match.getEndpoint());
279 if (endpoint == null) {
280 endpoints = new ServiceEndpoint[0];
281 } else {
282 endpoints = new ServiceEndpoint[] {endpoint };
283 }
284 } else if (match.getService() != null) {
285 endpoints = getContext().getEndpointsForService(match.getService());
286 } else if (interfaceName != null) {
287 endpoints = getContext().getEndpoints(interfaceName);
288 } else {
289 throw new IllegalStateException("One of interfaceName or serviceName should be provided");
290 }
291 return endpoints;
292 }
293
294 protected ServiceEndpoint chooseFirstEndpointWithDescriptor(ServiceEndpoint[] endpoints) throws JBIException {
295 for (int i = 0; i < endpoints.length; i++) {
296 if (getContext().getEndpointDescriptor(endpoints[i]) != null) {
297 return endpoints[i];
298 }
299 }
300 return null;
301 }
302
303
304 protected abstract void processAsync(MessageExchange exchange) throws Exception;
305
306 protected abstract void processSync(MessageExchange exchange) throws Exception;
307
308 public ExchangeTarget getWsdlExchangeTarget() {
309 return wsdlExchangeTarget;
310 }
311 public void setWsdlExchangeTarget(ExchangeTarget wsdlExchangeTarget) {
312 this.wsdlExchangeTarget = wsdlExchangeTarget;
313 }
314
315 /**
316 * Copies properties from one message to another that do not already exist
317 *
318 * @param from the message containing the properties
319 * @param to the destination message where the properties are set
320 */
321 protected void copyProperties(NormalizedMessage from, NormalizedMessage to) {
322 for (String propertyName : (Set<String>) from.getPropertyNames()) {
323 // Do not copy existing properties or transient properties
324 if (to.getProperty(propertyName) == null && !PojoMarshaler.BODY.equals(propertyName)) {
325 Object value = from.getProperty(propertyName);
326 to.setProperty(propertyName, value);
327 }
328 }
329 }
330
331 /**
332 * Copies attachments from one message to another that do not already exist
333 *
334 * @param from the message with the attachments
335 * @param to the destination message where the attachments are to be added
336 * @throws javax.jbi.messaging.MessagingException if an attachment could not be added
337 */
338 protected void copyAttachments(NormalizedMessage from, NormalizedMessage to) throws MessagingException {
339 for (String attachmentName : (Set<String>) from.getAttachmentNames()) {
340 // Do not copy existing attachments
341 if (to.getAttachment(attachmentName) == null) {
342 DataHandler value = from.getAttachment(attachmentName);
343 to.addAttachment(attachmentName, value);
344 }
345 }
346 }
347 }