| ClassUtil.java |
1 /**
2 * Distribution License:
3 * JSword is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License, version 2.1 as published by
5 * the Free Software Foundation. This program is distributed in the hope
6 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 * See the GNU Lesser General Public License for more details.
9 *
10 * The License is available on the internet at:
11 * http://www.gnu.org/copyleft/lgpl.html
12 * or by writing to:
13 * Free Software Foundation, Inc.
14 * 59 Temple Place - Suite 330
15 * Boston, MA 02111-1307, USA
16 *
17 * Copyright: 2005
18 * The copyright to this program is held by it's authors.
19 *
20 * ID: $Id: ClassUtil.java 2230 2012-02-08 00:00:10Z dmsmith $
21 */
22 package org.crosswire.common.util;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.zip.ZipEntry;
27 import java.util.zip.ZipFile;
28
29 /**
30 * Various Java Class Utilities.
31 *
32 * @see gnu.lgpl.License for license details.<br>
33 * The copyright to this program is held by it's authors.
34 * @author Joe Walker [joe at eireneh dot com]
35 */
36 public final class ClassUtil {
37 /**
38 * Prevent instantiation
39 */
40 private ClassUtil() {
41 }
42
43 /**
44 * Gets the Class for the className in a way that works well for extensions.
45 * See: http://www.javageeks.com/Papers/ClassForName/ClassForName.pdf
46 *
47 * @param className
48 * the class to get
49 * @return the found Class
50 * @throws ClassNotFoundException
51 */
52 public static Class<?> forName(String className) throws ClassNotFoundException {
53 return Thread.currentThread().getContextClassLoader().loadClass(className);
54 }
55
56 /**
57 * This function finds the first matching filename for a Java class file
58 * from the classpath, if none is found it returns null.
59 */
60 public static String findClasspathEntry(String classname, String classpath) {
61 String full = null;
62
63 String[] paths = StringUtil.split(classpath, File.pathSeparator);
64 for (int i = 0; i < paths.length; i++) {
65 // Search the jar
66 if (paths[i].endsWith(EXTENSION_ZIP) || paths[i].endsWith(EXTENSION_JAR)) {
67 ZipFile zip = null;
68 try {
69 String fileName = classname.replace(',', '/') + EXTENSION_CLASS;
70 zip = new ZipFile(paths[i]);
71 ZipEntry entry = zip.getEntry(fileName);
72
73 if (entry != null && !entry.isDirectory()) {
74 if (full != null && !full.equals(fileName)) {
75 log.warn("Warning duplicate " + classname + " found: " + full + " and " + paths[i]);
76 } else {
77 full = paths[i];
78 }
79 }
80 } catch (IOException ex) {
81 // If that zip file failed, then ignore it and move on.
82 log.warn("Missing zip file for " + classname + " and " + paths[i]);
83 } finally {
84 IOUtil.close(zip);
85 }
86 } else {
87 StringBuilder path = new StringBuilder(256);
88
89 // Search for the file
90 String extra = classname.replace('.', File.separatorChar);
91
92 path.append(paths[i]);
93 if (paths[i].charAt(paths[i].length() - 1) != File.separatorChar) {
94 path.append(File.separatorChar);
95 }
96
97 path.append(extra);
98 path.append(EXTENSION_CLASS);
99 String fileName = path.toString();
100
101 if (new File(fileName).isFile()) {
102 if (full != null && !full.equals(fileName)) {
103 log.warn("Warning duplicate " + classname + " found: " + full + " and " + paths[i]);
104 } else {
105 full = paths[i];
106 }
107 }
108 }
109 }
110
111 return full;
112 }
113
114 /**
115 * This function find the first matching filename for a Java class file from
116 * the classpath, if none is found it returns null.
117 */
118 public static String findClasspathEntry(String classname) {
119 String classpath = System.getProperty("java.class.path", "");
120 return findClasspathEntry(classname, classpath);
121 }
122
123 /**
124 * <p>
125 * Gets the class name minus the package name for an <code>Object</code>.
126 * </p>
127 *
128 * @param object
129 * the class to get the short name for, may be null
130 * @param valueIfNull
131 * the value to return if null
132 * @return the class name of the object without the package name, or the
133 * null value
134 */
135 public static String getShortClassName(Object object, String valueIfNull) {
136 if (object == null) {
137 return valueIfNull;
138 }
139 return getShortClassName(object.getClass().getName());
140 }
141
142 /**
143 * <p>
144 * Gets the class name minus the package name from a <code>Class</code>.
145 * </p>
146 *
147 * @param cls
148 * the class to get the short name for, must not be
149 * <code>null</code>
150 * @return the class name without the package name
151 * @throws IllegalArgumentException
152 * if the class is <code>null</code>
153 */
154 public static String getShortClassName(Class<?> cls) {
155 if (cls == null) {
156 throw new IllegalArgumentException("The class must not be null");
157 }
158 return getShortClassName(cls.getName());
159 }
160
161 /**
162 * <p>
163 * Gets the class name minus the package name from a String.
164 * </p>
165 *
166 * <p>
167 * The string passed in is assumed to be a class name - it is not checked.
168 * </p>
169 *
170 * @param className
171 * the className to get the short name for, must not be empty or
172 * <code>null</code>
173 * @return the class name of the class without the package name
174 * @throws IllegalArgumentException
175 * if the className is empty
176 */
177 public static String getShortClassName(String className) {
178 if (className == null || className.length() == 0) {
179 throw new IllegalArgumentException("The class name must not be empty");
180 }
181 char[] chars = className.toCharArray();
182 int lastDot = 0;
183 for (int i = 0; i < chars.length; i++) {
184 if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
185 lastDot = i + 1;
186 } else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) {
187 chars[i] = PACKAGE_SEPARATOR_CHAR;
188 }
189 }
190 return new String(chars, lastDot, chars.length - lastDot);
191 }
192
193 /**
194 * <p>
195 * The package separator character: <code>.</code>.
196 * </p>
197 */
198 private static final char PACKAGE_SEPARATOR_CHAR = '.';
199
200 /**
201 * <p>
202 * The inner class separator character: <code>$</code>.
203 * </p>
204 */
205 private static final char INNER_CLASS_SEPARATOR_CHAR = '$';
206
207 private static final String EXTENSION_CLASS = ".class";
208 private static final String EXTENSION_JAR = ".jar";
209 private static final String EXTENSION_ZIP = ".zip";
210
211 /**
212 * The log stream
213 */
214 private static final Logger log = Logger.getLogger(ClassUtil.class);
215 }
216