001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
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 GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mx.util;
023:
024: import java.util.HashSet;
025:
026: /**
027: * Utilities for handling meta data
028: *
029: * Based on Strings from common (should jbossmx use common?)
030: *
031: * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
032: * @author <a href="Scott.Stark@jboss.org">Scott Stark</a>
033: * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>
034: * @version $Revision: 57200 $
035: */
036: public final class MetaDataUtil {
037: // Constants -----------------------------------------------------
038:
039: public static final String BOOLEAN_TYPE_NAME = Boolean.TYPE
040: .getName();
041: public static final String BYTE_TYPE_NAME = Byte.TYPE.getName();
042: public static final String CHAR_TYPE_NAME = Character.TYPE
043: .getName();
044: public static final String DOUBLE_TYPE_NAME = Double.TYPE.getName();
045: public static final String FLOAT_TYPE_NAME = Float.TYPE.getName();
046: public static final String INT_TYPE_NAME = Integer.TYPE.getName();
047: public static final String LONG_TYPE_NAME = Long.TYPE.getName();
048: public static final String SHORT_TYPE_NAME = Short.TYPE.getName();
049: public static final String VOID_TYPE_NAME = Void.TYPE.getName();
050:
051: private static final HashSet reserved = new HashSet();
052:
053: static {
054: reserved.add("assert");
055: reserved.add("abstract");
056: reserved.add("boolean");
057: reserved.add("break");
058: reserved.add("byte");
059: reserved.add("case");
060: reserved.add("catch");
061: reserved.add("char");
062: reserved.add("class");
063: reserved.add("const");
064: reserved.add("continue");
065: reserved.add("default");
066: reserved.add("do");
067: reserved.add("double");
068: reserved.add("else");
069: reserved.add("extends");
070: reserved.add("false");
071: reserved.add("final");
072: reserved.add("finally");
073: reserved.add("float");
074: reserved.add("for");
075: reserved.add("goto");
076: reserved.add("if");
077: reserved.add("implements");
078: reserved.add("import");
079: reserved.add("instanceof");
080: reserved.add("int");
081: reserved.add("interface");
082: reserved.add("long");
083: reserved.add("native");
084: reserved.add("new");
085: reserved.add("null");
086: reserved.add("package");
087: reserved.add("private");
088: reserved.add("protected");
089: reserved.add("public");
090: reserved.add("return");
091: reserved.add("short");
092: reserved.add("static");
093: reserved.add("strictfp");
094: reserved.add("super");
095: reserved.add("switch");
096: reserved.add("synchronized");
097: reserved.add("this");
098: reserved.add("throw");
099: reserved.add("throws");
100: reserved.add("transient");
101: reserved.add("true");
102: reserved.add("try");
103: reserved.add("void");
104: reserved.add("volatile");
105: reserved.add("while");
106: }
107:
108: // Static --------------------------------------------------------
109:
110: /**
111: * Tests whether the passed string is a valid java identifier
112: *
113: * @param string the string to test
114: * @return true when it is valid
115: */
116: public static final boolean isValidJavaIdentifier(String string) {
117: // Null or empty
118: if (string == null || string.length() == 0)
119: return false;
120:
121: final char[] chars = string.toCharArray();
122:
123: // Invalid start character
124: if (Character.isJavaIdentifierStart(chars[0]) == false)
125: return false;
126:
127: // Invalid part character
128: for (int i = 1; i < chars.length; ++i) {
129: if (Character.isJavaIdentifierPart(chars[i]) == false)
130: return false;
131: }
132:
133: if (reserved.contains(string))
134: return false;
135:
136: // Yippee!
137: return true;
138: }
139:
140: /**
141: * Tests whether the passed string is a valid java type
142: *
143: * @param string the string to test
144: * @return true when it is valid
145: */
146: public static final boolean isValidJavaType(String string) {
147: // Null or empty
148: if (string == null || string.length() == 0)
149: return false;
150:
151: // Looks like an array
152: if (string.charAt(0) == '[') {
153: String baseClassName = getBaseClassName(string);
154: // But it is not valid
155: if (baseClassName == null)
156: return false;
157:
158: string = baseClassName;
159: }
160:
161: // Check for a primitive
162: if (isPrimitive(string))
163: return true;
164:
165: final char[] chars = string.toCharArray();
166:
167: int start = 0;
168:
169: for (int i = 0; i < chars.length; ++i) {
170: // Found a dot
171: if (chars[i] == '.') {
172: // But it as the start or straight after a previous dot
173: if (i == start)
174: return false;
175:
176: // Is what is before the dot a valid identifier?
177: if (isValidJavaIdentifier(string.substring(start, i)) == false)
178: return false;
179:
180: start = i + 1;
181: }
182: }
183:
184: // Check the trailing characters
185: if (start < chars.length
186: && isValidJavaIdentifier(string.substring(start,
187: chars.length)) == false)
188: return false;
189:
190: // Yippee!
191: return true;
192: }
193:
194: /**
195: * Gets the base class name, either the passed class name
196: * or the underlying class name if it is an array.<p>
197: *
198: * NOTE: The class is not check for validity.<p>
199: *
200: * Null is returned when the array declaration is invalid.
201: *
202: * @param string the string to test
203: * @return the underlying class name or null
204: */
205: public static String getBaseClassName(String className) {
206: final int length = className.length();
207: final int last = length - 1;
208: int i = 0;
209:
210: // Eat the array dimensions
211: while (i < length && className.charAt(i) == '[')
212: ++i;
213:
214: // It looks like an array
215: if (i > 0) {
216: // But is it valid
217: char type = className.charAt(i);
218: // Primitive array
219: if (type == 'B' || type == 'C' || type == 'D'
220: || type == 'F' || type == 'I' || type == 'J'
221: || type == 'S' || type == 'Z' || type == 'V') {
222: if (i != last)
223: return null;
224: return className.substring(last, length);
225: }
226: // Object Array
227: else if (className.charAt(i) != 'L' || i >= last - 1
228: || className.charAt(last) != ';')
229: return null;
230:
231: // Potentially valid array, class name might be rubbish
232: return className.substring(i + 1, last);
233: }
234:
235: // Not an array
236: return className;
237: }
238:
239: /**
240: * Checks whether a string is primitive
241: *
242: * @param string the string to test
243: * @return true if it is primitive
244: */
245: public static boolean isPrimitive(String string) {
246: if (string.equals(INT_TYPE_NAME))
247: return true;
248: if (string.equals(LONG_TYPE_NAME))
249: return true;
250: if (string.equals(BOOLEAN_TYPE_NAME))
251: return true;
252: if (string.equals(BYTE_TYPE_NAME))
253: return true;
254: if (string.equals(CHAR_TYPE_NAME))
255: return true;
256: if (string.equals(SHORT_TYPE_NAME))
257: return true;
258: if (string.equals(FLOAT_TYPE_NAME))
259: return true;
260: if (string.equals(DOUBLE_TYPE_NAME))
261: return true;
262: if (string.equals(VOID_TYPE_NAME))
263: return true;
264: return false;
265: }
266: }
|