View Javadoc

1   /**
2    *
3    * Copyright 2003-2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.gbean;
19  
20  import java.beans.Introspector;
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  import java.util.HashMap;
24  import java.util.Map;
25  import java.util.Set;
26  import java.util.List;
27  import java.util.ArrayList;
28  import java.util.Iterator;
29  
30  import net.sf.cglib.reflect.FastClass;
31  import net.sf.cglib.reflect.FastMethod;
32  
33  
34  /**
35   * Wraps an <code>Object</code> in a <code>DynamicGBean</code> facade.
36   *
37   * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
38   */
39  public class DynamicGBeanDelegate implements DynamicGBean {
40      protected final Map getters = new HashMap();
41      protected final Map setters = new HashMap();
42      protected final Map operations = new HashMap();
43      private Class targetClass;
44  
45      public void addAll(Object target) {
46          this.targetClass = target.getClass();
47          Method[] methods = targetClass.getMethods();
48          for (int i = 0; i < methods.length; i++) {
49              Method method = methods[i];
50              if (isGetter(method)) {
51                  addGetter(target, method);
52              } else if (isSetter(method)) {
53                  addSetter(target, method);
54              } else {
55                  addOperation(target, method);
56              }
57          }
58      }
59  
60      public void addGetter(Object target, Method method) {
61          String name = method.getName();
62          if (name.startsWith("get")) {
63              addGetter(name.substring(3), target, method);
64          } else if (name.startsWith("is")) {
65              addGetter(name.substring(2), target, method);
66          } else {
67              throw new IllegalArgumentException("Method name must start with 'get' or 'is' " + method);
68          }
69      }
70  
71      public void addGetter(String name, Object target, Method method) {
72          if (!(method.getParameterTypes().length == 0 && method.getReturnType() != Void.TYPE)) {
73              throw new IllegalArgumentException("Method must take no parameters and return a value " + method);
74          }
75          getters.put(name, new Operation(target, method));
76          // we want to be user-friendly so we put the attribute name in
77          // the Map in both lower-case and upper-case
78          getters.put(Introspector.decapitalize(name), new Operation(target, method));
79      }
80  
81      public void addSetter(Object target, Method method) {
82          if (!method.getName().startsWith("set")) {
83              throw new IllegalArgumentException("Method name must start with 'set' " + method);
84          }
85          addSetter(method.getName().substring(3), target, method);
86      }
87  
88      public void addSetter(String name, Object target, Method method) {
89          if (!(method.getParameterTypes().length == 1 && method.getReturnType() == Void.TYPE)) {
90              throw new IllegalArgumentException("Method must take one parameter and not return anything " + method);
91          }
92          setters.put(name, new Operation(target, method));
93          // we want to be user-friendly so we put the attribute name in
94          // the Map in both lower-case and upper-case
95          setters.put(Introspector.decapitalize(name), new Operation(target, method));
96      }
97  
98      public void addOperation(Object target, Method method) {
99          Class[] parameters = method.getParameterTypes();
100         String[] types = new String[parameters.length];
101         for (int i = 0; i < parameters.length; i++) {
102             types[i] = parameters[i].getName();
103         }
104         GOperationSignature key = new GOperationSignature(method.getName(), types);
105         operations.put(key, new Operation(target, method));
106     }
107 
108     private boolean isGetter(Method method) {
109         String name = method.getName();
110         return (name.startsWith("get") || name.startsWith("is")) &&
111                 method.getParameterTypes().length == 0
112                 && method.getReturnType() != Void.TYPE;
113     }
114 
115     private boolean isSetter(Method method) {
116         return method.getName().startsWith("set") &&
117                 method.getParameterTypes().length == 1 &&
118                 method.getReturnType() == Void.TYPE;
119     }
120 
121     public Object getAttribute(String name) throws Exception {
122         Operation operation = (Operation) getters.get(name);
123         if (operation == null) {
124             throw new IllegalArgumentException(targetClass.getName() + ": no getter for " + name);
125         }
126         return operation.invoke(null);
127     }
128 
129     public void setAttribute(String name, Object value) throws Exception {
130         Operation operation = (Operation) setters.get(name);
131         if (operation == null) {
132             throw new IllegalArgumentException(targetClass.getName() + ": no setter for " + name);
133         }
134         operation.invoke(new Object[]{value});
135     }
136 
137     public Object invoke(String name, Object[] arguments, String[] types) throws Exception {
138         GOperationSignature signature = new GOperationSignature(name, types);
139         Operation operation = (Operation) operations.get(signature);
140         if (operation == null) {
141             throw new IllegalArgumentException(targetClass.getName() + ": no operation " + signature);
142         }
143         return operation.invoke(arguments);
144     }
145 
146     /**
147      * Gets all properties (with both a getter and setter), in the form of
148      * propertyName
149      */ 
150     public String[] getProperties() {
151         Set one = getters.keySet();
152         Set two = setters.keySet();
153         List out = new ArrayList();
154         for (Iterator it = one.iterator(); it.hasNext();) {
155             String name = (String) it.next();
156             if(Character.isLowerCase(name.charAt(0)) && two.contains(name)) {
157                 out.add(name);
158             }
159         }
160         return (String[]) out.toArray(new String[out.size()]);
161     }
162 
163     public Class getPropertyType(String name) {
164         Operation oper = (Operation) getters.get(name);
165         return oper.method.getReturnType();
166     }
167 
168     protected static class Operation {
169         private final Object target;
170         private final FastMethod method;
171 
172         public Operation(Object target, Method method) {
173             assert target != null;
174             assert method != null;
175             this.target = target;
176             this.method = FastClass.create(target.getClass()).getMethod(method);
177         }
178 
179         public Object invoke(Object[] arguments) throws Exception {
180             try {
181                 return method.invoke(target, arguments);
182             } catch (InvocationTargetException e) {
183                 Throwable targetException = e.getTargetException();
184                 if (targetException instanceof Exception) {
185                     throw (Exception) targetException;
186                 } else if (targetException instanceof Error) {
187                     throw (Error) targetException;
188                 }
189                 throw e;
190             }
191         }
192     }
193 }