001: /**********************************************************************
002: Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015:
016: Contributors:
017: 2003 Andy Jefferson - commented
018: ...
019: **********************************************************************/package org.jpox.util;
020:
021: import java.lang.reflect.Array;
022: import java.util.HashMap;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.StringTokenizer;
026:
027: import org.jpox.ClassLoaderResolver;
028: import org.jpox.exceptions.ClassNotResolvedException;
029: import org.jpox.exceptions.JPOXUserException;
030:
031: /**
032: * Utility class handling Imports.
033: *
034: * @version $Revision: 1.13 $
035: **/
036: public class Imports {
037: private static final Localiser LOCALISER = Localiser
038: .getInstance("org.jpox.Localisation");
039:
040: private HashMap primitives = new HashMap();
041: private HashMap importedClassesByName = new HashMap();
042: private HashSet importedPackageNames = new HashSet();
043:
044: /**
045: * Constructor.
046: **/
047: public Imports() {
048: //imported automatically into queries
049: primitives.put("boolean", boolean.class);
050: primitives.put("byte", byte.class);
051: primitives.put("char", char.class);
052: primitives.put("short", short.class);
053: primitives.put("int", int.class);
054: primitives.put("long", long.class);
055: primitives.put("float", float.class);
056: primitives.put("double", double.class);
057: importedPackageNames.add("java.lang");
058: }
059:
060: /**
061: * Method to import the package given by the specified class.
062: * @param className The class name
063: **/
064: public void importPackage(String className) {
065: int lastDot = className.lastIndexOf('.');
066:
067: if (lastDot > 0) {
068: importedPackageNames.add(className.substring(0, lastDot));
069: }
070: }
071:
072: /**
073: * Method to import the specified class.
074: * @param className Class to import
075: */
076: public void importClass(String className) {
077: int lastDot = className.lastIndexOf('.');
078: if (lastDot > 0) {
079: importedClassesByName.put(className.substring(lastDot + 1),
080: className);
081: }
082: }
083:
084: /**
085: * Utility to parse the imports.
086: * @param imports The Imports string
087: * @throws JPOXUserException when finding an invalid declaration
088: */
089: public void parseImports(String imports) {
090: StringTokenizer t1 = new StringTokenizer(imports, ";");
091:
092: while (t1.hasMoreTokens()) {
093: String importDecl = t1.nextToken().trim();
094:
095: if (importDecl.length() == 0 && !t1.hasMoreTokens()) {
096: break;
097: }
098:
099: StringTokenizer t2 = new StringTokenizer(importDecl, " ");
100:
101: if (t2.countTokens() != 2
102: || !t2.nextToken().equals("import")) {
103: throw new JPOXUserException(LOCALISER.msg("021002",
104: importDecl));
105: }
106:
107: String importName = t2.nextToken();
108: int lastDot = importName.lastIndexOf(".");
109: String lastPart = importName.substring(lastDot + 1);
110:
111: if (lastPart.equals("*")) {
112: if (lastDot < 1) {
113: throw new JPOXUserException(LOCALISER.msg("021003",
114: importName));
115: }
116:
117: importedPackageNames.add(importName.substring(0,
118: lastDot));
119: } else {
120: if (importedClassesByName.put(lastPart, importName) != null) {
121: // Duplicated imports are valid (see spec 14.4 "declareImports"), so just log it for info
122: JPOXLogger.QUERY.info(LOCALISER.msg("021004",
123: importName));
124: }
125: }
126: }
127: }
128:
129: /**
130: * Utility to resolve a class declaration.
131: * @param classDecl The class declaration
132: * @param clr ClassLoaderResolver
133: * @param primaryClassLoader The primary ClassLoader for the class
134: * @return The class
135: * @throws ClassNotResolvedException
136: * @throws JPOXUserException if a type is duplicately defined
137: **/
138: public Class resolveClassDeclaration(String classDecl,
139: ClassLoaderResolver clr, ClassLoader primaryClassLoader) {
140: boolean isArray = classDecl.indexOf('[') >= 0;
141: if (isArray) {
142: classDecl = classDecl.substring(0, classDecl.indexOf('['));
143: }
144:
145: Class c;
146: if (classDecl.indexOf('.') < 0) {
147: c = (Class) primitives.get(classDecl);
148: if (c == null) {
149: String cd = (String) importedClassesByName
150: .get(classDecl);
151: if (cd != null) {
152: c = clr.classForName(cd, primaryClassLoader);
153: }
154: }
155:
156: if (c == null) {
157: Iterator packageNames = importedPackageNames.iterator();
158: while (packageNames.hasNext()) {
159: String packageName = (String) packageNames.next();
160:
161: try {
162: Class c1 = clr.classForName(packageName + '.'
163: + classDecl, primaryClassLoader);
164: if (c != null && c1 != null) {
165: // Duplicate definition of type
166: throw new JPOXUserException(LOCALISER
167: .msg("021008", c.getName(), c1
168: .getName()));
169: }
170:
171: c = c1;
172: } catch (ClassNotResolvedException e) {
173: // Do nothing
174: }
175: }
176:
177: if (c == null) {
178: throw new ClassNotResolvedException(classDecl);
179: }
180:
181: JPOXLogger.GENERAL.info(LOCALISER.msg("021010",
182: classDecl, c.getName()));
183:
184: // Give warning that the performance could have been improved by explicit usage
185: JPOXLogger.GENERAL.info(LOCALISER.msg("021009", c
186: .getName()));
187: }
188: } else {
189: c = clr.classForName(classDecl, primaryClassLoader);
190: }
191:
192: if (isArray) {
193: c = Array.newInstance(c, 0).getClass();
194: }
195:
196: return c;
197: }
198: }
|