blob: 37070482c5d9aca74ca36403b8ed48354ebad063 [file] [log] [blame]
/*
* Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* COMPONENT_NAME: idl.toJava
*
* ORIGINS: 27
*
* Licensed Materials - Property of IBM
* 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
* RMI-IIOP v1.0
*
*/
package com.sun.tools.corba.se.idl.toJavaPortable;
// NOTES:
// -F46082.51<daz> Remove -stateful feature; javaStatefulName() obsolete.
// -D57147 <klr> Make _Tie implement org.omg.CORBA.portable.InvokeHandler
// -D58037 <klr> Make _Tie delegate to Operations interface
// -D62739 <klr> no TIE for values that support abstract interfaces, etc.
import java.io.File;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import com.sun.tools.corba.se.idl.AttributeEntry;
import com.sun.tools.corba.se.idl.GenFileStream;
import com.sun.tools.corba.se.idl.InterfaceEntry;
import com.sun.tools.corba.se.idl.InterfaceState;
import com.sun.tools.corba.se.idl.MethodEntry;
import com.sun.tools.corba.se.idl.SymtabEntry;
import com.sun.tools.corba.se.idl.TypedefEntry;
import com.sun.tools.corba.se.idl.ValueEntry;
/**
*
**/
public class Skeleton implements AuxGen
{
private NameModifier skeletonNameModifier ;
private NameModifier tieNameModifier ;
public Skeleton ()
{
}
public void generate (Hashtable symbolTable, SymtabEntry entry)
{
// <d62739-begin>
// Per Simon, 5-12-99, don't generate TIE or Skeleton for
//
// 1) valuetypes supporting abstract interfaces
// 2) valuetypes with no supports.
// 3) abstract interfaces
//
if (entry instanceof ValueEntry)
{
ValueEntry v = (ValueEntry) entry;
if ((v.supports ().size () == 0) ||
((InterfaceEntry) v.supports ().elementAt (0)).isAbstract ()) {
return;
}
}
if (((InterfaceEntry) entry).isAbstract ()) {
return;
}
// <d62739-end>
this.symbolTable = symbolTable;
this.i = (InterfaceEntry)entry;
init ();
openStream ();
if (stream == null)
return;
writeHeading ();
writeBody ();
writeClosing ();
closeStream ();
} // generate
/**
* Initialize members unique to this generator.
**/
protected void init ()
{
tie = ((Arguments)Compile.compiler.arguments).TIEServer ;
poa = ((Arguments)Compile.compiler.arguments).POAServer ;
skeletonNameModifier =
((Arguments)Compile.compiler.arguments).skeletonNameModifier ;
tieNameModifier =
((Arguments)Compile.compiler.arguments).tieNameModifier ;
tieClassName = tieNameModifier.makeName( i.name() ) ;
skeletonClassName = skeletonNameModifier.makeName( i.name() ) ;
intfName = Util.javaName (i);
// for valuetype, get the name of the interface the valuetype supports
if (i instanceof ValueEntry)
{
ValueEntry v = (ValueEntry) i;
InterfaceEntry intf = (InterfaceEntry) v.supports ().elementAt (0);
intfName = Util.javaName (intf);
}
} // init
protected void openStream ()
{
if (tie)
stream = Util.stream( i, tieNameModifier, ".java" ) ;
else
stream = Util.stream( i, skeletonNameModifier, ".java" ) ;
} // openStream
protected void writeHeading ()
{
Util.writePackage (stream, i, Util.StubFile);
Util.writeProlog (stream, ((GenFileStream)stream).name ());
if (i.comment () != null)
i.comment ().generate ("", stream);
writeClassDeclaration ();
stream.println ('{');
stream.println ();
} // writeHeading
protected void writeClassDeclaration ()
{
if (tie){
stream.println ("public class " + tieClassName +
" extends " + skeletonClassName ) ;
} else {
if (poa) {
stream.println ("public abstract class " + skeletonClassName +
" extends org.omg.PortableServer.Servant");
stream.print (" implements " + intfName + "Operations, ");
stream.println ("org.omg.CORBA.portable.InvokeHandler");
} else {
stream.println ("public abstract class " + skeletonClassName +
" extends org.omg.CORBA.portable.ObjectImpl");
stream.print (" implements " + intfName + ", ");
stream.println ("org.omg.CORBA.portable.InvokeHandler");
}
}
} // writeClassDeclaration
/**
*
**/
protected void writeBody ()
{
// <f46082.51> Remove -stateful feature. ?????
//if (i.state () != null)
// writeState ();
writeCtors ();
if (i instanceof ValueEntry)
{
// use the interface the valuetype supports to generate the
// tie class instead of using the valuetype itself
ValueEntry v = (ValueEntry) i;
this.i = (InterfaceEntry) v.supports ().elementAt (0);
}
buildMethodList ();
//DispatchMethod and MethodTable
if (tie){ //Concrete class implementing the remote interface
//The logic is here for future use
if (poa) {
writeMethods ();
stream.println (" private " + intfName + "Operations _impl;");
stream.println (" private org.omg.PortableServer.POA _poa;");
} else {
writeMethods ();
stream.println (" private " + intfName + "Operations _impl;");
}
} else { //Both POA and ImplBase are abstract InvokeHandler
//The logic is here for future use
if (poa) {
writeMethodTable ();
writeDispatchMethod ();
writeCORBAOperations ();
} else {
writeMethodTable ();
writeDispatchMethod ();
writeCORBAOperations ();
}
}
//legacy !!
writeOperations ();
} // writeBody
/**
* Close the skeleton class. The singleton ORB member is
* necessary only for portable skeletons.
**/
protected void writeClosing ()
{
stream.println ();
if (tie){
stream.println ("} // class " + tieClassName);
} else {
stream.println ("} // class " + skeletonClassName);
}
} // writeClosing
/**
* Close the print stream, which flushes the stream to file.
**/
protected void closeStream ()
{
stream.close ();
} // closeStream
protected void writeCtors ()
{
stream.println (" // Constructors");
// Empty argument constructors
if (!poa) {
if (tie){
stream.println (" public " + tieClassName + " ()");
stream.println (" {");
stream.println (" }");
} else {
stream.println (" public " + skeletonClassName + " ()");
stream.println (" {");
stream.println (" }");
}
}
stream.println ();
// Argumented constructors
if (tie){
if (poa) {
//Write constructors
writePOATieCtors();
//Write state setters and getters
writePOATieFieldAccessMethods();
} else {
stream.println (" public " + tieClassName +
" (" + intfName + "Operations impl)");
stream.println (" {");
// Does it derive from a interface having state, e.g., valuetype?
if (((InterfaceEntry)i.derivedFrom ().firstElement ()).state () != null)
stream.println (" super (impl);");
else
stream.println (" super ();");
stream.println (" _impl = impl;");
stream.println (" }");
stream.println ();
}
} else { //Skeleton is not Tie so it has no constructors.
if (poa) {
} else {
}
}
} // writeCtors
private void writePOATieCtors(){
//First constructor
stream.println (" public " + tieClassName + " ( " + intfName + "Operations delegate ) {");
stream.println (" this._impl = delegate;");
stream.println (" }");
//Second constructor specifying default poa.
stream.println (" public " + tieClassName + " ( " + intfName +
"Operations delegate , org.omg.PortableServer.POA poa ) {");
stream.println (" this._impl = delegate;");
stream.println (" this._poa = poa;");
stream.println (" }");
}
private void writePOATieFieldAccessMethods(){
//Getting delegate
stream.println (" public " + intfName+ "Operations _delegate() {");
stream.println (" return this._impl;");
stream.println (" }");
//Setting delegate
stream.println (" public void _delegate (" + intfName + "Operations delegate ) {");
stream.println (" this._impl = delegate;");
stream.println (" }");
//Overriding default poa
stream.println (" public org.omg.PortableServer.POA _default_POA() {");
stream.println (" if(_poa != null) {");
stream.println (" return _poa;");
stream.println (" }");
stream.println (" else {");
stream.println (" return super._default_POA();");
stream.println (" }");
stream.println (" }");
}
/**
* Build a list of all of the methods, keeping out duplicates.
**/
protected void buildMethodList ()
{
// Start from scratch
methodList = new Vector ();
buildMethodList (i);
} // buildMethodList
/**
*
**/
private void buildMethodList (InterfaceEntry entry)
{
// Add the local methods
Enumeration locals = entry.methods ().elements ();
while (locals.hasMoreElements ())
addMethod ((MethodEntry)locals.nextElement ());
// Add the inherited methods
Enumeration parents = entry.derivedFrom ().elements ();
while (parents.hasMoreElements ())
{
InterfaceEntry parent = (InterfaceEntry)parents.nextElement ();
if (!parent.name ().equals ("Object"))
buildMethodList (parent);
}
} // buildMethodList
/**
*
**/
private void addMethod (MethodEntry method)
{
if (!methodList.contains (method))
methodList.addElement (method);
} // addMethod
/**
*
**/
protected void writeDispatchMethod ()
{
String indent = " ";
stream.println (" public org.omg.CORBA.portable.OutputStream _invoke (String $method,");
stream.println (indent + "org.omg.CORBA.portable.InputStream in,");
stream.println (indent + "org.omg.CORBA.portable.ResponseHandler $rh)");
stream.println (" {");
// this is a special case code generation for cases servantLocator and
// servantActivator, where OMG is taking too long to define them
// as local objects
boolean isLocalInterface = false;
if (i instanceof InterfaceEntry) {
isLocalInterface = i.isLocalServant();
}
if (!isLocalInterface) {
// Per Simon 8/26/98, create and return reply stream for all methods - KLR
stream.println (" org.omg.CORBA.portable.OutputStream out = null;");
stream.println (" java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);");
stream.println (" if (__method == null)");
stream.println (" throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);");
stream.println ();
if (methodList.size () > 0)
{
stream.println (" switch (__method.intValue ())");
stream.println (" {");
// Write the method case statements
int realI = 0;
for (int i = 0; i < methodList.size (); ++i)
{
MethodEntry method = (MethodEntry)methodList.elementAt (i);
((MethodGen)method.generator ()).dispatchSkeleton (symbolTable, method, stream, realI);
if (method instanceof AttributeEntry && !((AttributeEntry)method).readOnly ())
realI += 2;
else
++realI;
}
indent = " ";
stream.println (indent + "default:");
stream.println (indent + " throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);");
stream.println (" }");
stream.println ();
}
stream.println (" return out;");
} else {
stream.println(" throw new org.omg.CORBA.BAD_OPERATION();");
}
stream.println (" } // _invoke");
stream.println ();
} // writeDispatchMethod
/**
*
**/
protected void writeMethodTable ()
{
// Write the methods hashtable
stream.println (" private static java.util.Hashtable _methods = new java.util.Hashtable ();");
stream.println (" static");
stream.println (" {");
int count = -1;
Enumeration e = methodList.elements ();
while (e.hasMoreElements ())
{
MethodEntry method = (MethodEntry)e.nextElement ();
if (method instanceof AttributeEntry)
{
stream.println (" _methods.put (\"_get_" + Util.stripLeadingUnderscores (method.name ()) + "\", new java.lang.Integer (" + (++count) + "));");
if (!((AttributeEntry)method).readOnly ())
stream.println (" _methods.put (\"_set_" + Util.stripLeadingUnderscores (method.name ()) + "\", new java.lang.Integer (" + (++count) + "));");
}
else
stream.println (" _methods.put (\"" + Util.stripLeadingUnderscores (method.name ()) + "\", new java.lang.Integer (" + (++count) + "));");
}
stream.println (" }");
stream.println ();
} // writeMethodTable
/**
*
**/
protected void writeMethods ()
{
int realI = 0;
for (int i = 0; i < methodList.size (); ++i)
{
MethodEntry method = (MethodEntry)methodList.elementAt (i);
((MethodGen)method.generator ()).skeleton
(symbolTable, method, stream, realI);
if (method instanceof AttributeEntry &&
!((AttributeEntry)method).readOnly ())
realI += 2;
else
++realI;
stream.println ();
}
} // writeMethods
/**
*
**/
private void writeIDs ()
{
Vector list = new Vector ();
buildIDList (i, list);
Enumeration e = list.elements ();
boolean first = true;
while (e.hasMoreElements ())
{
if (first)
first = false;
else
stream.println (", ");
stream.print (" \"" + (String)e.nextElement () + '"');
}
} // writeIDs
/**
*
**/
private void buildIDList (InterfaceEntry entry, Vector list)
{
if (!entry.fullName ().equals ("org/omg/CORBA/Object"))
{
String id = Util.stripLeadingUnderscoresFromID (entry.repositoryID ().ID ());
if (!list.contains (id))
list.addElement (id);
Enumeration e = entry.derivedFrom ().elements ();
while (e.hasMoreElements ())
buildIDList ((InterfaceEntry)e.nextElement (), list);
}
} // buildIDList
/**
*
**/
protected void writeCORBAOperations ()
{
stream.println (" // Type-specific CORBA::Object operations");
stream.println (" private static String[] __ids = {");
writeIDs ();
stream.println ("};");
stream.println ();
if (poa)
writePOACORBAOperations();
else
writeNonPOACORBAOperations();
} // writeCORBAOperations
protected void writePOACORBAOperations(){
stream.println (" public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId)");
//Right now, with our POA implementation, the same
//implementation of _ids() type methods seem to work for both non-POA
//as well as POA servers. We need to REVISIT since the equivalent
//POA interface, i.e. _all_interfaces, has parameters which are not being
//used in the _ids() implementation.
stream.println (" {");
stream.println (" return (String[])__ids.clone ();");
stream.println (" }");
stream.println ();
//_this()
stream.println (" public "+ i.name() +" _this() ");
stream.println (" {");
stream.println (" return "+ i.name() +"Helper.narrow(" );
stream.println (" super._this_object());");
stream.println (" }");
stream.println ();
//_this(org.omg.CORBA.ORB orb)
stream.println (" public "+ i.name() +" _this(org.omg.CORBA.ORB orb) ");
stream.println (" {");
stream.println (" return "+ i.name() +"Helper.narrow(" );
stream.println (" super._this_object(orb));");
stream.println (" }");
stream.println ();
}
protected void writeNonPOACORBAOperations(){
stream.println (" public String[] _ids ()");
stream.println (" {");
stream.println (" return (String[])__ids.clone ();");
stream.println (" }");
stream.println ();
}
/**
*
**/
protected void writeOperations ()
{
// _get_ids removed at Simon's request 8/26/98 - KLR
} // writeOperations
protected Hashtable symbolTable = null;
protected InterfaceEntry i = null;
protected PrintWriter stream = null;
// Unique to this generator
protected String tieClassName = null;
protected String skeletonClassName = null;
protected boolean tie = false;
protected boolean poa = false;
protected Vector methodList = null;
protected String intfName = "";
} // class Skeleton