001: /*
002: * Distributed as part of c3p0 v.0.9.1.2
003: *
004: * Copyright (C) 2005 Machinery For Change, Inc.
005: *
006: * Author: Steve Waldman <swaldman@mchange.com>
007: *
008: * This library is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU Lesser General Public License version 2.1, as
010: * published by the Free Software Foundation.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public License
018: * along with this software; see the file LICENSE. If not, write to the
019: * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: */
022:
023: package com.mchange.v1.lang;
024:
025: import java.util.*;
026: import com.mchange.v1.jvm.*;
027:
028: public final class ClassUtils {
029: final static String[] EMPTY_SA = new String[0];
030:
031: static Map primitivesToClasses;
032:
033: static {
034: HashMap tmp = new HashMap();
035: tmp.put("boolean", boolean.class);
036: tmp.put("int", int.class);
037: tmp.put("char", char.class);
038: tmp.put("short", short.class);
039: tmp.put("int", int.class);
040: tmp.put("long", long.class);
041: tmp.put("float", float.class);
042: tmp.put("double", double.class);
043: tmp.put("void", void.class);
044:
045: primitivesToClasses = Collections.unmodifiableMap(tmp);
046: }
047:
048: public static Set allAssignableFrom(Class type) {
049: Set out = new HashSet();
050:
051: //type itself and superclasses (if any)
052: for (Class cl = type; cl != null; cl = cl.getSuperclass())
053: out.add(cl);
054:
055: //super interfaces (if any)
056: addSuperInterfacesToSet(type, out);
057: return out;
058: }
059:
060: public static String simpleClassName(Class cl) {
061: String scn;
062: int array_level = 0;
063: while (cl.isArray()) {
064: ++array_level;
065: cl = cl.getComponentType();
066: }
067: scn = simpleClassName(cl.getName());
068: if (array_level > 0) {
069: StringBuffer sb = new StringBuffer(16);
070: sb.append(scn);
071: for (int i = 0; i < array_level; ++i)
072: sb.append("[]");
073: return sb.toString();
074: } else
075: return scn;
076: }
077:
078: private static String simpleClassName(String fqcn) {
079: int pkgdot = fqcn.lastIndexOf('.');
080: if (pkgdot < 0)
081: return fqcn;
082: String scn = fqcn.substring(pkgdot + 1);
083: if (scn.indexOf('$') >= 0) {
084: StringBuffer sb = new StringBuffer(scn);
085: for (int i = 0, len = sb.length(); i < len; ++i) {
086: if (sb.charAt(i) == '$')
087: sb.setCharAt(i, '.');
088: }
089: return sb.toString();
090: } else
091: return scn;
092: }
093:
094: public static boolean isPrimitive(String typeStr) {
095: return (primitivesToClasses.get(typeStr) != null);
096: }
097:
098: public static Class classForPrimitive(String typeStr) {
099: return (Class) primitivesToClasses.get(typeStr);
100: }
101:
102: public static Class forName(String fqcnOrPrimitive)
103: throws ClassNotFoundException {
104: Class out = classForPrimitive(fqcnOrPrimitive);
105: if (out == null)
106: out = Class.forName(fqcnOrPrimitive);
107: return out;
108: }
109:
110: public static Class forName(String fqOrSimple, String[] importPkgs,
111: String[] importClasses) throws AmbiguousClassNameException,
112: ClassNotFoundException {
113: try {
114: return Class.forName(fqOrSimple);
115: } catch (ClassNotFoundException e) {
116: return classForSimpleName(fqOrSimple, importPkgs,
117: importClasses);
118: }
119: }
120:
121: public static Class classForSimpleName(String simpleName,
122: String[] importPkgs, String[] importClasses)
123: throws AmbiguousClassNameException, ClassNotFoundException {
124: Set checkSet = new HashSet();
125: Class out = classForPrimitive(simpleName);
126:
127: if (out == null) {
128: if (importPkgs == null)
129: importPkgs = EMPTY_SA;
130:
131: if (importClasses == null)
132: importClasses = EMPTY_SA;
133:
134: for (int i = 0, len = importClasses.length; i < len; ++i) {
135: String importSimpleName = fqcnLastElement(importClasses[i]);
136: if (!checkSet.add(importSimpleName))
137: throw new IllegalArgumentException(
138: "Duplicate imported classes: "
139: + importSimpleName);
140: if (simpleName.equals(importSimpleName))
141: //we won't duplicate assign. we'd have caught it above
142: out = Class.forName(importClasses[i]);
143: }
144: if (out == null) {
145: try {
146: out = Class.forName("java.lang." + simpleName);
147: } catch (ClassNotFoundException e) { /* just means we haven't found it yet */
148: }
149:
150: for (int i = 0, len = importPkgs.length; i < len; ++i) {
151: try {
152: String tryClass = importPkgs[i] + '.'
153: + simpleName;
154: Class test = Class.forName(tryClass);
155: if (out == null)
156: out = test;
157: else
158: throw new AmbiguousClassNameException(
159: simpleName, out, test);
160: } catch (ClassNotFoundException e) { /* just means we haven't found it yet */
161: }
162: }
163: }
164: }
165: if (out == null)
166: throw new ClassNotFoundException(
167: "Could not find a class whose unqualified name is \042"
168: + simpleName
169: + "\042 with the imports supplied. Import packages are "
170: + Arrays.asList(importPkgs)
171: + "; class imports are "
172: + Arrays.asList(importClasses));
173: else
174: return out;
175: }
176:
177: public static String resolvableTypeName(Class type,
178: String[] importPkgs, String[] importClasses)
179: throws ClassNotFoundException {
180: String simpleName = simpleClassName(type);
181: try {
182: classForSimpleName(simpleName, importPkgs, importClasses);
183: } catch (AmbiguousClassNameException e) {
184: return type.getName();
185: }
186: return simpleName;
187: }
188:
189: public static String fqcnLastElement(String fqcn) {
190: int pkgdot = fqcn.lastIndexOf('.');
191: if (pkgdot < 0)
192: return fqcn;
193: return fqcn.substring(pkgdot + 1);
194: }
195:
196: /* does not add type itself, only its superinterfaces */
197: private static void addSuperInterfacesToSet(Class type, Set set) {
198: Class[] ifaces = type.getInterfaces();
199: for (int i = 0, len = ifaces.length; i < len; ++i) {
200: set.add(ifaces[i]);
201: addSuperInterfacesToSet(ifaces[i], set);
202: }
203: }
204:
205: private ClassUtils() {
206: }
207: }
|