1 /**
2 * Redistribution and use of this software and associated documentation ("Software"), with or
3 * without modification, are permitted provided that the following conditions are met:
4 *
5 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6 * must also contain a copy of this document.
7 *
8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9 * conditions and the following disclaimer in the documentation and/or other materials provided with
10 * the distribution.
11 *
12 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13 * without prior written permission of Intalio, Inc. For written permission, please contact
14 * info@exolab.org.
15 *
16 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18 * Intalio, Inc.
19 *
20 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21 *
22 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Copyright 1999-2000 (C) Intalio, Inc. All Rights Reserved.
32 */
33 package org.exolab.javasource;
34
35 /**
36 * A utility class used to validate identifiers and class names.
37 *
38 * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
39 * @version $Revision$ $Date: 2003-03-03 00:05:44 -0700 (Mon, 03 Mar 2003) $
40 */
41 public final class JNaming {
42 // --------------------------------------------------------------------------
43
44 /**
45 * Reserved keywords in Java as of Java 5.
46 */
47 private static final String[] KEYWORDS = {"abstract", "boolean", "break", "byte", "case", "catch",
48 "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends",
49 "false", "final", "finally", "float", "for", "goto", "if", "implements", "import",
50 "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private",
51 "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this",
52 "throw", "throws", "transient", "true", "try", "void", "volatile", "while"};
53
54 /**
55 * Collection classes in Java as of Java 5.
56 */
57 private static final String[] COLLECTIONS = {"ArrayList", "List", "Set", "Collection", "Vector",
58 "Hashtable", "Map", "HashMap", "HashSet", "TreeSet", "Enumeration", "Iterator",
59 "ListIterator", "SortedSet", "SortedMap", "Queue", "EnumSet", "EnumMap", "IdentityHashMap",
60 "LinkedHashMap", "LinkedHashSet", "LinkedList", "Stack", "TreeMap", "WeakHashMap"};
61
62 /**
63 * Classes in java.lang.* as of Java 5.
64 */
65 private static final String[] JAVA_LANG = {
66 // Interfaces in java.lang.*
67 "Appendable", "CharSequence", "Cloneable", "Comparable", "Iterable", "Readable", "Runnable",
68 // Classes in java.lang.*
69 "Boolean", "Byte", "Character", "Class", "ClassLoader", "Compiler", "Double", "Enum", "Float",
70 "InheritableThreadLocal", "Integer", "Long", "Math", "Number", "Object", "Package", "Process",
71 "ProcessBuilder", "Runtime", "RuntimePermission", "SecurityManager", "Short",
72 "StackTraceElement", "StrictMath", "String", "StringBuffer", "StringBuilder", "System",
73 "Thread", "ThreadGroup", "ThreadLocal", "Throwable", "Void",
74 // Exceptions in java.lang.*
75 "ArithmeticException", "ArrayIndexOutOfBoundsException", "ArrayStoreException",
76 "ClassCastException", "ClassNotFoundException", "CloneNotSupportedException",
77 "EnumConstantNotPresentException", "Exception", "IllegalAccessException",
78 "IllegalArgumentException", "IllegalMonitorStateException", "IllegalStateException",
79 "IllegalThreadStateException", "IndexOutOfBoundsException", "InstantiationException",
80 "InterruptedException", "NegativeArraySizeException", "NoSuchFieldException",
81 "NoSuchMethodException", "NullPointerException", "NumberFormatException", "RuntimeException",
82 "SecurityException", "StringIndexOutOfBoundsException", "TypeNotPresentException",
83 "UnsupportedOperationException",
84 // Errors in java.lang.*
85 "AbstractMethodError", "AssertionError", "ClassCircularityError", "ClassFormatError", "Error",
86 "ExceptionInInitializerError", "IllegalAccessError", "IncompatibleClassChangeError",
87 "InstantiationError", "InternalError", "LinkageError", "NoClassDefFoundError",
88 "NoSuchFieldError", "NoSuchMethodError", "OutOfMemoryError", "StackOverflowError",
89 "ThreadDeath", "UnknownError", "UnsatisfiedLinkError", "UnsupportedClassVersionError",
90 "VerifyError", "VirtualMachineError",
91 // Annotation types in java.lang.*
92 "Deprecated", "Override", "SuppressWarnings"};
93
94 /**
95 * Field names used within Castor that prevent a user from using the same name as an element
96 * without using a mapping file. Some fields that Castor uses depend on the contents of the
97 * schema, so we only warn. <br/>
98 * Reserved:
99 *
100 * <pre>
101 * _items -- might be fetched using getXXXXItems where XXX == class name
102 * _content
103 * _choiceValue
104 * _anyObject
105 * </pre>
106 */
107 private static final String[] CASTOR_RESERVED = {"Content", "MenuItem",};
108
109 /**
110 * Special reserved names within Windows that prevent a user from using the same name as an
111 * element without using a mapping file. Windows will not allow the use of any of these names with
112 * any case with any extension. At least, not without contortions.
113 *
114 * @see <a href=
115 * "http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp">
116 * The MSDN web page on file naming</a>
117 */
118 private static final String[] WINDOWS_RESERVED =
119 {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8",
120 "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",};
121
122 // --------------------------------------------------------------------------
123
124 /**
125 * As we're a static utility class, our constructor is private.
126 */
127 private JNaming() {
128 super();
129 }
130
131 // --------------------------------------------------------------------------
132
133 /**
134 * Returns true if the given String is a Java keyword which will cause a problem when used as a
135 * variable name.
136 *
137 * @param name The String to check against the list of keywords.
138 * @return True if the given String is a Java keyword which will cause a problem when used as a
139 * variable name.
140 */
141 public static boolean isKeyword(final String name) {
142 if (name == null) {
143 return false;
144 }
145 for (String keyword : KEYWORDS) {
146 if (keyword.equals(name)) {
147 return true;
148 }
149 }
150 return false;
151 }
152
153 /**
154 * Returns true if the given String is a parameterized Java collection. object keyword which will
155 * cause a problem when used as a variable name
156 *
157 * @param name The String to check as a parameterized Java collection.
158 * @return True if the given String is a parameterized Java collection object keyword which will
159 * cause a problem when used as a variable name.
160 */
161 public static boolean isParameterizedCollectionsObject(final String name) {
162 if (name == null) {
163 return false;
164 }
165 for (String collection : COLLECTIONS) {
166 if (name.indexOf(collection) != -1) {
167 return true;
168 }
169 }
170 return false;
171 }
172
173 /**
174 * Returns true if the given String is a Java class in java.lang.* which will cause a problem when
175 * used as a variable name.
176 *
177 * @param name The String to check against the list of keywords.
178 * @return True if the given String is a Java class in java.lang.* which will cause a problem when
179 * used as a variable name.
180 */
181 public static boolean isInJavaLang(final String name) {
182 if (name == null) {
183 return false;
184 }
185 for (String javaLang : JAVA_LANG) {
186 if (javaLang.equals(name)) {
187 return true;
188 }
189 }
190 return false;
191 }
192
193 /**
194 * Returns true if the given String is a reserved name by Castor which may cause a problem when
195 * used as a variable name. Some fields that Castor uses depend on the contents of the schema, so
196 * we only warn.
197 *
198 * @param name The String to check against the list of keywords.
199 * @return True if the given String is a reserved name by Castor which may cause a problem when
200 * used as a variable name.
201 */
202 public static boolean isReservedByCastor(final String name) {
203 if (name == null) {
204 return false;
205 }
206 for (String reserved : CASTOR_RESERVED) {
207 if (reserved.equals(name)) {
208 return true;
209 }
210 }
211 return false;
212 }
213
214 /**
215 * Returns true if the given String is a reserved name by the Windows filesystem which will cause
216 * a problem when used as a class name under Windows.
217 *
218 * @param name The String to check against the list of keywords.
219 * @return True if the given String is a reserved name by Castor which may cause a problem when
220 * used as a variable name.
221 */
222 public static boolean isReservedByWindows(final String name) {
223 if (name == null) {
224 return false;
225 }
226 for (String windowsReserved : WINDOWS_RESERVED) {
227 if (windowsReserved.equalsIgnoreCase(name)) {
228 return true;
229 }
230 }
231 return false;
232 }
233
234 /**
235 * Returns true if the given String matches the production of a valid Java identifier.
236 *
237 * @param string The String to check the production of.
238 * @return True if the given String matches the production of a valid Java name, otherwise false.
239 */
240 public static boolean isValidJavaIdentifier(final String string) {
241 if ((string == null) || (string.length() == 0)) {
242 return false;
243 }
244
245 char[] chars = string.toCharArray();
246
247 if (isParameterizedCollectionsObject(string)) {
248 return true;
249 }
250
251 // -- make sure starting character is valid
252 if (!Character.isJavaIdentifierStart(chars[0])) {
253 return false;
254 }
255
256 for (char ch : chars) {
257 if (!Character.isJavaIdentifierPart(ch)) {
258 return false;
259 }
260 }
261 if (isKeyword(string)) {
262 return false;
263 }
264 return true;
265 }
266
267 /**
268 * Returns the package name from the given class name.
269 *
270 * @param className An arbitrary class name, optionally including a package.
271 * @return The package name from the given class name.
272 */
273 public static String getPackageFromClassName(final String className) {
274 if (className == null) {
275 return null;
276 }
277 int idx = className.lastIndexOf('.');
278 if (idx > 0) {
279 return className.substring(0, idx);
280 }
281 return null;
282 }
283
284 /**
285 * Returns the local class name from the given fully qualified class name.
286 *
287 * @param className An arbitrary class name, optionally including a package.
288 * @return The local name from the given class name.
289 */
290 public static String getLocalNameFromClassName(final String className) {
291 if (className == null) {
292 return null;
293 }
294 int idx = className.lastIndexOf('.');
295 if (idx > 0) {
296 return className.substring(idx + 1);
297 }
298 return className;
299 }
300
301 // --------------------------------------------------------------------------
302 }