View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  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.commons.proxy.factory.javassist;
19  
20  import javassist.CannotCompileException;
21  import javassist.ClassPool;
22  import javassist.CtClass;
23  import javassist.CtField;
24  import javassist.LoaderClassPath;
25  import javassist.NotFoundException;
26  import org.apache.commons.proxy.ProxyUtils;
27  import org.apache.commons.proxy.exception.ObjectProviderException;
28  
29  import java.util.HashSet;
30  import java.util.Set;
31  
32  /**
33   * Some utility methods for dealing with Javassist.  This class is not part of the public API!
34   * 
35   * @author James Carman
36   * @since 1.0
37   */
38  class JavassistUtils
39  {
40  //----------------------------------------------------------------------------------------------------------------------
41  // Fields
42  //----------------------------------------------------------------------------------------------------------------------
43      public static final String DEFAULT_BASE_NAME = "JavassistUtilsGenerated";
44      private static int classNumber = 0;
45      private static final ClassPool classPool = new ClassPool();
46  
47      static
48      {
49          classPool.appendClassPath( new LoaderClassPath( ClassLoader.getSystemClassLoader() ) );
50      }
51  
52      private static final Set classLoaders = new HashSet();
53  //----------------------------------------------------------------------------------------------------------------------
54  // Static Methods
55  //----------------------------------------------------------------------------------------------------------------------
56  
57      /**
58       * Adds a field to a class.
59       * 
60       * @param fieldType the field's type
61       * @param fieldName the field name
62       * @param enclosingClass the class receiving the new field 
63       * @throws CannotCompileException if a compilation problem occurs
64       */
65      public static void addField( Class fieldType, String fieldName, CtClass enclosingClass )
66              throws CannotCompileException
67      {
68          enclosingClass.addField( new CtField( resolve( fieldType ), fieldName, enclosingClass ) );
69      }
70  
71      /**
72       * Finds the {@link CtClass} corresponding to the Java {@link Class} passed in.
73       * 
74       * @param clazz the Java {@link Class}
75       * @return the {@link CtClass}
76       */
77      public static CtClass resolve( Class clazz )
78      {
79          synchronized( classLoaders )
80          {
81              try
82              {
83                  final ClassLoader loader = clazz.getClassLoader();
84                  if( loader != null && !classLoaders.contains( loader ) )
85                  {
86                      classLoaders.add( loader );
87                      classPool.appendClassPath( new LoaderClassPath( loader ) );
88                  }
89                  return classPool.get( ProxyUtils.getJavaClassName( clazz ) );
90              }
91              catch( NotFoundException e )
92              {
93                  throw new ObjectProviderException(
94                          "Unable to find class " + clazz.getName() + " in default Javassist class pool.", e );
95              }
96          }
97      }
98  
99      /**
100      * Adds interfaces to a {@link CtClass}
101      * 
102      * @param ctClass the {@link CtClass}
103      * @param proxyClasses the interfaces
104      */
105     public static void addInterfaces( CtClass ctClass, Class[] proxyClasses )
106     {
107         for( int i = 0; i < proxyClasses.length; i++ )
108         {
109             Class proxyInterface = proxyClasses[i];
110             ctClass.addInterface( resolve( proxyInterface ) );
111         }
112     }
113 
114     /**
115      * Creates a new {@link CtClass} derived from the Java {@link Class} using the default base name.
116      * 
117      * @param superclass the superclass
118      * @return the new derived {@link CtClass}
119      */
120     public static CtClass createClass( Class superclass )
121     {
122         return createClass( DEFAULT_BASE_NAME, superclass );
123     }
124 
125     /**
126      * Creates a new {@link CtClass} derived from the Java {@link Class} using the supplied base name.
127      * 
128      * @param baseName the base name
129      * @param superclass the superclass
130      * @return the new derived {@link CtClass}
131      */
132     public synchronized static CtClass createClass( String baseName, Class superclass )
133     {
134         return classPool.makeClass( baseName + "_" + classNumber++, resolve( superclass ) );
135     }
136 
137     /**
138      * Resolves an array of Java {@link Class}es to an array of their corresponding {@link CtClass}es.
139      * 
140      * @param classes the Java {@link Class}es
141      * @return the corresponding {@link CtClass}es
142      */
143     public static CtClass[] resolve( Class[] classes )
144     {
145         final CtClass[] ctClasses = new CtClass[classes.length];
146         for( int i = 0; i < ctClasses.length; ++i )
147         {
148             ctClasses[i] = resolve( classes[i] );
149         }
150         return ctClasses;
151     }
152 }
153