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 */
017package org.apache.camel.component.bean;
018
019import java.lang.reflect.Proxy;
020
021import org.apache.camel.Endpoint;
022import org.apache.camel.Producer;
023import org.apache.camel.processor.DeferServiceFactory;
024
025/**
026 * A helper class for creating proxies which delegate to Camel
027 *
028 * @version 
029 */
030public final class ProxyHelper {
031
032    /**
033     * Utility classes should not have a public constructor.
034     */
035    private ProxyHelper() {
036    }
037
038    /**
039     * Creates a Proxy which sends the exchange to the endpoint.
040     *
041     * @deprecated use the same method name with binding as parameter
042     */
043    @SuppressWarnings("unchecked")
044    @Deprecated
045    public static <T> T createProxyObject(Endpoint endpoint, Producer producer, ClassLoader classLoader, Class<T>[] interfaces, MethodInfoCache methodCache) {
046        return createProxyObject(endpoint, true, producer, classLoader, interfaces, methodCache);
047    }
048
049    /**
050     * Creates a Proxy which sends the exchange to the endpoint.
051     */
052    @SuppressWarnings("unchecked")
053    public static <T> T createProxyObject(Endpoint endpoint, boolean binding, Producer producer, ClassLoader classLoader, Class<T>[] interfaces, MethodInfoCache methodCache) {
054        return (T) Proxy.newProxyInstance(classLoader, interfaces.clone(), new CamelInvocationHandler(endpoint, binding, producer, methodCache));
055    }
056
057    /**
058     * Creates a Proxy which sends the exchange to the endpoint.
059     *
060     * @deprecated use the same method name with binding as parameter
061     */
062    @Deprecated
063    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T> interfaceClass, MethodInfoCache methodCache) throws Exception {
064        return createProxy(endpoint, true, cl, toArray(interfaceClass), methodCache);
065    }
066
067    /**
068     * Creates a Proxy which sends the exchange to the endpoint.
069     */
070    public static <T> T createProxy(Endpoint endpoint, boolean binding, ClassLoader cl, Class<T> interfaceClass, MethodInfoCache methodCache) throws Exception {
071        return createProxy(endpoint, binding, cl, toArray(interfaceClass), methodCache);
072    }
073
074    /**
075     * Creates a Proxy which sends the exchange to the endpoint.
076     *
077     * @deprecated use the same method name with binding as parameter
078     */
079    @Deprecated
080    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T>[] interfaceClasses, MethodInfoCache methodCache) throws Exception {
081        return createProxy(endpoint, true, cl, interfaceClasses, methodCache);
082    }
083
084    /**
085     * Creates a Proxy which sends the exchange to the endpoint.
086     */
087    public static <T> T createProxy(Endpoint endpoint, boolean binding, ClassLoader cl, Class<T>[] interfaceClasses, MethodInfoCache methodCache) throws Exception {
088        Producer producer = DeferServiceFactory.createProducer(endpoint);
089        endpoint.getCamelContext().deferStartService(producer, true);
090        return createProxyObject(endpoint, binding, producer, cl, interfaceClasses, methodCache);
091    }
092
093    /**
094     * Creates a Proxy which sends the exchange to the endpoint.
095     */
096    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T> interfaceClass) throws Exception {
097        return createProxy(endpoint, true, cl, toArray(interfaceClass));
098    }
099
100    /**
101     * Creates a Proxy which sends the exchange to the endpoint.
102     *
103     * @deprecated use the same method name with binding as parameter
104     */
105    @Deprecated
106    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T>... interfaceClasses) throws Exception {
107        return createProxy(endpoint, true, cl, interfaceClasses);
108    }
109
110    /**
111     * Creates a Proxy which sends the exchange to the endpoint.
112     */
113    public static <T> T createProxy(Endpoint endpoint, boolean binding, ClassLoader cl, Class<T>... interfaceClasses) throws Exception {
114        return createProxy(endpoint, binding, cl, interfaceClasses, createMethodInfoCache(endpoint));
115    }
116
117    /**
118     * Creates a Proxy which sends the exchange to the endpoint.
119     */
120    public static <T> T createProxy(Endpoint endpoint, Class<T> interfaceClass) throws Exception {
121        return createProxy(endpoint, true, toArray(interfaceClass));
122    }
123
124    /**
125     * Creates a Proxy which sends the exchange to the endpoint.
126     *
127     * @deprecated use the same method name with binding as parameter
128     */
129    @Deprecated
130    public static <T> T createProxy(Endpoint endpoint, Class<T>... interfaceClasses) throws Exception {
131        return createProxy(endpoint, true, interfaceClasses);
132    }
133
134    /**
135     * Creates a Proxy which sends the exchange to the endpoint.
136     */
137    public static <T> T createProxy(Endpoint endpoint, boolean binding, Class<T>... interfaceClasses) throws Exception {
138        return createProxy(endpoint, binding, getClassLoader(interfaceClasses), interfaceClasses);
139    }
140
141    /**
142     * Creates a Proxy which sends the exchange to the endpoint.
143     */
144    public static <T> T createProxy(Endpoint endpoint, Producer producer, Class<T> interfaceClass) throws Exception {
145        return createProxy(endpoint, true, producer, toArray(interfaceClass));
146    }
147
148    /**
149     * Creates a Proxy which sends the exchange to the endpoint.
150     *
151     * @deprecated use the same method name with binding as parameter
152     */
153    @Deprecated
154    public static <T> T createProxy(Endpoint endpoint, Producer producer, Class<T>... interfaceClasses) throws Exception {
155        return createProxyObject(endpoint, true, producer, getClassLoader(interfaceClasses), interfaceClasses, createMethodInfoCache(endpoint));
156    }
157
158    /**
159     * Creates a Proxy which sends the exchange to the endpoint.
160     */
161    public static <T> T createProxy(Endpoint endpoint, boolean binding, Producer producer, Class<T>... interfaceClasses) throws Exception {
162        return createProxyObject(endpoint, binding, producer, getClassLoader(interfaceClasses), interfaceClasses, createMethodInfoCache(endpoint));
163    }
164
165    /**
166     * Returns the class loader of the first interface or throws {@link IllegalArgumentException} if there are no interfaces specified
167     */
168    protected static ClassLoader getClassLoader(Class<?>... interfaces) {
169        if (interfaces == null || interfaces.length < 1) {
170            throw new IllegalArgumentException("You must provide at least 1 interface class.");
171        }
172        return interfaces[0].getClassLoader();
173    }
174
175    protected static MethodInfoCache createMethodInfoCache(Endpoint endpoint) {
176        return new MethodInfoCache(endpoint.getCamelContext());
177    }
178
179    @SuppressWarnings("unchecked")
180    private static <T> Class<T>[] toArray(Class<T> interfaceClass) {
181        // this method and it's usage is introduced to avoid compiler warnings
182        // about the generic Class arrays in the case we've got only one single
183        // Class to build a Proxy for
184        return new Class[] {interfaceClass};
185    }
186}