View Javadoc

1   
2   /*
3    * Copyright (C) 2005 by Arno Schumacher
4    *
5    * This file is part of net.sourceforge.servletspy
6    *
7    * net.sourceforge.servletspy is free software; you can redistribute
8    * it and/or modify it under the terms of the GNU General Public 
9    * License as published by the Free Software Foundation; either 
10   * version 2, or (at your option) any later version.
11   *
12   * net.sourceforge.servletspy is distributed in the hope that it will
13   * be useful, but WITHOUT ANY WARRANTY; without even the implied 
14   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
15   * See the GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA 
20   */
21  
22  package net.sourceforge.servletspy.handler.base;
23  
24  import java.beans.BeanInfo;
25  import java.beans.Introspector;
26  import java.beans.PropertyDescriptor;
27  import java.lang.reflect.Method;
28  import java.lang.reflect.Modifier;
29  import java.util.ArrayList;
30  import java.util.List;
31  import java.util.StringTokenizer;
32  
33  import net.sourceforge.servletspy.IContext;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  
38  /***
39   * @author arno schumacher
40   */
41  public abstract class AbstractInterfaceTransformer extends AbstractHandler {
42  
43      /*** The logger. */
44      private static final Log LOGGER = LogFactory
45              .getLog(AbstractInterfaceTransformer.class);
46  
47      /***
48       * Returns an array of <code>java.lang.Class</code> objects using
49       * the provided space separated string of class names as input.
50       *
51       * @param clazzes The class names, space separated.
52       * @return An array of <code>java.lang.Class</code> objects.
53       */
54      protected static Class[] fromString(final String clazzes) {
55          final List interfaceList = new ArrayList();
56          final StringTokenizer st = new StringTokenizer(clazzes);
57          while (st.hasMoreTokens()) {
58              Class clazz = loadInterface(st.nextToken().trim());
59              if (clazz != null) {
60                  interfaceList.add(clazz);
61              }
62          }
63          return (Class[]) interfaceList.toArray(new Class[0]);
64      }
65  
66      /***
67       * Loads a <code>java.lang.Class</code>.
68       *
69       * @param s The name of the class.
70       * @return The class object or <code>null</code> in case of an error.
71       */
72      private static Class loadInterface(final String s) {
73          Class clazz = null;
74          try {
75              clazz =
76                  Thread.currentThread().getContextClassLoader().loadClass(s);
77              if (!clazz.isInterface()) {
78                  clazz = null;
79              }
80          } catch (Exception e) {
81              LOGGER.warn("Could not load class '" + s + "'");
82          }
83          return clazz;
84      }
85  
86      private Class[] classes = new Class[0];
87  
88      /***
89       * Constructor.
90       */
91      protected AbstractInterfaceTransformer() {
92      }
93  
94      /***
95       * Constructor.
96       *
97       * @param clazz an array of class specifying the interfaces for which
98       *    the transformer is applicable.
99       */
100     protected AbstractInterfaceTransformer(final Class[] clazz) {
101         if (clazz != null) {
102             this.classes = clazz;
103         }
104     }
105 
106     /***
107      * Constructor.
108      *
109      * @param s space separated string of class names specifying the
110      *    interfaces for which the transformer is applicable.
111      */
112     protected AbstractInterfaceTransformer(final String s) {
113         this(fromString(s));
114     }
115 
116     /* (non-Javadoc)
117      * @see net.sourceforge.servletspy.IContextHandler#handle(net.sourceforge.servletspy.IContext)
118      */
119     public final void handle(final IContext context) throws Exception {
120         final Object subject = context.getSubject();
121         for (int i = 0; i < classes.length; i++) {
122             if (classes[i] == null) {
123                 continue;
124             }
125             if (classes[i].isAssignableFrom(subject.getClass())) {
126                 handleClass(context, classes[i]);
127                 return;
128             }
129         }
130         context.proceed();
131     }
132 
133     private void handleClass(final IContext context, final Class clazz) throws Exception {
134         final BeanInfo beanInfo = Introspector.getBeanInfo(clazz, clazz
135                 .isInterface() ? null : Object.class);
136         final PropertyDescriptor[] apd = beanInfo.getPropertyDescriptors();
137         for (int i = 0; i < apd.length; i++) {
138             final PropertyDescriptor pd = apd[i];
139             final Method m = pd.getReadMethod();
140             final Class clazzType = pd.getPropertyType();
141             if (m == null) {
142                 continue;
143             }
144             // Readers with parameter, i.e. indexed properties.
145             if (m.getParameterTypes().length > 0) {
146                 continue;
147             }
148             // Exclude null types, just in case there exists an
149             // 'invalid' user defined property descriptor.
150             if (clazzType == null) {
151                 continue;
152             }
153             if (!Modifier.isPublic(m.getModifiers())
154                     || Modifier.isStatic(m.getModifiers())) {
155                 continue;
156             }
157             // Guess the name of the property ...
158             final String mName = m.getName();
159             String key = null;
160             if (mName.startsWith("get") && mName.length() > 3) {
161                 key = Introspector.decapitalize(mName.substring(3));
162             }
163             if (mName.startsWith("is") && mName.length() > 2) {
164                 key = Introspector.decapitalize(mName.substring(2));
165             }
166             final Object prop = m.invoke(context.getSubject(), new Object[0]);
167             context.add(key, prop);
168         }
169     }
170 }