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.util.ServiceHelper;
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    @SuppressWarnings("unchecked")
042    public static <T> T createProxyObject(Endpoint endpoint, Producer producer, ClassLoader classLoader, Class<T>[] interfaces, MethodInfoCache methodCache) {
043        return (T) Proxy.newProxyInstance(classLoader, interfaces.clone(), new CamelInvocationHandler(endpoint, producer, methodCache));
044    }
045
046    /**
047     * Creates a Proxy which sends the exchange to the endpoint.
048     */
049    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T> interfaceClass, MethodInfoCache methodCache) throws Exception {
050        return createProxy(endpoint, cl, toArray(interfaceClass), methodCache);
051    }
052
053    /**
054     * Creates a Proxy which sends the exchange to the endpoint.
055     */
056    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T>[] interfaceClasses, MethodInfoCache methodCache) throws Exception {
057        Producer producer = endpoint.createProducer();
058        // ensure the producer is started
059        ServiceHelper.startService(producer);
060        return createProxyObject(endpoint, producer, cl, interfaceClasses, methodCache);
061    }
062
063    /**
064     * Creates a Proxy which sends the exchange to the endpoint.
065     */
066    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T> interfaceClass) throws Exception {
067        return createProxy(endpoint, cl, toArray(interfaceClass));
068    }
069
070    /**
071     * Creates a Proxy which sends the exchange to the endpoint.
072     */
073    public static <T> T createProxy(Endpoint endpoint, ClassLoader cl, Class<T>... interfaceClasses) throws Exception {
074        return createProxy(endpoint, cl, interfaceClasses, createMethodInfoCache(endpoint));
075    }
076
077    /**
078     * Creates a Proxy which sends the exchange to the endpoint.
079     */
080    public static <T> T createProxy(Endpoint endpoint, Class<T> interfaceClass) throws Exception {
081        return createProxy(endpoint, toArray(interfaceClass));
082    }
083
084    /**
085     * Creates a Proxy which sends the exchange to the endpoint.
086     */
087    public static <T> T createProxy(Endpoint endpoint, Class<T>... interfaceClasses) throws Exception {
088        return createProxy(endpoint, getClassLoader(interfaceClasses), interfaceClasses);
089    }
090
091    /**
092     * Creates a Proxy which sends the exchange to the endpoint.
093     */
094    public static <T> T createProxy(Endpoint endpoint, Producer producer, Class<T> interfaceClass) throws Exception {
095        return createProxy(endpoint, producer, toArray(interfaceClass));
096    }
097
098    /**
099     * Creates a Proxy which sends the exchange to the endpoint.
100     */
101    public static <T> T createProxy(Endpoint endpoint, Producer producer, Class<T>... interfaceClasses) throws Exception {
102        return createProxyObject(endpoint, producer, getClassLoader(interfaceClasses), interfaceClasses, createMethodInfoCache(endpoint));
103    }
104
105    /**
106     * Returns the class loader of the first interface or throws {@link IllegalArgumentException} if there are no interfaces specified
107     */
108    protected static ClassLoader getClassLoader(Class<?>... interfaces) {
109        if (interfaces == null || interfaces.length < 1) {
110            throw new IllegalArgumentException("You must provide at least 1 interface class.");
111        }
112        return interfaces[0].getClassLoader();
113    }
114
115    protected static MethodInfoCache createMethodInfoCache(Endpoint endpoint) {
116        return new MethodInfoCache(endpoint.getCamelContext());
117    }
118
119    @SuppressWarnings("unchecked")
120    private static <T> Class<T>[] toArray(Class<T> interfaceClass) {
121        // this method and it's usage is introduced to avoid compiler warnings
122        // about the generic Class arrays in the case we've got only one single
123        // Class to build a Proxy for
124        return new Class[] {interfaceClass};
125    }
126}