View Javadoc

1   /*
2      Copyright 2002-2006 Martin van den Bemt
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15  */
16  package org.xulux.utils;
17  
18  import java.lang.reflect.Constructor;
19  import java.lang.reflect.InvocationTargetException;
20  import java.lang.reflect.Modifier;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.xulux.api.logging.ILog;
25  import org.xulux.api.logging.ILogger;
26  
27  /**
28   * This util class contains classloader utils
29   * so we can do actual code reuse.
30   *
31   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
32   * @version $Id: ClassLoaderUtils.java,v 1.1 2005/12/18 12:58:15 mvdb Exp $
33   */
34  public class ClassLoaderUtils {
35  
36  
37      private static ILogger logger;
38  
39      /**
40       * Make it possible to extend..
41       */
42      protected ClassLoaderUtils() {
43      }
44      
45      /**
46       * Set the logger to be used
47       * @param logger the logger
48       */
49      public static void setLogger(ILogger logger) {
50          ClassLoaderUtils.logger = logger;
51      }
52  
53      /**
54       *
55       * @param classString the class
56       * @return an object from the specified classString or null when errors occur
57       */
58      public static Object getObjectFromClassString(String classString) {
59          Class clazz = getClass(classString);
60          return getObjectFromClass(clazz);
61      }
62      /**
63       * Also instantiates static AND non static innerclasses.
64       * The parent class needs to have an empty constructor!
65       * You can overcome this problem by adding this to the paramlist!
66       * @param clazz the class
67       * @return an object from the specified class or null when errors occur
68       */
69      public static Object getObjectFromClass(Class clazz) {
70          if (clazz == null) {
71              return null;
72          }
73          Object object = null;
74          try {
75              if (isInner(clazz) && !Modifier.isStatic(clazz.getModifiers())) {
76                  Object parent = getParentObjectForInnerClass(clazz);
77                  if (parent != null) {
78                      Constructor constructor = clazz.getConstructor(new Class[] {parent.getClass()});
79                      object = constructor.newInstance(new Object[] {parent} );
80                  }
81              } else {
82                  // static inner classes can be instantiated without a problem..
83                  object = clazz.newInstance();
84              }
85              return object;
86          } catch (InvocationTargetException e) {
87              if (logger != null) {
88                  logger.log(ILog.WARN, ClassLoaderUtils.class.getName(),"Cannot invocate target on " + clazz.getName());
89              }
90          } catch (NoSuchMethodException e) {
91              if (logger != null) {
92                  logger.log(ILog.WARN, ClassLoaderUtils.class.getName(), "Cannot find method on " + clazz.getName());
93              }
94          } catch (InstantiationException e) {
95              if (logger != null) {
96                  logger.log(ILog.WARN, ClassLoaderUtils.class.getName(), "Cannot instantiate class " + clazz.getName());
97              }
98          } catch (Throwable t) {
99              if (logger != null) {
100                 logger.log(ILog.WARN, ClassLoaderUtils.class.getName(), null, t);
101             }
102         }
103         return null;
104     }
105 
106     /**
107      * Instantiates the parent object of an inner class.
108      * @param clazz the class
109      * @return the instance of the inner class
110      */
111     protected static Object getParentObjectForInnerClass(Class clazz) {
112         String name = clazz.getName();
113         int index = name.indexOf("$");
114         if (index != -1 ) {
115             name = name.substring(0, index);
116             // cannot think of a scenario when this is null,
117             Class clz = getClass(name.substring(0, index));
118             ArrayList parms = new ArrayList();
119 //            boolean hasEmptyConstructor = false;
120             Constructor[] css = clz.getConstructors();
121             for (int i = 0; i < css.length; i++) {
122                 Constructor cs = css[i];
123                 if (cs.getParameterTypes().length == 0) {
124 //                    hasEmptyConstructor = true;
125                     parms = new ArrayList();
126                     break;
127                 } else {
128                     for (int j = 0; j < cs.getParameterTypes().length; j++) {
129                         Class c = cs.getParameterTypes()[j];
130                         Object object = null;
131                         try {
132                             object = c.newInstance();
133                         }
134                         catch (Exception e) {
135                             // eat it..
136                         } finally {
137                             parms.add(object);
138                         }
139                     }
140                 }
141             }
142             return getObjectFromClass(getClass(name.substring(0, index)), parms);
143         }
144         return null;
145     }
146 
147     /**
148      *
149      * @param clazz the class
150      * @return if the class is an inner class
151      */
152     public static boolean isInner(Class clazz) {
153         if (clazz == null) {
154             return false;
155         }
156         return clazz.getName().indexOf("$") != -1;
157     }
158 
159     /**
160      * Tries to find a constructor with the parameters specified in the list
161      * If it cannot it will return the empty constructor.
162      *
163      * @param clazz the class
164      * @param parms the list of parameters as classes
165      * @return the instantiated object
166      */
167     public static Object getObjectFromClass(Class clazz, List parms) {
168         try {
169             if (parms != null && parms.size() > 0) {
170                 boolean cleanUp = false;
171                 if (isInner(clazz) && !Modifier.isStatic(clazz.getModifiers())) {
172                     parms.add(0, getParentObjectForInnerClass(clazz));
173                     cleanUp = true;
174                 }
175                 Class[] clzList = new Class[parms.size()];
176                 for (int i = 0; i < parms.size(); i++) {
177                     clzList[i] = parms.get(i).getClass();
178                 }
179                 try {
180                     Constructor constructor = clazz.getConstructor(clzList);
181                     // clean up list..
182                     Object retValue = constructor.newInstance(parms.toArray());
183                     if (cleanUp) {
184                         parms.remove(0);
185                     }
186                     return retValue;
187                 } catch (NoSuchMethodException nsme) {
188                     // we should check alternative constructors
189                     // eg new ObjectImpl(Object object) is an ok constructor
190                     // when there is a String parameter.
191                     Constructor[] constructors = clazz.getConstructors();
192                     for (int c = 0; c < constructors.length; c++) {
193                         Constructor constructor = constructors[c];
194                         Class[] cclz = constructor.getParameterTypes();
195                         boolean cStatus = true;
196                         if (clzList.length >= cclz.length) {
197                             for (int cc = 0; cc < cclz.length; cc++) {
198                                 if (!cclz[cc].isAssignableFrom(clzList[cc])) {
199                                     cStatus = false;
200                                 }
201                             }
202                         } else {
203                             cStatus = false;
204                         }
205                         if (cStatus) {
206                             Object retValue = null;
207                             if (parms.size() == constructor.getParameterTypes().length) {
208                                 retValue = constructor.newInstance(parms.toArray());
209                                 if (cleanUp) {
210                                     parms.remove(0);
211                                 }
212                                 return retValue;
213                             }
214                         }
215                     }
216                     if (cleanUp) {
217                         parms.remove(0);
218                     }
219                     return null;
220                 }
221             }
222         }
223         catch (Exception e) {
224             if (logger != null) {
225                 logger.log(ILog.WARN, ClassLoaderUtils.class.getName(), "Unknown error in getting object", e);
226             }
227         }
228         return getObjectFromClass(clazz);
229     }
230 
231     /**
232      *
233      * @param clazzString the class
234      * @return the clazz created from the specified String or null
235      *          when it could not be created
236      */
237     public static Class getClass(String clazzString) {
238         if (clazzString == null) {
239             return null;
240         }
241         try {
242             Class clazz = null;
243             try {
244                 clazz = Thread.currentThread().getContextClassLoader().loadClass( clazzString );
245             }
246             catch (ClassNotFoundException e) {
247                 clazz = ClassLoaderUtils.class.getClassLoader().loadClass( clazzString );
248             }
249             return clazz;
250         }
251         catch (ClassNotFoundException e) {
252             if (logger != null) {
253                 logger.log(ILog.WARN, ClassLoaderUtils.class.getName(), "Cannot find class " + clazzString);
254             }
255         }
256         return null;
257     }
258 
259 }