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 }