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.camel.component.bean;
018    
019    import java.lang.reflect.Proxy;
020    
021    import org.apache.camel.Endpoint;
022    import org.apache.camel.Producer;
023    import org.apache.camel.util.ServiceHelper;
024    
025    /**
026     * A helper class for creating proxies which delegate to Camel
027     *
028     * @version 
029     */
030    public 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    }