package org.jacorb.idl; /* * 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.io.File; import java.io.PrintWriter; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; /** * @author Gerald Brose */ public class AliasTypeSpec extends TypeSpec { /** the type for which this is an alias */ public TypeSpec originalType; private boolean written; private boolean originalTypeWasScopedName = false; /** * Class constructor, * @param ts - the TypeSpec for which to create a new alias */ public AliasTypeSpec(TypeSpec ts ) { super(IdlSymbol.new_num()); originalType = ts; } public Object clone() { AliasTypeSpec alias = new AliasTypeSpec((TypeSpec)type_spec.clone()); alias.name = name; alias.pack_name = pack_name; return alias; } public String full_name() { if (pack_name.length() > 0) { String fullName = ScopedName.unPseudoName(pack_name + "." + name); return getFullName(fullName); } else { return ScopedName.unPseudoName(name); } } /** * @return the type name of this alias, which is the name of the * original type */ public String typeName() { return originalType.typeName(); } public TypeSpec typeSpec() { return this; } /** * @return the original type for which this is an alias */ public TypeSpec originalType() { if (originalType instanceof AliasTypeSpec) { return (((AliasTypeSpec)originalType).originalType ()); } return originalType; } public void setPackage(String s) { if (pack_name.length() > 0) pack_name = s + "." + pack_name; else pack_name = s; pack_name = parser.pack_replace(pack_name); } public void setEnclosingSymbol(IdlSymbol s) { if (enclosing_symbol != null && enclosing_symbol != s) throw new RuntimeException("Compiler Error: trying to reassign container for " + name); enclosing_symbol = s; } /** * @return true if this is a basic type */ public boolean basic() { return false; } /** * Perform the parsing phase, must be called before code * generation */ public void parse() { if (originalType instanceof TemplateTypeSpec) { ((TemplateTypeSpec)originalType).markTypeDefd(); } if (originalType instanceof ConstrTypeSpec || originalType instanceof FixedPointType || originalType instanceof SequenceType || originalType instanceof ArrayTypeSpec) { originalType.parse(); if (originalType.typeName().indexOf('.') < 0) { String tName = null; if (originalType instanceof VectorType) { tName = originalType.typeName().substring(0, originalType.typeName().indexOf('[')); } else { tName = originalType.typeName(); } addImportedName(tName); } } if (originalType instanceof ScopedName) { if (parser.logger.isLoggable(Level.ALL)) parser.logger.log(Level.ALL, " Alias " + name + " has scoped name orig Type : " + ((ScopedName)originalType).toString()); originalType = ((ScopedName)originalType).resolvedTypeSpec(); originalTypeWasScopedName = true; if (originalType instanceof AliasTypeSpec) addImportedAlias(originalType.full_name()); else addImportedName(originalType.typeName()); } } public String toString() { return originalType.toString(); } /** * @return a string for an expression of type TypeCode that describes this type * Note that this is the TypeSpec for the alias type and is not unwound to * the original type. */ public String getTypeCodeExpression() { return getTypeCodeExpression(new HashSet()); } public String getTypeCodeExpression(Set knownTypes) { //TODO: what happens, when actual type is in knownTypes? return "org.omg.CORBA.ORB.init().create_alias_tc(" + full_name() + "Helper.id(), \"" + name + "\"," + originalType.typeSpec().getTypeCodeExpression(knownTypes) + ")"; } public String className() { String fullName = full_name(); String cName; if (fullName.indexOf('.') > 0) { pack_name = fullName.substring(0, fullName.lastIndexOf('.')); cName = fullName.substring(fullName.lastIndexOf('.') + 1); } else { pack_name = ""; cName = fullName; } return cName; } /** * Code generation, generate holder and helper classes. Holder classes * are only generated for array and sequence types. */ public void print(PrintWriter ps) { setPrintPhaseNames(); // no code generation for included definitions if (included && !generateIncluded()) return; if (!written) { // guard against recursive entries, which can happen due to // containments, e.g., an alias within an interface that refers // back to the interface written = true; try { if (!(originalType instanceof FixedPointType) && !(originalType.typeSpec() instanceof ArrayTypeSpec) && !(originalType.typeSpec() instanceof StringType) && !(originalType.typeSpec() instanceof SequenceType) && ! originalTypeWasScopedName && !(originalType instanceof ConstrTypeSpec && ((ConstrTypeSpec)originalType).declaration() instanceof Interface ) ) { // only print local type definitions, not just // scoped names (references to other defs), which would // lead to loops! originalType.print(ps); } if(originalType.typeSpec() instanceof ArrayTypeSpec) { originalType.type_spec.print(ps); } String className = className(); String path = parser.out_dir + fileSeparator + pack_name.replace('.', fileSeparator); File dir = new File(path); if (!dir.exists()) { if (!dir.mkdirs()) { org.jacorb.idl.parser.fatal_error("Unable to create " + path, null); } } String fname = null; PrintWriter decl_ps = null; if ( originalType instanceof TemplateTypeSpec && !(originalType instanceof StringType)) { // print the holder class fname = className + "Holder.java"; File f = new File(dir, fname); if (GlobalInputStream.isMoreRecentThan(f)) { decl_ps = new PrintWriter(new java.io.FileWriter(f)); printHolderClass(className, decl_ps); decl_ps.close(); } } fname = className + "Helper.java"; File f = new File(dir, fname); if (GlobalInputStream.isMoreRecentThan(f)) { // print the helper class decl_ps = new PrintWriter(new java.io.FileWriter(f)); printHelperClass(className, decl_ps); decl_ps.close(); } } catch(java.io.IOException i) { throw new RuntimeException("File IO error" + i); } } } public String printReadStatement(String varname, String streamname) { if (doUnwind()) { return originalType.printReadStatement(varname, streamname); } return varname + " = " + full_name() + "Helper.read(" + streamname + ");"; } public String printReadExpression(String streamname) { if (doUnwind()) { return originalType.printReadExpression(streamname); } return full_name() + "Helper.read(" + streamname + ")"; } public String printWriteStatement(String var_name, String streamname) { if (doUnwind()) { return originalType.printWriteStatement(var_name, streamname); } return full_name() + "Helper.write(" + streamname + "," + var_name + ");"; } /** * @return true iff the original type is such that the alias should * be unwound to it, either anothetr alias, a constructed type (e.g a struct), * an any, a basic type (long, short, etc.) */ private boolean doUnwind() { return ( originalType.basic() && ( !(originalType instanceof TemplateTypeSpec) || originalType instanceof StringType ) ) || originalType instanceof AliasTypeSpec || originalType instanceof ConstrTypeSpec || originalType instanceof AnyType ; } public String holderName() { if (doUnwind()) { return originalType.holderName(); } return full_name() + "Holder"; } /** * generates the holder class for this alias type */ private void printHolderClass(String className, PrintWriter ps) { if (!pack_name.equals("")) ps.println("package " + pack_name + ";"); printImport(ps); printClassComment("alias", className, ps); ps.println("public" + parser.getFinalString() + " class " + className + "Holder"); ps.println("\timplements org.omg.CORBA.portable.Streamable"); ps.println("{"); ps.println("\tpublic " + originalType.typeName() + " value;" + Environment.NL); ps.println("\tpublic " + className + "Holder ()"); ps.println("\t{"); ps.println("\t}"); ps.println("\tpublic " + className + "Holder (final " + originalType.typeName() + " initial)"); ps.println("\t{"); ps.println("\t\tvalue = initial;"); ps.println("\t}"); ps.println("\tpublic org.omg.CORBA.TypeCode _type ()"); ps.println("\t{"); ps.println("\t\treturn " + className + "Helper.type ();"); ps.println("\t}"); ps.println("\tpublic void _read (final org.omg.CORBA.portable.InputStream in)"); ps.println("\t{"); ps.println("\t\tvalue = " + className + "Helper.read (in);"); ps.println("\t}"); ps.println("\tpublic void _write (final org.omg.CORBA.portable.OutputStream out)"); ps.println("\t{"); ps.println("\t\t" + className + "Helper.write (out,value);"); ps.println("\t}"); ps.println("}"); } /** * generates the holder class for this alias type */ private void printHelperClass(String className, PrintWriter ps) { if (!pack_name.equals("")) { ps.println("package " + pack_name + ";"); } printImport(ps); printClassComment("alias", className, ps); ps.println("public abstract class " + className + "Helper"); ps.println("{"); ps.println("\tprivate volatile static org.omg.CORBA.TypeCode _type;" + Environment.NL); String type = originalType.typeName(); ps.println("\tpublic static void insert (org.omg.CORBA.Any any, " + type + " s)"); ps.println("\t{"); TypeSpec origType = this.originalType(); boolean useAnySpeedAccessor = !(origType instanceof TemplateTypeSpec) && !(origType instanceof ConstrTypeSpec) && BaseType.isBasicName(origType.typeName()); if (useAnySpeedAccessor) { ps.print("\t\tany."); ps.print(this.originalType().printInsertExpression()); ps.println("(s);"); } else { ps.println("\t\tany.type (type ());"); ps.println("\t\twrite (any.create_output_stream (), s);"); } ps.println("\t}" + Environment.NL); ps.println("\tpublic static " + type + " extract (final org.omg.CORBA.Any any)"); ps.println("\t{"); if (useAnySpeedAccessor) { ps.print("\t\treturn any."); ps.print(this.originalType().printExtractExpression()); ps.println("();"); } else { ps.println ("\t\tif ( any.type().kind() == org.omg.CORBA.TCKind.tk_null)"); ps.println ("\t\t{"); ps.println ("\t\t\tthrow new org.omg.CORBA.BAD_OPERATION (\"Can't extract from Any with null type.\");"); ps.println ("\t\t}"); ps.println("\t\treturn read (any.create_input_stream ());"); } ps.println("\t}" + Environment.NL); ps.println("\tpublic static org.omg.CORBA.TypeCode type ()"); ps.println("\t{"); ps.println("\t\tif (_type == null)"); ps.println("\t\t{"); ps.println("\t\t\tsynchronized(" + className + "Helper.class)"); ps.println("\t\t\t{"); ps.println("\t\t\t\tif (_type == null)"); ps.println("\t\t\t\t{"); ps.println("\t\t\t\t\t_type = " + getTypeCodeExpression() + ";"); ps.println("\t\t\t\t}"); ps.println("\t\t\t}"); ps.println("\t\t}"); ps.println("\t\treturn _type;"); ps.println("\t}" + Environment.NL); printIdMethod(ps); // inherited from IdlSymbol /* read */ ps.println("\tpublic static " + type + " read (final org.omg.CORBA.portable.InputStream _in)"); ps.println("\t{"); ps.println("\t\t" + type + " _result;"); ps.println("\t\t" + originalType.printReadStatement("_result", "_in")); ps.println("\t\treturn _result;"); ps.println("\t}" + Environment.NL); /* write */ ps.println("\tpublic static void write (final org.omg.CORBA.portable.OutputStream _out, " + type + " _s)"); ps.println("\t{"); ps.println("\t\t" + originalType.printWriteStatement("_s", "_out")); ps.println("\t}"); ps.println("}"); } public void printInsertIntoAny(PrintWriter ps, String anyname, String varname) { String helpername = className() + "Helper"; ps.println("\t\t" + pack_name + "." + helpername + ".insert(" + anyname + ", " + varname + " );"); } public void printExtractResult(PrintWriter ps, String resultname, String anyname, String resulttype) { String helpername = className() + "Helper"; ps.println("\t\t" + resultname + " = " + pack_name + "." + helpername + ".extract(" + anyname + ");"); } public void accept(IDLTreeVisitor visitor) { visitor.visitAlias(this); } }