package org.jacorb.ir;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import org.omg.CORBA.INTF_REPOS;
import org.omg.CORBA.portable.BoxedValueHelper;
import org.omg.CORBA.StringValueHelper;
import org.omg.CORBA.WStringValueHelper;
/**
* This class builds CORBA repository IDs from Java classes
* or class names, or builds Java class names from repository
* IDs
*/
public class RepositoryID
{
/**
* Returns the fully qualified name of the Java class to which
* the given Repository ID is mapped.
*/
public static String className (String repId,
ClassLoader loader)
{
return className (repId, null, loader);
}
/**
* Returns the fully qualified name of the Java class to which
* the given Repository ID is mapped, with a given suffix appended
* to the class name. For example, the string "Helper" can be used
* as the suffix to find the helper class for a given Repository ID.
*/
public static String className (String repId,
String suffix,
ClassLoader loader)
{
if (repId.startsWith ("RMI:"))
{
// TODO should convertFromISOLatin1 be called in else branch also?
repId = convertFromISOLatin1(repId);
return repId.substring (4, repId.indexOf (':', 4))
+ ( suffix != null ? suffix : "" );
}
else if (repId.startsWith ("IDL:"))
{
if (repId.equals(WStringValueHelper.id()))
{
return "java.lang.String";
}
if (repId.equals(StringValueHelper.id()))
{
return "java.lang.String";
}
final String id = repId.substring (4, repId.lastIndexOf(':'))
+ ( suffix != null ? suffix : "" );
int firstSlash = id.indexOf ("/");
final String prefix;
if (firstSlash == -1)
{
prefix = "";
}
else
{
prefix = id.substring (0, firstSlash);
}
if (prefix.equals ("omg.org"))
{
return ir2scopes ("org.omg",
id.substring (firstSlash + 1),
loader);
}
else if (prefix.indexOf ('.') != -1)
{
return ir2scopes (reversePrefix (prefix),
id.substring (firstSlash + 1),
loader);
}
else
{
return ir2scopes ("", id, loader);
}
}
else
{
throw new INTF_REPOS ("Unrecognized RepositoryID: " + repId);
}
}
/**
* Convert the repository ID with escape sequences back to original strings.
*
* com.sun.corba.se.internal.orbutil.RepositoryId
* contains an implementation of this conversion.
* however the method is private and its an internal sun class.
*/
private static String convertFromISOLatin1 (String id) {
StringBuffer dest = new StringBuffer(id.length());
int pos = 0;
int index = -1;
while ((index = id.indexOf("\\U", pos)) != -1)
{
dest.append(id.substring(pos, index));
pos = index + 6;
// convert the hexa val in 4 char into one char
char theChar = (char)(Integer.parseInt(id.substring(index+2, index+6), 16));
dest.append(theChar);
}
if (pos < id.length())
{
dest.append(id.substring(pos));
}
return dest.toString();
}
private static final String reversePrefix (String prefix)
{
StringTokenizer tok = new StringTokenizer (prefix, ".");
String result = tok.nextToken();
while (tok.hasMoreTokens())
{
result = tok.nextToken() + '.' + result;
}
return result;
}
/**
* Convert a repoID path string to a fully qualified class name.
* Check to see if the final name in the class is actually nested within
* a "intfPackage" package, and modify the FQ class name appropriately.
*/
private static String ir2scopes (String prefix,
String s,
ClassLoader loader)
{
if( s.indexOf("/") < 0)
{
return s;
}
StringBuffer sb = new StringBuffer();
if (prefix != null && prefix.length() > 0)
{
sb.append(prefix + ".");
}
sb.append (s);
int lastdot = -1;
for (int dotpos = sb.indexOf ("/"); dotpos >= 0; dotpos = sb.indexOf ("/", dotpos))
{
sb.setCharAt (dotpos, '.');
lastdot = dotpos;
}
String scope = sb.toString ();
if (loadClass (scope, loader) == null)
{
sb.insert (lastdot,"Package");
String pkgscope = sb.toString ();
if (loadClass (pkgscope, loader) != null)
{
scope = pkgscope;
}
}
return scope;
}
public static String repId (Class c)
{
if (org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom (c))
{
String className = c.getName();
String body = "";
// add "IDL:" and ":1.0"
// and swap "org.omg" if necessary
if( className.startsWith("org.omg") ||
className.startsWith("org/omg") )
{
if( className.length() > 7 )
{
body = className.substring(7);
}
return "IDL:omg.org/" + scopesToIR(body) + ":1.0";
}
return "IDL:" + scopesToIR(className) + ":1.0" ;
}
return org.jacorb.util.ValueHandler.getRMIRepositoryID (c);
}
/**
* Convert a fully qualified class name to a repoID by first eliminating any
* "Package" extensions then replacing all dots with slashes. Note that this
* function is an imperfect compliment of ir2scopes in that it does not have
* a way to distinguish any prefix that was explicitly added to a repository
* ID to make a class name.
*/
private static String scopesToIR( String s )
{
if( s.indexOf(".") < 0)
{
return s;
}
StringBuffer sb = new StringBuffer (s);
String pkgstr = "Package";
for (int i = sb.indexOf (pkgstr); i != -1; i = sb.indexOf (pkgstr, i))
{
sb.delete (i, i+pkgstr.length());
}
for (int i = sb.indexOf ("."); i != -1; i = sb.indexOf (".", i))
{
sb.setCharAt (i,'/');
}
return sb.toString();
}
/**
* Converts a class name to a Repository ID.
* @param className the class name to convert
* @param resolveClass indicates whether the method should try to
* resolve and load the class. If true and the class could
* not be loaded, an IllegalArgumentException will be thrown
*/
public static String toRepositoryID ( String className,
boolean resolveClass,
ClassLoader loader )
{
if( className.equals("") ||
className.startsWith("IDL:") ||
className.startsWith ("RMI:"))
{
return className;
}
if( resolveClass )
{
Class c = loadClass(className, loader);
if (c == null)
{
throw new IllegalArgumentException("cannot find class: " + className);
}
return repId (c);
}
return "IDL:" + className + ":1.0";
}
public static String toRepositoryID( String className, ClassLoader loader )
{
return toRepositoryID( className, true, loader );
}
/**
* Loads class `name' using an appropriate class loader.
* Returns the corresponding class object, or null if the class loader
* cannot find a class by that name.
*/
private static Class loadClass (String name, ClassLoader loader)
{
try
{
if (loader != null)
{
return loader.loadClass (name);
}
return org.jacorb.util.ObjectUtil.classForName(name);
}
catch (ClassNotFoundException e)
{
return null;
}
}
/**
* Creates a BoxedValueHelper instance for a given repository ID.
* @param repId the repository ID of the boxed value type
* @return a newly created BoxedValueHelper, or null if no
* BoxedValueHelper class can be found for that ID
* @throws RuntimeException if creation of the Helper instance fails
*/
public static BoxedValueHelper createBoxedValueHelper(String repId,
ClassLoader loader)
{
String className = className(repId, "Helper", loader);
Class clazz = loadClass(className, loader);
if (clazz != null)
{
try
{
return (BoxedValueHelper)clazz.newInstance();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
return null;
}
}