0001: /*
0002: * JBoss, Home of Professional Open Source.
0003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
0004: * as indicated by the @author tags. See the copyright.txt file in the
0005: * distribution for a full listing of individual contributors.
0006: *
0007: * This is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU Lesser General Public License as
0009: * published by the Free Software Foundation; either version 2.1 of
0010: * the License, or (at your option) any later version.
0011: *
0012: * This software is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this software; if not, write to the Free
0019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021: */
0022: package org.jboss.iiop.rmi.ir;
0023:
0024: import org.omg.CORBA.ORB;
0025: import org.omg.CORBA.Any;
0026: import org.omg.CORBA.TypeCode;
0027: import org.omg.CORBA.TCKind;
0028: import org.omg.CORBA.DefinitionKind;
0029: import org.omg.CORBA.Repository;
0030: import org.omg.CORBA.RepositoryHelper;
0031: import org.omg.CORBA.InterfaceDef;
0032: import org.omg.CORBA.InterfaceDefHelper;
0033: import org.omg.CORBA.ParameterDescription;
0034: import org.omg.CORBA.ParameterMode;
0035: import org.omg.CORBA.ValueDef;
0036: import org.omg.CORBA.ValueDefHelper;
0037: import org.omg.CORBA.ValueMember;
0038: import org.omg.CORBA.StructMember;
0039: import org.omg.CORBA.ExceptionDef;
0040: import org.omg.CORBA.ExceptionDefHelper;
0041: import org.omg.CORBA.VM_NONE;
0042: import org.omg.CORBA.VM_CUSTOM;
0043: import org.omg.CORBA.VM_ABSTRACT;
0044: import org.omg.PortableServer.POA;
0045:
0046: import org.jboss.iiop.rmi.Util;
0047: import org.jboss.iiop.rmi.ContainerAnalysis;
0048: import org.jboss.iiop.rmi.InterfaceAnalysis;
0049: import org.jboss.iiop.rmi.ExceptionAnalysis;
0050: import org.jboss.iiop.rmi.ValueAnalysis;
0051: import org.jboss.iiop.rmi.ValueMemberAnalysis;
0052: import org.jboss.iiop.rmi.ConstantAnalysis;
0053: import org.jboss.iiop.rmi.AttributeAnalysis;
0054: import org.jboss.iiop.rmi.OperationAnalysis;
0055: import org.jboss.iiop.rmi.ParameterAnalysis;
0056: import org.jboss.iiop.rmi.RMIIIOPViolationException;
0057: import org.jboss.iiop.rmi.RMIIIOPValueNotSerializableException;
0058: import org.jboss.iiop.rmi.RmiIdlUtil;
0059:
0060: import java.util.ArrayList;
0061: import java.util.HashMap;
0062: import java.util.List;
0063: import java.util.Map;
0064:
0065: import javax.naming.InitialContext;
0066: import javax.naming.NamingException;
0067:
0068: /**
0069: * An Interface Repository.
0070: *
0071: * @author <a href="mailto:osh@sparre.dk">Ole Husgaard</a>
0072: * @version $Revision: 57194 $
0073: */
0074: public class InterfaceRepository {
0075: // Constants -----------------------------------------------------
0076:
0077: // Attributes ----------------------------------------------------
0078:
0079: // Static --------------------------------------------------------
0080:
0081: /**
0082: * Maps java classes to IDL TypeCodes for primitives.
0083: */
0084: private static Map primitiveTypeCodeMap;
0085:
0086: /**
0087: * Maps java classes to IDL TypeCodes for constants.
0088: */
0089: private static Map constantTypeCodeMap;
0090:
0091: static {
0092: // Get an ORB for creating type codes.
0093: ORB orb;
0094: try {
0095: orb = (ORB) new InitialContext()
0096: .lookup("java:/JBossCorbaORB");
0097: } catch (NamingException ex) {
0098: throw new RuntimeException(
0099: "Cannot lookup java:/JBossCorbaORB: " + ex);
0100: }
0101:
0102: // TypeCodes for primitive types
0103: primitiveTypeCodeMap = new HashMap();
0104: primitiveTypeCodeMap.put(Void.TYPE, orb
0105: .get_primitive_tc(TCKind.tk_void));
0106: primitiveTypeCodeMap.put(Boolean.TYPE, orb
0107: .get_primitive_tc(TCKind.tk_boolean));
0108: primitiveTypeCodeMap.put(Character.TYPE, orb
0109: .get_primitive_tc(TCKind.tk_wchar));
0110: primitiveTypeCodeMap.put(Byte.TYPE, orb
0111: .get_primitive_tc(TCKind.tk_octet));
0112: primitiveTypeCodeMap.put(Short.TYPE, orb
0113: .get_primitive_tc(TCKind.tk_short));
0114: primitiveTypeCodeMap.put(Integer.TYPE, orb
0115: .get_primitive_tc(TCKind.tk_long));
0116: primitiveTypeCodeMap.put(Long.TYPE, orb
0117: .get_primitive_tc(TCKind.tk_longlong));
0118: primitiveTypeCodeMap.put(Float.TYPE, orb
0119: .get_primitive_tc(TCKind.tk_float));
0120: primitiveTypeCodeMap.put(Double.TYPE, orb
0121: .get_primitive_tc(TCKind.tk_double));
0122:
0123: // TypeCodes for constant types
0124: constantTypeCodeMap = new HashMap(primitiveTypeCodeMap);
0125: constantTypeCodeMap.put(String.class, orb.create_wstring_tc(0));
0126: }
0127:
0128: /**
0129: * Static logger used by the interface repository.
0130: */
0131: private static final org.jboss.logging.Logger logger = org.jboss.logging.Logger
0132: .getLogger(InterfaceRepository.class);
0133:
0134: // Constructors --------------------------------------------------
0135:
0136: public InterfaceRepository(ORB orb, POA poa, String name) {
0137: this .orb = orb;
0138: this .poa = poa;
0139: impl = new RepositoryImpl(orb, poa, name);
0140: }
0141:
0142: // Public --------------------------------------------------------
0143:
0144: /**
0145: * Add mapping for a class.
0146: */
0147: public void mapClass(Class cls) throws RMIIIOPViolationException,
0148: IRConstructionException {
0149: // Just lookup a TypeCode for the class: That will provoke
0150: // mapping the class and adding it to the IR.
0151: getTypeCode(cls);
0152: }
0153:
0154: /**
0155: * Finish the build.
0156: */
0157: public void finishBuild() throws IRConstructionException {
0158: impl.allDone();
0159: }
0160:
0161: /**
0162: * Return a CORBA reference to this IR.
0163: */
0164: public Repository getReference() {
0165: return RepositoryHelper.narrow(impl.getReference());
0166: }
0167:
0168: /**
0169: * Deactivate all CORBA objects in this IR.
0170: */
0171: public void shutdown() {
0172: impl.shutdown();
0173: }
0174:
0175: // Z implementation ----------------------------------------------
0176:
0177: // Y overrides ---------------------------------------------------
0178:
0179: // Package protected ---------------------------------------------
0180:
0181: // Protected -----------------------------------------------------
0182:
0183: // Private -------------------------------------------------------
0184:
0185: /**
0186: * The repository implementation.
0187: */
0188: RepositoryImpl impl;
0189:
0190: /**
0191: * The ORB that I use.
0192: */
0193: private ORB orb = null;
0194:
0195: /**
0196: * The POA that I use.
0197: */
0198: private POA poa = null;
0199:
0200: /**
0201: * Maps java classes to IDL TypeCodes for parameter, result, attribute
0202: * and value member types.
0203: */
0204: private Map typeCodeMap = new HashMap(primitiveTypeCodeMap);
0205:
0206: /**
0207: * Maps java classes to <code>InterfaceDefImpl</code>s for interfaces.
0208: */
0209: private Map interfaceMap = new HashMap();
0210:
0211: /**
0212: * Maps java classes to <code>ValueDefImpl</code>s for values.
0213: */
0214: private Map valueMap = new HashMap();
0215:
0216: /**
0217: * Maps java classes to <code>ExceptionDefImpl</code>s for exceptions.
0218: */
0219: private Map exceptionMap = new HashMap();
0220:
0221: /**
0222: * Maps java classes to <code>ValueBoxDefImpl</code>s for arrays.
0223: */
0224: private Map arrayMap = new HashMap();
0225:
0226: /**
0227: * java.io.Serializable special mapping, as per section 1.3.10.1.
0228: * Do not use this variable directly, use the
0229: * <code>getJavaIoSerializable()</code> method instead, as that will
0230: * create the typedef in the IR on demand.
0231: */
0232: private AliasDefImpl javaIoSerializable = null;
0233:
0234: /**
0235: * java.io.Externalizable special mapping, as per section 1.3.10.1.
0236: * Do not use this variable directly, use the
0237: * <code>getJavaIoExternalizable()</code> method instead, as that will
0238: * create the typedef in the IR on demand.
0239: */
0240: private AliasDefImpl javaIoExternalizable = null;
0241:
0242: /**
0243: * java.lang.Object special mapping, as per section 1.3.10.2.
0244: * Do not use this variable directly, use the
0245: * <code>getJavaLang_Object()</code> method instead, as that will
0246: * create the typedef in the IR on demand.
0247: */
0248: private AliasDefImpl javaLang_Object = null;
0249:
0250: /**
0251: * java.lang.String special mapping, as per section 1.3.5.10.
0252: * Do not use this variable directly, use the
0253: * <code>getJavaLangString()</code> method instead, as that will
0254: * create the value type in the IR on demand.
0255: */
0256: private ValueDefImpl javaLangString = null;
0257:
0258: /**
0259: * java.lang.Class special mapping, as per section 1.3.5.11.
0260: * Do not use this variable directly, use the
0261: * <code>getJavaxRmiCORBAClassDesc()</code> method instead, as that will
0262: * create the value type in the IR on demand.
0263: */
0264: private ValueDefImpl javaxRmiCORBAClassDesc = null;
0265:
0266: /**
0267: * Returns the TypeCode suitable for an IDL constant.
0268: * @param cls The Java class denoting the type of the constant.
0269: */
0270: private TypeCode getConstantTypeCode(Class cls)
0271: throws IRConstructionException {
0272: if (cls == null)
0273: throw new IllegalArgumentException("Null class");
0274:
0275: TypeCode ret = (TypeCode) constantTypeCodeMap.get(cls);
0276:
0277: if (ret == null)
0278: throw new IRConstructionException("Bad class \""
0279: + cls.getName() + "\" for a constant.");
0280:
0281: return ret;
0282: }
0283:
0284: /**
0285: * Returns the TypeCode IDL TypeCodes for parameter, result, attribute
0286: * and value member types.
0287: * This may provoke a mapping of the class argument.
0288: *
0289: * Exception classes map to both values and exceptions. For these, this
0290: * method returns the typecode for the value, and you can use the
0291: * <code>getExceptionTypeCode</code> TODO method to get the typecode for the
0292: * mapping to exception.
0293: *
0294: * @param cls The Java class denoting the java type.
0295: */
0296: private TypeCode getTypeCode(Class cls)
0297: throws IRConstructionException, RMIIIOPViolationException {
0298: if (cls == null)
0299: throw new IllegalArgumentException("Null class");
0300:
0301: TypeCode ret = (TypeCode) typeCodeMap.get(cls);
0302:
0303: if (ret == null) {
0304: if (cls == java.lang.String.class)
0305: ret = getJavaLangString().type();
0306: else if (cls == java.lang.Object.class)
0307: ret = getJavaLang_Object().type();
0308: else if (cls == java.lang.Class.class)
0309: ret = getJavaxRmiCORBAClassDesc().type();
0310: else if (cls == java.io.Serializable.class)
0311: ret = getJavaIoSerializable().type();
0312: else if (cls == java.io.Externalizable.class)
0313: ret = getJavaIoExternalizable().type();
0314: else {
0315: // Try adding a mapping of the the class to the IR
0316: addClass(cls);
0317:
0318: // Lookup again, it should be there now.
0319: ret = (TypeCode) typeCodeMap.get(cls);
0320:
0321: if (ret == null)
0322: throw new IRConstructionException(
0323: "TypeCode for class " + cls.getName()
0324: + " unknown.");
0325: else
0326: return ret;
0327: }
0328:
0329: typeCodeMap.put(cls, ret);
0330: }
0331:
0332: return ret;
0333: }
0334:
0335: /**
0336: * Add a new IDL TypeCode for a mapped class.
0337: *
0338: * @param cls The Java class denoting the java type.
0339: * @param typeCode The IDL type code of the mapped java class.
0340: */
0341: private void addTypeCode(Class cls, TypeCode typeCode)
0342: throws IRConstructionException {
0343: if (cls == null)
0344: throw new IllegalArgumentException("Null class");
0345:
0346: TypeCode tc = (TypeCode) typeCodeMap.get(cls);
0347:
0348: if (tc != null)
0349: throw new IllegalArgumentException("Class " + cls.getName()
0350: + " already has TypeCode.");
0351:
0352: logger.trace("InterfaceRepository: added typecode for "
0353: + cls.getName());
0354: typeCodeMap.put(cls, typeCode);
0355: }
0356:
0357: /**
0358: * Get a reference to the special case mapping for java.io.Serializable.
0359: * This is according to "Java(TM) Language to IDL Mapping Specification",
0360: * section 1.3.10.1
0361: */
0362: private AliasDefImpl getJavaIoSerializable()
0363: throws IRConstructionException {
0364: if (javaIoSerializable == null) {
0365: final String id = "IDL:java/io/Serializable:1.0";
0366: final String name = "Serializable";
0367: final String version = "1.0";
0368:
0369: // Get module to add typedef to.
0370: ModuleDefImpl m = ensurePackageExists("java.io");
0371:
0372: TypeCode typeCode = orb.create_alias_tc(id, name, orb
0373: .get_primitive_tc(TCKind.tk_any));
0374: // TypeCode typeCode = new TypeCodeImpl(TCKind._tk_alias, id, name,
0375: // new TypeCodeImpl(TCKind.tk_any));
0376:
0377: javaIoSerializable = new AliasDefImpl(id, name, version, m,
0378: typeCode, impl);
0379: m.add(name, javaIoSerializable);
0380: }
0381:
0382: return javaIoSerializable;
0383: }
0384:
0385: /**
0386: * Get a reference to the special case mapping for java.io.Externalizable.
0387: * This is according to "Java(TM) Language to IDL Mapping Specification",
0388: * section 1.3.10.1
0389: */
0390: private AliasDefImpl getJavaIoExternalizable()
0391: throws IRConstructionException {
0392: if (javaIoExternalizable == null) {
0393: final String id = "IDL:java/io/Externalizable:1.0";
0394: final String name = "Externalizable";
0395: final String version = "1.0";
0396:
0397: // Get module to add typedef to.
0398: ModuleDefImpl m = ensurePackageExists("java.io");
0399:
0400: TypeCode typeCode = orb.create_alias_tc(id, name, orb
0401: .get_primitive_tc(TCKind.tk_any));
0402: // TypeCode typeCode = new TypeCodeImpl(TCKind._tk_alias, id, name,
0403: // new TypeCodeImpl(TCKind.tk_any));
0404:
0405: javaIoExternalizable = new AliasDefImpl(id, name, version,
0406: m, typeCode, impl);
0407: m.add(name, javaIoExternalizable);
0408: }
0409:
0410: return javaIoExternalizable;
0411: }
0412:
0413: /**
0414: * Get a reference to the special case mapping for java.lang.Object.
0415: * This is according to "Java(TM) Language to IDL Mapping Specification",
0416: * section 1.3.10.2
0417: */
0418: private AliasDefImpl getJavaLang_Object()
0419: throws IRConstructionException {
0420: if (javaLang_Object == null) {
0421: final String id = "IDL:java/lang/_Object:1.0";
0422: final String name = "_Object";
0423: final String version = "1.0";
0424:
0425: // Get module to add typedef to.
0426: ModuleDefImpl m = ensurePackageExists("java.lang");
0427:
0428: TypeCode typeCode = orb.create_alias_tc(id, name, orb
0429: .get_primitive_tc(TCKind.tk_any));
0430: // TypeCode typeCode = new TypeCodeImpl(TCKind._tk_alias, id, name,
0431: // new TypeCodeImpl(TCKind.tk_any));
0432:
0433: javaLang_Object = new AliasDefImpl(id, name, version, m,
0434: typeCode, impl);
0435: m.add(name, javaLang_Object);
0436: }
0437:
0438: return javaLang_Object;
0439: }
0440:
0441: /**
0442: * Get a reference to the special case mapping for java.lang.String.
0443: * This is according to "Java(TM) Language to IDL Mapping Specification",
0444: * section 1.3.5.10
0445: */
0446: private ValueDefImpl getJavaLangString()
0447: throws IRConstructionException {
0448: if (javaLangString == null) {
0449: ModuleDefImpl m = ensurePackageExists("org.omg.CORBA");
0450: ValueDefImpl val = new ValueDefImpl(
0451: "IDL:omg.org/CORBA/WStringValue:1.0",
0452: "WStringValue", "1.0", m, false, false,
0453: new String[0], new String[0], orb
0454: .get_primitive_tc(TCKind.tk_null), impl);
0455: ValueMemberDefImpl vmdi = new ValueMemberDefImpl(
0456: "IDL:omg.org/CORBA/WStringValue.data:1.0", "data",
0457: "1.0", orb.create_wstring_tc(0), true, val, impl);
0458: val.add("data", vmdi);
0459: m.add("WStringValue", val);
0460:
0461: javaLangString = val;
0462: }
0463:
0464: return javaLangString;
0465: }
0466:
0467: /**
0468: * Get a reference to the special case mapping for java.lang.Class.
0469: * This is according to "Java(TM) Language to IDL Mapping Specification",
0470: * section 1.3.5.11.
0471: */
0472: private ValueDefImpl getJavaxRmiCORBAClassDesc()
0473: throws IRConstructionException, RMIIIOPViolationException {
0474: if (javaxRmiCORBAClassDesc == null) {
0475: // Just map the right value class
0476: ValueAnalysis va = ValueAnalysis
0477: .getValueAnalysis(javax.rmi.CORBA.ClassDesc.class);
0478: ValueDefImpl val = addValue(va);
0479:
0480: // Warn if it does not conform to the specification.
0481: if (!"RMI:javax.rmi.CORBA.ClassDesc:B7C4E3FC9EBDC311:CFBF02CF5294176B"
0482: .equals(val.id()))
0483: logger
0484: .debug("Compatibility problem: Class "
0485: + "javax.rmi.CORBA.ClassDesc does not conform "
0486: + "to the Java(TM) Language to IDL Mapping "
0487: + "Specification (01-06-07), section 1.3.5.11.");
0488:
0489: javaxRmiCORBAClassDesc = val;
0490: }
0491:
0492: return javaxRmiCORBAClassDesc;
0493: }
0494:
0495: /**
0496: * Ensure that a package exists in the IR.
0497: * This will create modules in the IR as needed.
0498: *
0499: * @param pkg
0500: * The package that needs to be defined as a module in the IR.
0501: *
0502: * @return A reference to the IR module that represents the package.
0503: */
0504: private ModuleDefImpl ensurePackageExists(String pkgName)
0505: throws IRConstructionException {
0506: return ensurePackageExists(impl, "", pkgName);
0507: }
0508:
0509: /**
0510: * Ensure that a package exists in the IR.
0511: * This will create modules in the IR as needed.
0512: *
0513: * @param c
0514: * The container that the remainder of modules should be defined in.
0515: * @param previous
0516: * The IDL module name, from root to <code>c</code>.
0517: * @param remainder
0518: * The java package name, relative to <code>c</code>.
0519: *
0520: * @return A reference to the IR module that represents the package.
0521: */
0522: private ModuleDefImpl ensurePackageExists(LocalContainer c,
0523: String previous, String remainder)
0524: throws IRConstructionException {
0525: if ("".equals(remainder))
0526: return (ModuleDefImpl) c; // done
0527:
0528: int idx = remainder.indexOf('.');
0529: String base;
0530:
0531: if (idx == -1)
0532: base = remainder;
0533: else
0534: base = remainder.substring(0, idx);
0535: base = Util.javaToIDLName(base);
0536:
0537: if (previous.equals(""))
0538: previous = base;
0539: else
0540: previous = previous + "/" + base;
0541: if (idx == -1)
0542: remainder = "";
0543: else
0544: remainder = remainder.substring(idx + 1);
0545:
0546: LocalContainer next = null;
0547: LocalContained contained = (LocalContained) c._lookup(base);
0548:
0549: if (contained instanceof LocalContainer)
0550: next = (LocalContainer) contained;
0551: else if (contained != null)
0552: throw new IRConstructionException(
0553: "Name collision while creating package.");
0554:
0555: if (next == null) {
0556: String id = "IDL:" + previous + ":1.0";
0557:
0558: // Create module
0559: ModuleDefImpl m = new ModuleDefImpl(id, base, "1.0", c,
0560: impl);
0561: logger.trace("Created module \"" + id + "\".");
0562:
0563: c.add(base, m);
0564:
0565: if (idx == -1)
0566: return m; // done
0567:
0568: next = (LocalContainer) c._lookup(base); // Better be there now...
0569: } else // Check that next _is_ a module
0570: if (next.def_kind() != DefinitionKind.dk_Module)
0571: throw new IRConstructionException(
0572: "Name collision while creating package.");
0573:
0574: return ensurePackageExists(next, previous, remainder);
0575: }
0576:
0577: /**
0578: * Add a set of constants to a container (interface or value class).
0579: */
0580: private void addConstants(LocalContainer container,
0581: ContainerAnalysis ca) throws RMIIIOPViolationException,
0582: IRConstructionException {
0583: ConstantAnalysis[] consts = ca.getConstants();
0584: for (int i = 0; i < consts.length; ++i) {
0585: ConstantDefImpl cDef;
0586: String cid = ca.getMemberRepositoryId(consts[i]
0587: .getJavaName());
0588: String cName = consts[i].getIDLName();
0589:
0590: Class cls = consts[i].getType();
0591: logger.trace("Constant[" + i + "] class: " + cls.getName());
0592: TypeCode typeCode = getConstantTypeCode(cls);
0593:
0594: Any value = orb.create_any();
0595: consts[i].insertValue(value);
0596:
0597: logger.trace("Adding constant: " + cid);
0598: cDef = new ConstantDefImpl(cid, cName, "1.0", typeCode,
0599: value, container, impl);
0600: container.add(cName, cDef);
0601: }
0602: }
0603:
0604: /**
0605: * Add a set of attributes to a container (interface or value class).
0606: */
0607: private void addAttributes(LocalContainer container,
0608: ContainerAnalysis ca) throws RMIIIOPViolationException,
0609: IRConstructionException {
0610: AttributeAnalysis[] attrs = ca.getAttributes();
0611: logger.trace("Attribute count: " + attrs.length);
0612: for (int i = 0; i < attrs.length; ++i) {
0613: AttributeDefImpl aDef;
0614: String aid = ca.getMemberRepositoryId(attrs[i]
0615: .getJavaName());
0616: String aName = attrs[i].getIDLName();
0617:
0618: Class cls = attrs[i].getCls();
0619: logger
0620: .trace("Attribute[" + i + "] class: "
0621: + cls.getName());
0622:
0623: TypeCode typeCode = getTypeCode(cls);
0624:
0625: logger.trace("Adding: " + aid);
0626: aDef = new AttributeDefImpl(aid, aName, "1.0", attrs[i]
0627: .getMode(), typeCode, container, impl);
0628: container.add(aName, aDef);
0629: }
0630: }
0631:
0632: /**
0633: * Add a set of operations to a container (interface or value class).
0634: */
0635: private void addOperations(LocalContainer container,
0636: ContainerAnalysis ca) throws RMIIIOPViolationException,
0637: IRConstructionException {
0638: OperationAnalysis[] ops = ca.getOperations();
0639: logger.debug("Operation count: " + ops.length);
0640: for (int i = 0; i < ops.length; ++i) {
0641: OperationDefImpl oDef;
0642: String oName = ops[i].getIDLName();
0643: String oid = ca.getMemberRepositoryId(oName);
0644:
0645: Class cls = ops[i].getReturnType();
0646: logger.debug("Operation[" + i + "] return type class: "
0647: + cls.getName());
0648: TypeCode typeCode = getTypeCode(cls);
0649:
0650: ParameterAnalysis[] ps = ops[i].getParameters();
0651: ParameterDescription[] params = new ParameterDescription[ps.length];
0652: for (int j = 0; j < ps.length; ++j) {
0653: params[j] = new ParameterDescription(
0654: ps[j].getIDLName(),
0655: getTypeCode(ps[j].getCls()), null, // filled in later
0656: ParameterMode.PARAM_IN);
0657: }
0658:
0659: ExceptionAnalysis[] exc = ops[i].getMappedExceptions();
0660: ExceptionDef[] exceptions = new ExceptionDef[exc.length];
0661: for (int j = 0; j < exc.length; ++j) {
0662: ExceptionDefImpl e = addException(exc[j]);
0663: exceptions[j] = ExceptionDefHelper.narrow(e
0664: .getReference());
0665: }
0666:
0667: logger.debug("Adding: " + oid);
0668: oDef = new OperationDefImpl(oid, oName, "1.0", container,
0669: typeCode, params, exceptions, impl);
0670: container.add(oName, oDef);
0671: }
0672: }
0673:
0674: /**
0675: * Add a set of interfaces to the IR.
0676: *
0677: * @return An array of the IR IDs of the interfaces.
0678: */
0679: private String[] addInterfaces(ContainerAnalysis ca)
0680: throws RMIIIOPViolationException, IRConstructionException {
0681: logger.trace("Adding interfaces: ");
0682: InterfaceAnalysis[] interfaces = ca.getInterfaces();
0683: List base_interfaces = new ArrayList();
0684: for (int i = 0; i < interfaces.length; ++i) {
0685: InterfaceDefImpl idi = addInterface(interfaces[i]);
0686: base_interfaces.add(idi.id());
0687: logger.trace(" " + idi.id());
0688: }
0689: String[] strArr = new String[base_interfaces.size()];
0690: return (String[]) base_interfaces.toArray(strArr);
0691: }
0692:
0693: /**
0694: * Add a set of abstract valuetypes to the IR.
0695: *
0696: * @return An array of the IR IDs of the abstract valuetypes.
0697: */
0698: private String[] addAbstractBaseValuetypes(ContainerAnalysis ca)
0699: throws RMIIIOPViolationException, IRConstructionException {
0700: logger.trace("Adding abstract valuetypes: ");
0701: ValueAnalysis[] abstractValuetypes = ca
0702: .getAbstractBaseValuetypes();
0703: List abstract_base_valuetypes = new ArrayList();
0704: for (int i = 0; i < abstractValuetypes.length; ++i) {
0705: ValueDefImpl vdi = addValue(abstractValuetypes[i]);
0706: abstract_base_valuetypes.add(vdi.id());
0707: logger.trace(" " + vdi.id());
0708: }
0709: String[] strArr = new String[abstract_base_valuetypes.size()];
0710: return (String[]) abstract_base_valuetypes.toArray(strArr);
0711: }
0712:
0713: /**
0714: * Map the class and add its IIOP mapping to the repository.
0715: */
0716: private void addClass(Class cls) throws RMIIIOPViolationException,
0717: IRConstructionException {
0718: if (cls.isPrimitive())
0719: return; // No need to add primitives.
0720:
0721: if (cls.isArray()) {
0722: // Add array mapping
0723: addArray(cls);
0724: } else if (cls.isInterface()) {
0725: if (!RmiIdlUtil.isAbstractValueType(cls)) {
0726: // Analyse the interface
0727: InterfaceAnalysis ia = InterfaceAnalysis
0728: .getInterfaceAnalysis(cls);
0729:
0730: // Add analyzed interface (which may be abstract)
0731: addInterface(ia);
0732: } else {
0733: // Analyse the value
0734: ValueAnalysis va = ValueAnalysis.getValueAnalysis(cls);
0735:
0736: // Add analyzed value
0737: addValue(va);
0738: }
0739: } else if (Exception.class.isAssignableFrom(cls)) { // Exception type.
0740: // Analyse the exception
0741: ExceptionAnalysis ea = ExceptionAnalysis
0742: .getExceptionAnalysis(cls);
0743:
0744: // Add analyzed exception
0745: addException(ea);
0746: } else { // Got to be a value type.
0747: // Analyse the value
0748: ValueAnalysis va = ValueAnalysis.getValueAnalysis(cls);
0749:
0750: // Add analyzed value
0751: addValue(va);
0752: }
0753: }
0754:
0755: /**
0756: * Add an array.
0757: */
0758: private ValueBoxDefImpl addArray(Class cls)
0759: throws RMIIIOPViolationException, IRConstructionException {
0760: if (!cls.isArray())
0761: throw new IllegalArgumentException("Not an array class.");
0762:
0763: ValueBoxDefImpl vbDef;
0764:
0765: // Lookup: Has it already been added?
0766: vbDef = (ValueBoxDefImpl) arrayMap.get(cls);
0767: if (vbDef != null)
0768: return vbDef; // Yes, just return it.
0769:
0770: int dimensions = 0;
0771: Class compType = cls;
0772:
0773: do {
0774: compType = compType.getComponentType();
0775: ++dimensions;
0776: } while (compType.isArray());
0777:
0778: String typeName;
0779: String moduleName;
0780: TypeCode typeCode;
0781:
0782: if (compType.isPrimitive()) {
0783: if (compType == Boolean.TYPE) {
0784: typeName = "boolean";
0785: typeCode = orb.get_primitive_tc(TCKind.tk_boolean);
0786: } else if (compType == Character.TYPE) {
0787: typeName = "wchar";
0788: typeCode = orb.get_primitive_tc(TCKind.tk_wchar);
0789: } else if (compType == Byte.TYPE) {
0790: typeName = "octet";
0791: typeCode = orb.get_primitive_tc(TCKind.tk_octet);
0792: } else if (compType == Short.TYPE) {
0793: typeName = "short";
0794: typeCode = orb.get_primitive_tc(TCKind.tk_short);
0795: } else if (compType == Integer.TYPE) {
0796: typeName = "long";
0797: typeCode = orb.get_primitive_tc(TCKind.tk_long);
0798: } else if (compType == Long.TYPE) {
0799: typeName = "long_long";
0800: typeCode = orb.get_primitive_tc(TCKind.tk_longlong);
0801: } else if (compType == Float.TYPE) {
0802: typeName = "float";
0803: typeCode = orb.get_primitive_tc(TCKind.tk_float);
0804: } else if (compType == Double.TYPE) {
0805: typeName = "double";
0806: typeCode = orb.get_primitive_tc(TCKind.tk_double);
0807: } else {
0808: throw new IRConstructionException(
0809: "Unknown primitive type for " + "array type: "
0810: + cls.getName());
0811: }
0812:
0813: moduleName = "org.omg.boxedRMI";
0814: } else {
0815: typeCode = getTypeCode(compType); // map the component type.
0816:
0817: if (compType == java.lang.String.class)
0818: typeName = getJavaLangString().name();
0819: else if (compType == java.lang.Object.class)
0820: typeName = getJavaLang_Object().name();
0821: else if (compType == java.lang.Class.class)
0822: typeName = getJavaxRmiCORBAClassDesc().name();
0823: else if (compType == java.io.Serializable.class)
0824: typeName = getJavaIoSerializable().name();
0825: else if (compType == java.io.Externalizable.class)
0826: typeName = getJavaIoExternalizable().name();
0827: else if (compType.isInterface()
0828: && !RmiIdlUtil.isAbstractValueType(compType))
0829: typeName = ((InterfaceDefImpl) interfaceMap
0830: .get(compType)).name();
0831: else if (Exception.class.isAssignableFrom(compType)) // exception type
0832: typeName = ((ExceptionDefImpl) exceptionMap
0833: .get(compType)).name();
0834: else
0835: // must be value type
0836: typeName = ((ValueDefImpl) valueMap.get(compType))
0837: .name();
0838:
0839: moduleName = "org.omg.boxedRMI."
0840: + compType.getPackage().getName();
0841: }
0842:
0843: // Get module to add array to.
0844: ModuleDefImpl m = ensurePackageExists(moduleName);
0845:
0846: // Create an array of the types for the dimensions
0847: Class[] types = new Class[dimensions];
0848: types[dimensions - 1] = cls;
0849: for (int i = dimensions - 2; i >= 0; --i)
0850: types[i] = types[i + 1].getComponentType();
0851:
0852: // Create boxed sequences for all dimensions.
0853: for (int i = 0; i < dimensions; ++i) {
0854: Class type = types[i];
0855:
0856: typeCode = orb.create_sequence_tc(0, typeCode);
0857: vbDef = (ValueBoxDefImpl) arrayMap.get(type);
0858: if (vbDef == null) {
0859: String id = Util.getIRIdentifierOfClass(type);
0860:
0861: SequenceDefImpl sdi = new SequenceDefImpl(typeCode,
0862: impl);
0863:
0864: String name = "seq" + (i + 1) + "_" + typeName;
0865: // TypeCode boxTypeCode = new TypeCodeImpl(TCKind._tk_value_box,
0866: // id, name, typeCode);
0867: TypeCode boxTypeCode = orb.create_value_box_tc(id,
0868: name, typeCode);
0869: vbDef = new ValueBoxDefImpl(id, name, "1.0", m,
0870: boxTypeCode, impl);
0871:
0872: addTypeCode(type, vbDef.type());
0873: m.add(name, vbDef);
0874: impl.putSequenceImpl(id, typeCode, sdi, vbDef);
0875:
0876: arrayMap.put(type, vbDef); // Remember we mapped this.
0877:
0878: typeCode = boxTypeCode;
0879: } else
0880: typeCode = vbDef.type();
0881: }
0882:
0883: // Return the box of higest dimension.
0884: return vbDef;
0885: }
0886:
0887: /**
0888: * Add an interface.
0889: */
0890: private InterfaceDefImpl addInterface(InterfaceAnalysis ia)
0891: throws RMIIIOPViolationException, IRConstructionException {
0892: InterfaceDefImpl iDef;
0893: Class cls = ia.getCls();
0894:
0895: // Lookup: Has it already been added?
0896: iDef = (InterfaceDefImpl) interfaceMap.get(cls);
0897: if (iDef != null)
0898: return iDef; // Yes, just return it.
0899:
0900: if (ia.isAbstractInterface())
0901: logger.trace("Adding abstract interface: "
0902: + ia.getRepositoryId());
0903:
0904: // Get module to add interface to.
0905: ModuleDefImpl m = ensurePackageExists(cls.getPackage()
0906: .getName());
0907:
0908: // Add superinterfaces
0909: String[] base_interfaces = addInterfaces(ia);
0910:
0911: // Create the interface
0912: String base = cls.getName();
0913: base = base.substring(base.lastIndexOf('.') + 1);
0914: base = Util.javaToIDLName(base);
0915:
0916: iDef = new InterfaceDefImpl(ia.getRepositoryId(), base, "1.0",
0917: m, base_interfaces, impl);
0918: addTypeCode(cls, iDef.type());
0919: m.add(base, iDef);
0920: interfaceMap.put(cls, iDef); // Remember we mapped this.
0921:
0922: // Fill in constants
0923: addConstants(iDef, ia);
0924:
0925: // Add attributes
0926: addAttributes(iDef, ia);
0927:
0928: // Fill in operations
0929: addOperations(iDef, ia);
0930:
0931: logger.trace("Added interface: " + ia.getRepositoryId());
0932: return iDef;
0933: }
0934:
0935: /**
0936: * Add a value type.
0937: */
0938: private ValueDefImpl addValue(ValueAnalysis va)
0939: throws RMIIIOPViolationException, IRConstructionException {
0940: ValueDefImpl vDef;
0941: Class cls = va.getCls();
0942:
0943: // Lookup: Has it already been added?
0944: vDef = (ValueDefImpl) valueMap.get(cls);
0945: if (vDef != null)
0946: return vDef; // Yes, just return it.
0947:
0948: // Get module to add value to.
0949: ModuleDefImpl m = ensurePackageExists(cls.getPackage()
0950: .getName());
0951:
0952: // Add implemented interfaces
0953: String[] supported_interfaces = addInterfaces(va);
0954:
0955: // Add abstract base valuetypes
0956: String[] abstract_base_valuetypes = addAbstractBaseValuetypes(va);
0957:
0958: // Add superclass
0959: ValueDefImpl super Value = null;
0960: ValueAnalysis super Analysis = va.getSuperAnalysis();
0961: if (super Analysis != null)
0962: super Value = addValue(super Analysis);
0963:
0964: // Create the value
0965: String base = cls.getName();
0966: base = base.substring(base.lastIndexOf('.') + 1);
0967: base = Util.javaToIDLName(base);
0968:
0969: TypeCode baseTypeCode;
0970: if (super Value == null)
0971: baseTypeCode = orb.get_primitive_tc(TCKind.tk_null);
0972: else
0973: baseTypeCode = super Value.type();
0974:
0975: vDef = new ValueDefImpl(va.getRepositoryId(), base, "1.0", m,
0976: va.isAbstractValue(), va.isCustom(),
0977: supported_interfaces, abstract_base_valuetypes,
0978: baseTypeCode, impl);
0979: addTypeCode(cls, vDef.type());
0980: logger.debug("Value: base=" + base);
0981: m.add(base, vDef);
0982: valueMap.put(cls, vDef); // Remember we mapped this.
0983:
0984: // Fill in constants.
0985: addConstants(vDef, va);
0986:
0987: // Add value members
0988: ValueMemberAnalysis[] vmas = va.getMembers();
0989: logger.debug("Value member count: " + vmas.length);
0990: for (int i = 0; i < vmas.length; ++i) {
0991: ValueMemberDefImpl vmDef;
0992: String vmid = va.getMemberRepositoryId(vmas[i]
0993: .getJavaName());
0994: String vmName = vmas[i].getIDLName();
0995:
0996: Class vmCls = vmas[i].getCls();
0997: logger.debug("ValueMembers[" + i + "] class: "
0998: + vmCls.getName());
0999: TypeCode typeCode = getTypeCode(vmCls);
1000:
1001: boolean vmPublic = vmas[i].isPublic();
1002:
1003: logger.debug("Adding value member: " + vmid);
1004: vmDef = new ValueMemberDefImpl(vmid, vmName, "1.0",
1005: typeCode, vmPublic, vDef, impl);
1006: vDef.add(vmName, vmDef);
1007: }
1008:
1009: // Add attributes
1010: addAttributes(vDef, va);
1011:
1012: // TODO: Fill in operations.
1013:
1014: return vDef;
1015: }
1016:
1017: /**
1018: * Add an exception type.
1019: */
1020: private ExceptionDefImpl addException(ExceptionAnalysis ea)
1021: throws RMIIIOPViolationException, IRConstructionException {
1022: ExceptionDefImpl eDef;
1023: Class cls = ea.getCls();
1024:
1025: // Lookup: Has it already been added?
1026: eDef = (ExceptionDefImpl) exceptionMap.get(cls);
1027: if (eDef != null)
1028: return eDef; // Yes, just return it.
1029:
1030: // 1.3.7.1: map to value
1031: ValueDefImpl vDef = addValue(ea);
1032:
1033: // 1.3.7.2: map to exception
1034: ModuleDefImpl m = ensurePackageExists(cls.getPackage()
1035: .getName());
1036: String base = cls.getName();
1037: base = base.substring(base.lastIndexOf('.') + 1);
1038: if (base.endsWith("Exception"))
1039: base = base.substring(0, base.length() - 9);
1040: base = Util.javaToIDLName(base + "Ex");
1041:
1042: StructMember[] members = new StructMember[1];
1043: members[0] = new StructMember("value", vDef.type(), null/*ignored*/);
1044: TypeCode typeCode = orb.create_exception_tc(ea
1045: .getExceptionRepositoryId(), base, members);
1046:
1047: eDef = new ExceptionDefImpl(ea.getExceptionRepositoryId(),
1048: base, "1.0", typeCode, vDef, m, impl);
1049: logger.debug("Exception: base=" + base);
1050: m.add(base, eDef);
1051: exceptionMap.put(cls, eDef); // Remember we mapped this.
1052:
1053: return eDef;
1054: }
1055:
1056: // Inner classes -------------------------------------------------
1057: }
|