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    
018    package org.apache.geronimo.gbean.runtime;
019    
020    import java.lang.reflect.Method;
021    import java.util.ArrayList;
022    import java.util.Collections;
023    import java.util.Iterator;
024    import java.util.List;
025    
026    import org.apache.geronimo.gbean.DynamicGBean;
027    import org.apache.geronimo.gbean.DynamicGOperationInfo;
028    import org.apache.geronimo.gbean.GOperationInfo;
029    import org.apache.geronimo.gbean.InvalidConfigurationException;
030    import org.apache.geronimo.kernel.ClassLoading;
031    
032    /**
033     * @version $Rev: 558235 $ $Date: 2007-07-20 23:47:45 -0400 (Fri, 20 Jul 2007) $
034     */
035    public final class GBeanOperation {
036        private final GBeanInstance gbeanInstance;
037        private final String name;
038        private final List parameterTypes;
039        private final MethodInvoker methodInvoker;
040        private final boolean framework;
041        private final GOperationInfo operationInfo;
042    
043        static GBeanOperation createFrameworkOperation(GBeanInstance gbeanInstance, String name, List parameterTypes, MethodInvoker methodInvoker) {
044            return new GBeanOperation(gbeanInstance, name, parameterTypes, methodInvoker);
045        }
046    
047        private GBeanOperation(GBeanInstance gbeanInstance, String name, List parameterTypes, MethodInvoker methodInvoker) {
048            framework = true;
049            this.gbeanInstance = gbeanInstance;
050            this.name = name;
051            this.parameterTypes = Collections.unmodifiableList(new ArrayList(parameterTypes));
052            this.methodInvoker = methodInvoker;
053            // this is not used
054            this.operationInfo = new GOperationInfo(this.name, this.parameterTypes, "java.lang.Object");
055        }
056    
057        public GBeanOperation(GBeanInstance gbeanInstance, GOperationInfo operationInfo) throws InvalidConfigurationException {
058            framework = false;
059            this.gbeanInstance = gbeanInstance;
060            this.name = operationInfo.getName();
061            this.operationInfo = operationInfo;
062    
063            // get an array of the parameter classes
064            this.parameterTypes = Collections.unmodifiableList(new ArrayList(operationInfo.getParameterList()));
065            Class[] types = new Class[parameterTypes.size()];
066            ClassLoader classLoader = gbeanInstance.getClassLoader();
067            for (int i = 0; i < types.length; i++) {
068                String type = (String) parameterTypes.get(i);
069                try {
070                    types[i] = ClassLoading.loadClass((String) parameterTypes.get(i), classLoader);
071                } catch (ClassNotFoundException e) {
072                    throw new InvalidConfigurationException("Could not load operation parameter class:" +
073                            " name=" + operationInfo.getName() +
074                            " class=" + type, e);
075                }
076            }
077    
078            // get a method invoker for the operation
079            if (operationInfo instanceof DynamicGOperationInfo) {
080                methodInvoker = new MethodInvoker() {
081                    private String[] types = (String[]) parameterTypes.toArray(new String[parameterTypes.size()]);
082    
083                    public Object invoke(Object target, Object[] arguments) throws Exception {
084                        DynamicGBean dynamicGBean = (DynamicGBean) target;
085                        dynamicGBean.invoke(name, arguments, types);
086                        return null;
087                    }
088                };
089            } else {
090                try {
091                    Method javaMethod = gbeanInstance.getType().getMethod(operationInfo.getMethodName(), types);
092                    if (AbstractGBeanReference.NO_PROXY) {
093                        methodInvoker = new ReflectionMethodInvoker(javaMethod);
094                    } else {
095                        methodInvoker = new FastMethodInvoker(javaMethod);
096                    }
097                } catch (Exception e) {
098                    throw new InvalidConfigurationException("Target does not have specified method (declared in a GBeanInfo operation):" +
099                            " name=" + operationInfo.getName() +
100                            " methodName=" + operationInfo.getMethodName() +
101                            " returnType=" + operationInfo.getReturnType() +
102                            " targetClass=" + gbeanInstance.getType().getName(), e);
103                }
104            }
105        }
106    
107        public String getName() {
108            return name;
109        }
110    
111        public List getParameterTypes() {
112            return parameterTypes;
113        }
114    
115        public GOperationInfo getOperationInfo() {
116            return operationInfo;
117        }
118    
119        public boolean isFramework() {
120            return framework;
121        }
122    
123        public Object invoke(Object target, final Object[] arguments) throws Exception {
124            return methodInvoker.invoke(target, arguments);
125        }
126    
127        public String getDescription() {
128            String signature = name + "(";
129            for (Iterator iterator = parameterTypes.iterator(); iterator.hasNext();) {
130                String type = (String) iterator.next();
131                signature += type;
132                if (iterator.hasNext()) {
133                    signature += ", ";
134                }
135            }
136            signature += ")";
137            return "Operation Signature: " + signature + ", GBeanInstance: " + gbeanInstance.getName();
138        }
139    }