001: package org.jacorb.ir;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import java.util.StringTokenizer;
024: import org.omg.CORBA.portable.BoxedValueHelper;
025: import org.omg.CORBA.INTF_REPOS;
026:
027: /**
028: * This class builds CORBA repository IDs from Java classes
029: * or class names, or builds Java class names from repository
030: * IDs
031: */
032: public class RepositoryID {
033: /**
034: * Returns the fully qualified name of the Java class to which
035: * the given Repository ID is mapped.
036: */
037: public static String className(String repId, ClassLoader loader) {
038: return className(repId, null, loader);
039: }
040:
041: /**
042: * Returns the fully qualified name of the Java class to which
043: * the given Repository ID is mapped, with a given suffix appended
044: * to the class name. For example, the string "Helper" can be used
045: * as the suffix to find the helper class for a given Repository ID.
046: */
047: public static String className(String repId, String suffix,
048: ClassLoader loader) {
049: if (repId.startsWith("RMI:")) {
050: // TODO should convertFromISOLatin1 be called in else branch also?
051: repId = convertFromISOLatin1(repId);
052: return repId.substring(4, repId.indexOf(':', 4))
053: + (suffix != null ? suffix : "");
054: } else if (repId.startsWith("IDL:")) {
055: String id = repId.substring(4, repId.lastIndexOf(':'))
056: + (suffix != null ? suffix : "");
057: if (id.equals("omg.org/CORBA/WStringValue")) {
058: return "java.lang.String";
059: }
060:
061: int firstSlash = id.indexOf("/");
062: final String prefix;
063: if (firstSlash == -1) {
064: prefix = "";
065: } else {
066: prefix = id.substring(0, firstSlash);
067: }
068:
069: if (prefix.equals("omg.org")) {
070: return ir2scopes("org.omg", id
071: .substring(firstSlash + 1), loader);
072: } else if (prefix.indexOf('.') != -1) {
073: return ir2scopes(reversePrefix(prefix), id
074: .substring(firstSlash + 1), loader);
075: } else {
076: return ir2scopes("", id, loader);
077: }
078: } else {
079: throw new INTF_REPOS("Unrecognized RepositoryID: " + repId);
080: }
081: }
082:
083: /**
084: * Convert the repository ID with escape sequences back to original strings.
085: *
086: * com.sun.corba.se.internal.orbutil.RepositoryId
087: * contains an implementation of this conversion.
088: * however the method is private and its an internal sun class.
089: */
090: private static String convertFromISOLatin1(String id) {
091: StringBuffer dest = new StringBuffer(id.length());
092: int pos = 0;
093: int index = -1;
094:
095: while ((index = id.indexOf("\\U", pos)) != -1) {
096: dest.append(id.substring(pos, index));
097: pos = index + 6;
098: // convert the hexa val in 4 char into one char
099: char theChar = (char) (Integer.parseInt(id.substring(
100: index + 2, index + 6), 16));
101: dest.append(theChar);
102: }
103: if (pos < id.length()) {
104: dest.append(id.substring(pos));
105: }
106: return dest.toString();
107: }
108:
109: private static final String reversePrefix(String prefix) {
110: StringTokenizer tok = new StringTokenizer(prefix, ".");
111: String result = tok.nextToken();
112:
113: while (tok.hasMoreTokens()) {
114: result = tok.nextToken() + '.' + result;
115: }
116: return result;
117: }
118:
119: /**
120: * FIXME: This method needs documentation.
121: * What does this algorithm do, and why is it necessary? AS.
122: */
123: private static String ir2scopes(String prefix, String s,
124: ClassLoader loader) {
125: if (s.indexOf("/") < 0)
126: return s;
127: java.util.StringTokenizer strtok = new java.util.StringTokenizer(
128: s, "/");
129:
130: int count = strtok.countTokens();
131: StringBuffer sb = new StringBuffer();
132: sb.append(prefix);
133:
134: for (int i = 0; strtok.hasMoreTokens(); i++) {
135: String sc = strtok.nextToken();
136: Class c = null;
137: if (sb.toString().length() > 0)
138: c = loadClass(sb.toString() + "." + sc, loader);
139: else
140: c = loadClass(sc, loader);
141: if (c == null)
142: if (sb.toString().length() > 0)
143: sb.append("." + sc);
144: else
145: sb.append(sc);
146: else if (i < count - 1)
147: sb.append("." + sc + "Package");
148: else
149: sb.append("." + sc);
150: }
151:
152: return sb.toString();
153: }
154:
155: public static String repId(Class c) {
156: if (org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(c)) {
157: String className = c.getName();
158: String body = "";
159:
160: // add "IDL:" and ":1.0"
161: // and swap "org.omg" if necessary
162:
163: if (className.startsWith("org.omg")
164: || className.startsWith("org/omg")) {
165: if (className.length() > 7)
166: body = className.substring(7);
167: return "IDL:omg.org/" + scopesToIR(body) + ":1.0";
168: }
169: return "IDL:" + scopesToIR(className) + ":1.0";
170: }
171: return org.jacorb.util.ValueHandler.getRMIRepositoryID(c);
172: }
173:
174: private static String scopesToIR(String s) {
175: if (s.indexOf(".") < 0)
176: return s;
177: java.util.StringTokenizer strtok = new java.util.StringTokenizer(
178: s, ".");
179:
180: String scopes[] = new String[strtok.countTokens()];
181:
182: for (int i = 0; strtok.hasMoreTokens(); i++) {
183: String sc = strtok.nextToken();
184: if (sc.endsWith("Package"))
185: scopes[i] = sc.substring(0, sc.indexOf("Package"));
186: else
187: scopes[i] = sc;
188: }
189:
190: StringBuffer sb = new StringBuffer();
191: if (scopes.length > 1) {
192: for (int i = 0; i < scopes.length - 1; i++)
193: sb.append(scopes[i] + "/");
194: }
195:
196: sb.append(scopes[scopes.length - 1]);
197: return sb.toString();
198: }
199:
200: /**
201: * Converts a class name to a Repository ID.
202: * @param className the class name to convert
203: * @param resolveClass indicates whether the method should try to
204: * resolve and load the class. If true and the class could
205: * not be loaded, an IllegalArgumentException will be thrown
206: */
207: public static String toRepositoryID(String className,
208: boolean resolveClass, ClassLoader loader) {
209: if (className.equals("") || className.startsWith("IDL:")
210: || className.startsWith("RMI:")) {
211: return className;
212: }
213:
214: if (resolveClass) {
215:
216: Class c = loadClass(className, loader);
217: if (c == null) {
218: throw new IllegalArgumentException(
219: "cannot find class: " + className);
220: }
221: return repId(c);
222: }
223: return "IDL:" + className + ":1.0";
224: }
225:
226: public static String toRepositoryID(String className,
227: ClassLoader loader) {
228: return toRepositoryID(className, true, loader);
229: }
230:
231: /**
232: * Loads class `name' using an appropriate class loader.
233: * Returns the corresponding class object, or null if the class loader
234: * cannot find a class by that name.
235: */
236: private static Class loadClass(String name, ClassLoader loader) {
237: try {
238: if (loader != null) {
239: return loader.loadClass(name);
240: }
241: return org.jacorb.util.ObjectUtil.classForName(name);
242: } catch (ClassNotFoundException e) {
243: return null;
244: }
245: }
246:
247: /**
248: * Creates a BoxedValueHelper instance for a given repository ID.
249: * @param repId the repository ID of the boxed value type
250: * @return a newly created BoxedValueHelper, or null if no
251: * BoxedValueHelper class can be found for that ID
252: * @throws RuntimeException if creation of the Helper instance fails
253: */
254: public static BoxedValueHelper createBoxedValueHelper(String repId,
255: ClassLoader loader) {
256: String className = className(repId, "Helper", loader);
257: Class clazz = loadClass(className, loader);
258: if (clazz != null) {
259: try {
260: return (BoxedValueHelper) clazz.newInstance();
261: } catch (Exception e) {
262: throw new RuntimeException(e);
263: }
264: }
265: return null;
266: }
267: }
|