1 package com.zmicer.utils;
2
3 import org.apache.log4j.Logger;
4 import sun.reflect.Reflection;
5
6 import java.util.HashMap;
7 import java.util.Map;
8 import java.util.StringTokenizer;
9 import java.util.regex.Pattern;
10
11 /**
12 * Utility class for working with reflexion mechanism
13 * <p/>
14 * $Author:: zmicer $<br/>
15 * $Rev:: 67 $<br/>
16 * $Date:: 2007-08-28 21:37:07 #$<br/>
17 */
18 public class ReflexionUtils
19 {
20 /**
21 * Logger instance.
22 */
23 final public static Logger LOG = Logger.getLogger(ZmicerUtilsConstants.LoggingCategory.REFLEXION.toString());
24
25 /**
26 * Pattern to find the name of the method is currently running.
27 */
28 final public static Pattern PATTERN = Pattern.compile("\\.([a-zA-Z0-9_]*)\\(.*\r\n.*invoke0");
29
30 /**
31 * Get the instance of Object using the provided full class name.
32 * <br/>
33 * All the exception may appear during reflexion are catched and logged. In this case <code>null</code> is returned.
34 *
35 * @param className the full class name ro be reflected, Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
36 * @param throwIfNotInitialized if this is true we throw exception (IllegalStateException) if some implementations can not be
37 * instantiated
38 *
39 * @return Object, reflected object
40 */
41 public static Object reflectObject(final String className, boolean throwIfNotInitialized)
42 {
43 InputArgumentUtils.checkStrings(true, className);
44 try
45 {
46 return ReflexionUtils.class.getClassLoader().loadClass(className).newInstance();
47 }
48 catch (Throwable t)
49 {
50 final String message = "Can not instantiate the class instance using the provided " +
51 "name: [" + className + "]; reason: "+t.getMessage()+""; //with "getMessage()" reason more clear (:
52 LoggingUtils.logException(LOG, t, message, ReflexionUtils.class);
53 if (throwIfNotInitialized)
54 {
55 throw new IllegalStateException(message);
56 }
57 }
58 return null;
59 }
60
61 /**
62 * Get the instance of Object using the provided full class name.
63 * <br/>
64 * All the exception may appear during reflexion are catched and logged. In this case <code>null</code> is returned as the value.
65 *
66 * @param info the map with #key type of the object to be reflected #value. Can not contains null as neither key or value
67 * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
68 * @param throwIfNotInitialized if this is true we throw exception (IllegalStateException) if some implementations can not be
69 * instantiated
70 *
71 * @return map of the relflected objects with the appropaite keys
72 */
73 public static Map<String, Object> reflectObjects(final Map<String, String> info, final boolean throwIfNotInitialized)
74 {
75 InputArgumentUtils.checkObjects(info);
76 final Map<String, Object> result = new HashMap<String, Object>();
77 for (String key : info.keySet())
78 {
79 try
80 {
81 if (org.apache.commons.lang.StringUtils.isBlank(key) || org.apache.commons.lang.StringUtils.isBlank(info.get(key)))
82 {
83 final String message = "The map provided can not contains blank key and values. key [" + key + "], value [" +
84 info.get(key) + "]";
85 LoggingUtils.error(LOG, ReflexionUtils.class, message);
86 throw new IllegalArgumentException(message);
87 }
88 result.put(key, ReflexionUtils.class.getClassLoader().loadClass(info.get(key)).newInstance());
89 }
90 catch (Throwable t)
91 {
92 final String message = "Can not instantiate the class instance using the provided name: [" + info.get(key) + "]";
93 LoggingUtils.logException(LOG, t, message, ReflexionUtils.class);
94 if (throwIfNotInitialized)
95 {
96 throw new IllegalStateException(message);
97 }
98 result.put(key, null);
99 }
100 }
101 return result;
102 }
103
104 /**
105 * Get the base name of the provided String - the name of the class.
106 *
107 * @param claz <code>Class</code> instance. Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
108 *
109 * @return String, the base name of the class (without the packages pathes)
110 */
111 public static String getBaseName(final Class claz)
112 {
113 if (null == claz || null == claz.getName())
114 {
115 throw new IllegalArgumentException("The class and class name can not be null.");
116 }
117 final StringTokenizer tokenizer = new StringTokenizer(claz.getName(), ".");
118 String result = null;
119 while (tokenizer.hasMoreTokens())
120 {
121 result = tokenizer.nextToken();
122 }
123 return result;
124 }
125
126 /**
127 * Get the full name of the class from instances of which the certain array object class of which is passed as the single input param.
128 * <p/>
129 * todo [zmicer]: please clarify if this method to determine this full class name is correct for another versions of Java JDK. May be
130 * there are another ways to clarify this.
131 * <p/>
132 * Example: imagine we have the array of the {@link Global} object. This appropriate class for this array would have the name
133 * "[Lcom.sourceforge.jpatterns.schema.Global;", and String we need is "com.sourceforge.jpatterns.schema.Global".
134 *
135 * @param claz Class of an array for which we need to determine the class of the objects this array stores.
136 * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
137 * In the case the class provided do not correspond to the array of objects the IllegalArgumentException would appear too.
138 *
139 * @return String, the full name of class instances of which are the members of the array class of which is passed to this method.
140 */
141 public static String getClassNameOfArrayMembers(final Class claz)
142 {
143 InputArgumentUtils.checkObjects(claz);
144 final String prefix = "[L";
145 final String postfix = ";";
146 if (!claz.getName().startsWith(prefix) || !claz.getName().endsWith(postfix))
147 {
148 LoggingUtils.debug(LOG, ReflexionUtils.class, "Incorrect name of the class corresponding to the array of objects was " +
149 "provided: class name [" + claz.getName() + "]");
150 throw new IllegalArgumentException("Please provide the correct class corresponding to the array of objects.");
151 }
152 return claz.getName().substring(prefix.length(), claz.getName().length() - postfix.length());
153 }
154
155 /**
156 * note [zmicer]: only for the test purposes (for JPatterns test engine allowing to setup the props/xml environment per the folders)
157 *
158 * @return the caller class full name.
159 */
160 public static String getCallerFullClassName()
161 {
162 return Reflection.getCallerClass(MagicNumbers.THREE).getName();
163 }
164
165 /**
166 * Analog of the instance of construction (e.g. obj instanceof Serializable)
167 *
168 * @param obj object to be checked. Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
169 * @param baseClass base class (interface class) which should be used for the determining if obj is instace of this class
170 * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
171 *
172 * @return the true if this is "instance of" of the provided class (it is called base class here)
173 */
174 public static boolean instanceOf(final Object obj, Class<?> baseClass)
175 {
176 InputArgumentUtils.checkObjects(obj, baseClass);
177 return baseClass.isAssignableFrom(obj.getClass());
178 }
179
180 }