OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [gnu/] [classpath/] [tools/] [rmic/] [SourceGiopRmicCompiler.java] - Rev 779

Compare with Previous | Blame | View Log

/* SourceGiopRmicCompiler -- Central GIOP-based RMI stub and tie compiler class.
   Copyright (C) 2006, 2008 Free Software Foundation
 
This file is part of GNU Classpath.
 
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath 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 for more details.
 
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
*/
 
package gnu.classpath.tools.rmic;
 
import gnu.classpath.tools.rmic.AbstractMethodGenerator;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TreeSet;
 
/**
 * Provides the extended rmic functionality to generate the POA - based classes
 * for GIOP (javax.rmi.CORBA package).
 *
 * @author Audrius Meskauskas, Lithuania (audriusa@Bioinformatics.org)
 */
public class SourceGiopRmicCompiler
  extends Generator implements Comparator, RmicBackend
{
  /** The package name. */
  protected String packag;
 
  /**
   * The "basic" name (normally, the interface name, unless several Remote -
   * derived interfaces are implemented.
   */
  protected String name;
 
  /**
   * The name (without package) of the class, passed as the parameter.
   */
  protected String implName;
 
  /**
   * The proposed name for the stub.
   */
  protected String stubName;
 
  /**
   * The Remote's, implemented by this class.
   */
  protected Collection implementedRemotes = new HashSet();
 
  /**
   * The extra classes that must be imported.
   */
  protected Collection extraImports = new HashSet();
 
  /**
   * The methods we must implement.
   */
  protected Collection methods = new HashSet();
 
  /**
   * The map of all code generator variables.
   */
  public Properties vars = new Properties();
 
  /**
   * If this flag is set (true by default), the compiler generates the Servant
   * based classes. If set to false, the compiler generates the old style
   * ObjectImpl based classes.
   */
  protected boolean poaMode = true;
 
  /**
   * If this flag is set (true by default), the compiler emits warnings.
   */
  protected boolean warnings = true;
 
  /**
   * If this flag is set (false by default), the compiler does not
   * write output files.
   */
  protected boolean noWrite = false;
 
  /**
   * If this flag is set (false by default), the compiler keeps source
   * output files.  For SourceGiopRmicCompiler this overrides
   * -nowrite, since -nowrite doesn't apply to sources kept with
   * -keep.
   */
  protected boolean keep = false;
 
  /**
   * Verbose output
   */
  protected boolean verbose = false;
 
  /**
   * Force mode - do not check the exceptions
   */
  protected boolean force = false;
 
  /**
   * The output directory for generated files.
   */
  protected String outputDirectory;
 
  /**
   * The class loader to load the class being compiled.
   */
  ClassLoader classLoader;
 
  /**
   * Clear data, preparing for the next compilation.
   */
  public synchronized void reset()
  {
    packag = name = implName = stubName = null;
    implementedRemotes.clear();
    extraImports.clear();
    methods.clear();
    vars.clear();
  }
 
  /**
   * Set the class path (handle the -classpath key)
   *
   * @param classPath the class path to set.
   */
  public void setClassPath(String classPath)
  {
    classLoader = Thread.currentThread().getContextClassLoader();
    StringTokenizer tok = new StringTokenizer(classPath, File.pathSeparator,
                                              true);
    ArrayList urls = new ArrayList(tok.countTokens());
    String s = null;
    try
      {
        while (tok.hasMoreTokens())
          {
            s = tok.nextToken();
            if (s.equals(File.pathSeparator))
              urls.add(new File(".").toURL());
            else
              {
                urls.add(new File(s).toURL());
                if (tok.hasMoreTokens())
                  {
                    // Skip the separator.
                    tok.nextToken();
                    // If the classpath ended with a separator,
                    // append the current directory.
                    if (! tok.hasMoreTokens())
                      urls.add(new File(".").toURL());
                  }
              }
          }
      }
    catch (MalformedURLException ex)
      {
        System.err.println("Malformed path '" + s + "' in classpath '"
                           + classPath + "'");
        System.exit(1);
      }
    URL[] u = new URL[urls.size()];
    for (int i = 0; i < u.length; i++)
      {
        u[i] = (URL) urls.get(i);
      }
 
    classLoader = new URLClassLoader(u, classLoader);
  }
 
  /**
   * Loads the class with the given name (uses class path, if applicable)
   *
   * @param name the name of the class.
   */
  public Class loadClass(String name)
  {
    ClassLoader loader = classLoader;
    if (loader == null)
      loader = Thread.currentThread().getContextClassLoader();
    try
      {
        return loader.loadClass(name);
      }
    catch (ClassNotFoundException e)
      {
        System.err.println(name+" not found on "+loader);
        System.exit(1);
        // Unreacheable code.
        return null;
      }
  }
 
  /**
   * Compile the given class (the instance of Remote), generating the stub and
   * tie for it.
   *
   * @param remote
   *          the class to compile.
   */
  public synchronized void compile(Class remote)
  {
    reset();
    String s;
 
    // Get the package.
    s = remote.getName();
    int p = s.lastIndexOf('.');
    if (p < 0)
      {
        // Root package.
        packag = "";
        implName = name = s;
      }
    else
      {
        packag = s.substring(0, p);
        implName = name = s.substring(p + 1);
      }
 
    name = convertStubName(name);
 
    stubName = name;
 
    vars.put("#name", name);
    vars.put("#package", packag);
    vars.put("#implName", implName);
 
    if (verbose)
      System.out.println("Package " + packag + ", name " + name + " impl "
                         + implName);
 
    // Get the implemented remotes.
    Class[] interfaces = remote.getInterfaces();
 
    for (int i = 0; i < interfaces.length; i++)
      {
        if (Remote.class.isAssignableFrom(interfaces[i]))
          {
            if (! interfaces[i].equals(Remote.class))
              {
                implementedRemotes.add(interfaces[i]);
              }
          }
      }
 
    vars.put("#idList", getIdList(implementedRemotes));
 
    // Collect and process methods.
    Iterator iter = implementedRemotes.iterator();
 
    while (iter.hasNext())
      {
        Class c = (Class) iter.next();
        Method[] m = c.getMethods();
 
        // Check if throws RemoteException.
        for (int i = 0; i < m.length; i++)
          {
            Class[] exc = m[i].getExceptionTypes();
            boolean remEx = false;
 
            for (int j = 0; j < exc.length; j++)
              {
                if (exc[j].isAssignableFrom(RemoteException.class))
                  {
                    remEx = true;
                    break;
                  }
              }
            if (! remEx && !force)
              throw new CompilationError(m[i].getName() + ", defined in "
                                         + c.getName()
                                         + ", does not throw "
                                         + RemoteException.class.getName());
            AbstractMethodGenerator mm = createMethodGenerator(m[i]);
            methods.add(mm);
          }
      }
  }
 
  /**
   * Create the method generator for the given method.
   *
   * @param m the method
   *
   * @return the created method generator
   */
  protected AbstractMethodGenerator createMethodGenerator(Method m)
  {
    return new MethodGenerator(m, this);
  }
 
  /**
   * Get the name of the given class. The class is added to imports, if not
   * already present and not from java.lang and not from the current package.
   *
   * @param nameIt
   *          the class to name
   * @return the name of class as it should appear in java language
   */
  public synchronized String name(Class nameIt)
  {
    if (nameIt.isArray())
      {
        // Mesure dimensions:
        int dimension = 0;
        Class finalComponent = nameIt;
        while (finalComponent.isArray())
          {
            finalComponent = finalComponent.getComponentType();
            dimension++;
          }
 
        StringBuilder brackets = new StringBuilder();
 
        for (int i = 0; i < dimension; i++)
          {
            brackets.append("[]");
          }
 
        return name(finalComponent) + " " + brackets;
      }
    else
      {
        String n = nameIt.getName();
        if (! nameIt.isArray() && ! nameIt.isPrimitive())
          if (! n.startsWith("java.lang")
              && ! (packag != null && n.startsWith(packag)))
            extraImports.add(n);
 
        int p = n.lastIndexOf('.');
        if (p < 0)
          return n;
        else
          return n.substring(p + 1);
      }
  }
 
  /**
   * Get the RMI-style repository Id for the given class.
   *
   * @param c
   *          the interface, for that the repository Id must be created.
   * @return the repository id
   */
  public String getId(Class c)
  {
    return "RMI:" + c.getName() + ":0000000000000000";
  }
 
  /**
   * Get repository Id string array declaration.
   *
   * @param remotes
   *          the collection of interfaces
   * @return the fully formatted string array.
   */
  public String getIdList(Collection remotes)
  {
    StringBuilder b = new StringBuilder();
 
    // Keep the Ids sorted, ensuring, that the same order will be preserved
    // between compilations.
    TreeSet sortedIds = new TreeSet();
 
    Iterator iter = remotes.iterator();
    while (iter.hasNext())
      {
        sortedIds.add(getId((Class) iter.next()));
      }
 
    iter = sortedIds.iterator();
    while (iter.hasNext())
      {
        b.append("      \"" + iter.next() + "\"");
        if (iter.hasNext())
          b.append(", \n");
      }
    return b.toString();
  }
 
  /**
   * Generate stub. Can only be called from {@link #compile}.
   *
   * @return the string, containing the text of the generated stub.
   */
  public String generateStub()
  {
    String template = getResource("Stub.jav");
 
    // Generate methods.
    StringBuilder b = new StringBuilder();
    Iterator iter = methods.iterator();
    while (iter.hasNext())
      {
        AbstractMethodGenerator m = (AbstractMethodGenerator) iter.next();
        b.append(m.generateStubMethod());
      }
 
    vars.put("#stub_methods", b.toString());
    vars.put("#imports", getImportStatements());
    vars.put("#interfaces", getAllInterfaces());
 
    String output = replaceAll(template, vars);
    return output;
  }
 
  /**
   * Get the list of all interfaces, implemented by the class, that are
   * derived from Remote.
   *
   * @return the string - all interfaces.
   */
  public String getAllInterfaces()
  {
    StringBuilder b = new StringBuilder();
    Iterator iter = implementedRemotes.iterator();
 
    while (iter.hasNext())
      {
        b.append(name((Class) iter.next()));
        if (iter.hasNext())
          b.append(", ");
      }
 
    return b.toString();
  }
 
  /**
   * Generate Tie. Can only be called from {@link #compile}.
   *
   * @return the string, containing the text of the generated Tie.
   */
  public String generateTie()
  {
    String template;
    if (poaMode)
      template = getResource("Tie.jav");
    else
      template = getResource("ImplTie.jav");
 
    // Generate methods.
    HashFinder hashFinder = new HashFinder();
 
    // Find the hash character position:
    Iterator iter = methods.iterator();
    String[] names = new String[methods.size()];
    int p = 0;
 
    for (int i = 0; i < names.length; i++)
      names[i] = ((MethodGenerator) iter.next()).getGiopMethodName();
 
    int hashCharPosition = hashFinder.findHashCharPosition(names);
 
    iter = methods.iterator();
    while (iter.hasNext())
      ((MethodGenerator) iter.next()).hashCharPosition = hashCharPosition;
 
    vars.put("#hashCharPos", Integer.toString(hashCharPosition));
 
    ArrayList sortedMethods = new ArrayList(methods);
    Collections.sort(sortedMethods, this);
 
    iter = sortedMethods.iterator();
 
    StringBuilder b = new StringBuilder();
 
    MethodGenerator prev = null;
 
    while (iter.hasNext())
      {
        MethodGenerator m = (MethodGenerator) iter.next();
        m.previous = prev;
        m.hashCharPosition = hashCharPosition;
        prev = m;
        b.append(m.generateTieMethod());
      }
 
    vars.put("#tie_methods", b.toString());
 
    vars.put("#imports", getImportStatements());
 
    String output = replaceAll(template, vars);
    return output;
  }
 
  public int compare(Object a, Object b)
  {
    MethodGenerator g1 = (MethodGenerator) a;
    MethodGenerator g2 = (MethodGenerator) b;
 
    return g1.getHashChar() - g2.getHashChar();
  }
 
  /**
   * Import the extra classes, used as the method parameters and return values.
   *
   * @return the additional import block.
   */
  protected String getImportStatements()
  {
    TreeSet imp = new TreeSet();
 
    Iterator it = extraImports.iterator();
    while (it.hasNext())
      {
        String ic = it.next().toString();
        imp.add("import " + ic + ";\n");
      }
 
    StringBuilder b = new StringBuilder();
    it = imp.iterator();
 
    while (it.hasNext())
      {
        b.append(it.next());
      }
    return b.toString();
  }
 
  /**
   * If this flag is set (true by default), the compiler generates the Servant
   * based classes. If set to false, the compiler generates the old style
   * ObjectImpl based classes.
   */
  public void setPoaMode(boolean mode)
  {
    poaMode = mode;
  }
 
  /**
   * Set the verbose output mode (false by default)
   *
   * @param isVerbose the verbose output mode
   */
  public void setVerbose(boolean isVerbose)
  {
    verbose = isVerbose;
  }
 
  /**
   * If this flag is set (true by default), the compiler emits warnings.
   */
  public void setWarnings(boolean warn)
  {
    warnings = warn;
  }
 
  /**
   * Set the error ignore mode.
   */
  public void setForce(boolean isforce)
  {
    force = isforce;
  }
 
  /**
   * Get the package name.
   */
  public String getPackageName()
  {
    return packag;
  }
 
  /**
   * Get the proposed stub name
   */
  public String getStubName()
  {
    return stubName;
  }
 
  /**
   * Additional processing of the stub name.
   */
  public String convertStubName(String name)
  {
    // Drop the Impl suffix, if one exists.
    if (name.endsWith("Impl"))
      return name.substring(0, name.length() - "Impl".length());
    else
      return name;
  }
 
  /**
   * Assumes that output directory is already created.
   */
  protected boolean outputTie(File fw, Class c)
  {
    try
      {
        String tie = generateTie();
        String tieName = "_" + name(c) + "_Tie.java";
 
        OutputStream out = new FileOutputStream(new File(fw, tieName));
        out.write(tie.getBytes());
        out.close();
      }
    catch (IOException ioex)
      {
        System.err.println("Output path not accessible");
        ioex.printStackTrace();
        return false;
      }
    return true;
  }
 
  public void setup(boolean keep, boolean need11Stubs, boolean need12Stubs,
                    boolean iiop, boolean poa, boolean debug, boolean warnings,
                    boolean noWrite, boolean verbose, boolean force, String classpath,
                    String bootclasspath, String extdirs, String outputDirectory)
  {
    setWarnings(warnings);
    setVerbose(verbose);
    setForce(force);
    setClassPath(classpath);
    setPoaMode(poa);
    this.outputDirectory = outputDirectory;
    this.noWrite = noWrite;
    this.keep = keep;
  }
 
  public boolean run(String[] inputFiles)
  {
    for (int i = 0; i < inputFiles.length; i++)
      {
        reset();
        Class c = loadClass(inputFiles[i]);
 
        compile(c);
        String packag = getPackageName().replace('.', '/');
        File fw = new File(outputDirectory, packag);
 
        // Generate stub.
        String stub = generateStub();
        String subName = getStubName() + "_Stub.java";
 
        // -keep overrides -nowrite for sources.
        if (!noWrite || keep)
          {
            try
              {
                fw.mkdirs();
                OutputStream out = new FileOutputStream(new File(fw,
                                                                 subName));
                out.write(stub.getBytes());
                out.close();
 
                // Generate tie
                if (!outputTie(fw, c))
                  return false;
              }
            catch (IOException ioex)
              {
                System.err.println("Output path not accessible");
                ioex.printStackTrace();
                return false;
              }
          }
      }
    return true;
  }
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.