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.bpmscript.jbi;
018:
019: import java.lang.reflect.InvocationHandler;
020: import java.lang.reflect.Method;
021: import java.util.Arrays;
022: import java.util.Collection;
023: import java.util.HashSet;
024: import java.util.Map;
025: import java.util.Set;
026: import java.util.concurrent.ConcurrentHashMap;
027:
028: import javax.jbi.messaging.InOut;
029: import javax.jbi.messaging.NormalizedMessage;
030: import javax.jbi.servicedesc.ServiceEndpoint;
031: import javax.xml.namespace.QName;
032:
033: import org.apache.servicemix.client.DefaultServiceMixClient;
034: import org.apache.servicemix.jbi.messaging.PojoMarshaler;
035: import org.apache.servicemix.jbi.resolver.ServiceNameEndpointResolver;
036: import org.bpmscript.ExceptionMapper;
037: import org.bpmscript.TimeoutRuntimeException;
038:
039: public class PojoServiceProxy implements InvocationHandler {
040:
041: private DefaultServiceMixClient client;
042: private PojoMarshaler marshaler;
043: private QName service;
044: private long timeout;
045: private ExceptionMapper exceptionMapper;
046: private Map<Method, Set<Class>> exceptionCache = new ConcurrentHashMap<Method, Set<Class>>();
047:
048: public PojoServiceProxy(DefaultServiceMixClient client,
049: PojoMarshaler marshaler, QName service, long timeout,
050: ExceptionMapper exceptionMapper) {
051: this .client = client;
052: this .marshaler = marshaler;
053: this .service = service;
054: this .exceptionMapper = exceptionMapper;
055: this .timeout = timeout;
056: }
057:
058: public boolean isAvailable() {
059: ServiceEndpoint[] endpointsForService = client.getContext()
060: .getEndpointsForService(service);
061: return endpointsForService != null
062: && endpointsForService.length > 0;
063: }
064:
065: @SuppressWarnings("unchecked")
066: public Object invoke(Object proxy, Method method, Object[] args)
067: throws Throwable {
068: if (method.getDeclaringClass() == IRemoteService.class
069: && method.getName().equals("isAvailable")) {
070: return isAvailable();
071: }
072: try {
073: InOut out = client
074: .createInOutExchange(new ServiceNameEndpointResolver(
075: service));
076: NormalizedMessage inMessage = out.getInMessage();
077: inMessage.setProperty("method", method.getName());
078: marshaler.marshal(out, inMessage, args);
079: boolean processed = client.sendSync(out, timeout);
080: if (!processed) {
081: throw new TimeoutRuntimeException(service
082: + " timed out after " + timeout + "ms");
083: }
084: if (out.getError() != null) {
085: throw out.getError();
086: }
087: return marshaler.unmarshal(out, out.getOutMessage());
088: } catch (Throwable e) {
089: Set<Class> set = exceptionCache.get(method);
090: if (set == null) {
091: set = new HashSet<Class>(Arrays.asList(method
092: .getExceptionTypes()));
093: exceptionCache.put(method, set);
094: }
095: for (Class exClass : set) {
096: if (exClass.isAssignableFrom(e.getClass())) {
097: throw e;
098: }
099: }
100: throw exceptionMapper.getException(e);
101: }
102: }
103:
104: }
|