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