View Javadoc
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 }