feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,445 @@
/*
* Copyright (c) 1996, 2012, 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.
*/
/*****************************************************************************/
/* Copyright (c) IBM Corporation 1998 */
/* */
/* (C) Copyright IBM Corp. 1998 */
/* */
/*****************************************************************************/
package sun.rmi.rmic;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import sun.tools.java.ClassPath;
/**
* BatchEnvironment for rmic extends javac's version in four ways:
* 1. It overrides errorString() to handle looking for rmic-specific
* error messages in rmic's resource bundle
* 2. It provides a mechanism for recording intermediate generated
* files so that they can be deleted later.
* 3. It holds a reference to the Main instance so that generators
* can refer to it.
* 4. It provides access to the ClassPath passed to the constructor.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public class BatchEnvironment extends sun.tools.javac.BatchEnvironment {
/** instance of Main which created this environment */
private Main main;
/**
* Create a ClassPath object for rmic from a class path string.
*/
public static ClassPath createClassPath(String classPathString) {
ClassPath[] paths = classPaths(null, classPathString, null, null);
return paths[1];
}
/**
* Create a ClassPath object for rmic from the relevant command line
* options for class path, boot class path, and extension directories.
*/
public static ClassPath createClassPath(String classPathString,
String sysClassPathString,
String extDirsString)
{
/**
* Previously, this method delegated to the
* sun.tools.javac.BatchEnvironment.classPaths method in order
* to supply default values for paths not specified on the
* command line, expand extensions directories into specific
* JAR files, and construct the ClassPath object-- but as part
* of the fix for 6473331, which adds support for Class-Path
* manifest entries in JAR files, those steps are now handled
* here directly, with the help of a Path utility class copied
* from the new javac implementation (see below).
*/
Path path = new Path();
if (sysClassPathString == null) {
sysClassPathString = System.getProperty("sun.boot.class.path");
}
if (sysClassPathString != null) {
path.addFiles(sysClassPathString);
}
/*
* Class-Path manifest entries are supported for JAR files
* everywhere except in the boot class path.
*/
path.expandJarClassPaths(true);
if (extDirsString == null) {
extDirsString = System.getProperty("java.ext.dirs");
}
if (extDirsString != null) {
path.addDirectories(extDirsString);
}
/*
* In the application class path, an empty element means
* the current working directory.
*/
path.emptyPathDefault(".");
if (classPathString == null) {
// The env.class.path property is the user's CLASSPATH
// environment variable, and it set by the wrapper (ie,
// javac.exe).
classPathString = System.getProperty("env.class.path");
if (classPathString == null) {
classPathString = ".";
}
}
path.addFiles(classPathString);
return new ClassPath(path.toArray(new String[path.size()]));
}
/**
* Create a BatchEnvironment for rmic with the given class path,
* stream for messages and Main.
*/
public BatchEnvironment(OutputStream out, ClassPath path, Main main) {
super(out, new ClassPath(""), path);
// use empty "sourcePath" (see 4666958)
this.main = main;
}
/**
* Get the instance of Main which created this environment.
*/
public Main getMain() {
return main;
}
/**
* Get the ClassPath.
*/
public ClassPath getClassPath() {
return binaryPath;
}
/** list of generated source files created in this environment */
private Vector<File> generatedFiles = new Vector<>();
/**
* Remember a generated source file generated so that it
* can be removed later, if appropriate.
*/
public void addGeneratedFile(File file) {
generatedFiles.addElement(file);
}
/**
* Delete all the generated source files made during the execution
* of this environment (those that have been registered with the
* "addGeneratedFile" method).
*/
public void deleteGeneratedFiles() {
synchronized(generatedFiles) {
Enumeration<File> enumeration = generatedFiles.elements();
while (enumeration.hasMoreElements()) {
File file = enumeration.nextElement();
file.delete();
}
generatedFiles.removeAllElements();
}
}
/**
* Release resources, if any.
*/
public void shutdown() {
main = null;
generatedFiles = null;
super.shutdown();
}
/**
* Return the formatted, localized string for a named error message
* and supplied arguments. For rmic error messages, with names that
* being with "rmic.", look up the error message in rmic's resource
* bundle; otherwise, defer to java's superclass method.
*/
public String errorString(String err,
Object arg0, Object arg1, Object arg2)
{
if (err.startsWith("rmic.") || err.startsWith("warn.rmic.")) {
String result = Main.getText(err,
(arg0 != null ? arg0.toString() : null),
(arg1 != null ? arg1.toString() : null),
(arg2 != null ? arg2.toString() : null));
if (err.startsWith("warn.")) {
result = "warning: " + result;
}
return result;
} else {
return super.errorString(err, arg0, arg1, arg2);
}
}
public void reset() {
}
/**
* Utility for building paths of directories and JAR files. This
* class was copied from com.sun.tools.javac.util.Paths as part of
* the fix for 6473331, which adds support for Class-Path manifest
* entries in JAR files. Diagnostic code is simply commented out
* because rmic silently ignored these conditions historically.
*/
private static class Path extends LinkedHashSet<String> {
private static final long serialVersionUID = 0;
private static final boolean warn = false;
private static class PathIterator implements Collection<String> {
private int pos = 0;
private final String path;
private final String emptyPathDefault;
public PathIterator(String path, String emptyPathDefault) {
this.path = path;
this.emptyPathDefault = emptyPathDefault;
}
public PathIterator(String path) { this(path, null); }
public Iterator<String> iterator() {
return new Iterator<String>() {
public boolean hasNext() {
return pos <= path.length();
}
public String next() {
int beg = pos;
int end = path.indexOf(File.pathSeparator, beg);
if (end == -1)
end = path.length();
pos = end + 1;
if (beg == end && emptyPathDefault != null)
return emptyPathDefault;
else
return path.substring(beg, end);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
// required for Collection.
public int size() {
throw new UnsupportedOperationException();
}
public boolean isEmpty() {
throw new UnsupportedOperationException();
}
public boolean contains(Object o) {
throw new UnsupportedOperationException();
}
public Object[] toArray() {
throw new UnsupportedOperationException();
}
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
public boolean add(String o) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection<? extends String> c) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean equals(Object o) {
throw new UnsupportedOperationException();
}
public int hashCode() {
throw new UnsupportedOperationException();
}
}
/** Is this the name of a zip file? */
private static boolean isZip(String name) {
return new File(name).isFile();
}
private boolean expandJarClassPaths = false;
public Path expandJarClassPaths(boolean x) {
expandJarClassPaths = x;
return this;
}
/** What to use when path element is the empty string */
private String emptyPathDefault = null;
public Path emptyPathDefault(String x) {
emptyPathDefault = x;
return this;
}
public Path() { super(); }
public Path addDirectories(String dirs, boolean warn) {
if (dirs != null)
for (String dir : new PathIterator(dirs))
addDirectory(dir, warn);
return this;
}
public Path addDirectories(String dirs) {
return addDirectories(dirs, warn);
}
private void addDirectory(String dir, boolean warn) {
if (! new File(dir).isDirectory()) {
// if (warn)
// log.warning(Position.NOPOS,
// "dir.path.element.not.found", dir);
return;
}
for (String direntry : new File(dir).list()) {
String canonicalized = direntry.toLowerCase();
if (canonicalized.endsWith(".jar") ||
canonicalized.endsWith(".zip"))
addFile(dir + File.separator + direntry, warn);
}
}
public Path addFiles(String files, boolean warn) {
if (files != null)
for (String file : new PathIterator(files, emptyPathDefault))
addFile(file, warn);
return this;
}
public Path addFiles(String files) {
return addFiles(files, warn);
}
private void addFile(String file, boolean warn) {
if (contains(file)) {
/* Discard duplicates and avoid infinite recursion */
return;
}
File ele = new File(file);
if (! ele.exists()) {
/* No such file or directory exist */
if (warn)
// log.warning(Position.NOPOS,
// "path.element.not.found", file);
return;
}
if (ele.isFile()) {
/* File is an ordinay file */
String arcname = file.toLowerCase();
if (! (arcname.endsWith(".zip") ||
arcname.endsWith(".jar"))) {
/* File name don't have right extension */
// if (warn)
// log.warning(Position.NOPOS,
// "invalid.archive.file", file);
return;
}
}
/* Now what we have left is either a directory or a file name
confirming to archive naming convention */
super.add(file);
if (expandJarClassPaths && isZip(file))
addJarClassPath(file, warn);
}
// Adds referenced classpath elements from a jar's Class-Path
// Manifest entry. In some future release, we may want to
// update this code to recognize URLs rather than simple
// filenames, but if we do, we should redo all path-related code.
private void addJarClassPath(String jarFileName, boolean warn) {
try {
String jarParent = new File(jarFileName).getParent();
JarFile jar = new JarFile(jarFileName);
try {
Manifest man = jar.getManifest();
if (man == null) return;
Attributes attr = man.getMainAttributes();
if (attr == null) return;
String path = attr.getValue(Attributes.Name.CLASS_PATH);
if (path == null) return;
for (StringTokenizer st = new StringTokenizer(path);
st.hasMoreTokens();) {
String elt = st.nextToken();
if (jarParent != null)
elt = new File(jarParent, elt).getCanonicalPath();
addFile(elt, warn);
}
} finally {
jar.close();
}
} catch (IOException e) {
// log.error(Position.NOPOS,
// "error.reading.file", jarFileName,
// e.getLocalizedMessage());
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1997, 2003, 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.
*/
package sun.rmi.rmic;
import sun.tools.java.Identifier;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public interface Constants extends sun.tools.java.Constants {
/*
* Identifiers potentially useful for all Generators
*/
public static final Identifier idRemote =
Identifier.lookup("java.rmi.Remote");
public static final Identifier idRemoteException =
Identifier.lookup("java.rmi.RemoteException");
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic;
import java.io.File;
import sun.tools.java.ClassDefinition;
/**
* Generator defines the protocol for back-end implementations to be added
* to rmic. See the rmic.properties file for a description of the format for
* adding new Generators to rmic.
* <p>
* Classes implementing this interface must have a public default constructor
* which should set any required arguments to their defaults. When Main
* encounters a command line argument which maps to a specific Generator
* subclass, it will instantiate one and call parseArgs(...). At some later
* point, Main will invoke the generate(...) method once for _each_ class passed
* on the command line.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Bryan Atsatt
*/
public interface Generator {
/**
* Examine and consume command line arguments.
* @param argv The command line arguments. Ignore null
* and unknown arguments. Set each consumed argument to null.
* @param main Report any errors using the main.error() methods.
* @return true if no errors, false otherwise.
*/
public boolean parseArgs(String argv[], Main main);
/**
* Generate output. Any source files created which need compilation should
* be added to the compiler environment using the addGeneratedFile(File)
* method.
*
* @param env The compiler environment
* @param cdef The definition for the implementation class or interface from
* which to generate output
* @param destDir The directory for the root of the package hierarchy
* for generated files. May be null.
*/
public void generate(BatchEnvironment env, ClassDefinition cdef, File destDir);
}

View File

@@ -0,0 +1,299 @@
/*
* Copyright (c) 1997, 2007, 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.
*/
/*****************************************************************************/
/* Copyright (c) IBM Corporation 1998 */
/* */
/* (C) Copyright IBM Corp. 1998 */
/* */
/*****************************************************************************/
package sun.rmi.rmic;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.IOException;
/**
* IndentingWriter is a BufferedWriter subclass that supports automatic
* indentation of lines of text written to the underlying Writer.
*
* Methods are provided for compact, convenient indenting, writing text,
* and writing lines in various combinations.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public class IndentingWriter extends BufferedWriter {
/** true if the next character written is the first on a line */
private boolean beginningOfLine = true;
/** current number of spaces to prepend to lines */
private int currentIndent = 0;
/** number of spaces to change indent when indenting in or out */
private int indentStep = 4;
/** number of spaces to convert into tabs. Use MAX_VALUE to disable */
private int tabSize = 8;
/**
* Create a new IndentingWriter that writes indented text to the
* given Writer. Use the default indent step of four spaces.
*/
public IndentingWriter(Writer out) {
super(out);
}
/**
* Create a new IndentingWriter that writes indented text to the
* given Writer and uses the supplied indent step.
*/
public IndentingWriter(Writer out, int step) {
this(out);
if (indentStep < 0)
throw new IllegalArgumentException("negative indent step");
indentStep = step;
}
/**
* Create a new IndentingWriter that writes indented text to the
* given Writer and uses the supplied indent step and tab size.
*/
public IndentingWriter(Writer out, int step, int tabSize) {
this(out);
if (indentStep < 0)
throw new IllegalArgumentException("negative indent step");
indentStep = step;
this.tabSize = tabSize;
}
/**
* Write a single character.
*/
public void write(int c) throws IOException {
checkWrite();
super.write(c);
}
/**
* Write a portion of an array of characters.
*/
public void write(char[] cbuf, int off, int len) throws IOException {
if (len > 0) {
checkWrite();
}
super.write(cbuf, off, len);
}
/**
* Write a portion of a String.
*/
public void write(String s, int off, int len) throws IOException {
if (len > 0) {
checkWrite();
}
super.write(s, off, len);
}
/**
* Write a line separator. The next character written will be
* preceded by an indent.
*/
public void newLine() throws IOException {
super.newLine();
beginningOfLine = true;
}
/**
* Check if an indent needs to be written before writing the next
* character.
*
* The indent generation is optimized (and made consistent with
* certain coding conventions) by condensing groups of eight spaces
* into tab characters.
*/
protected void checkWrite() throws IOException {
if (beginningOfLine) {
beginningOfLine = false;
int i = currentIndent;
while (i >= tabSize) {
super.write('\t');
i -= tabSize;
}
while (i > 0) {
super.write(' ');
-- i;
}
}
}
/**
* Increase the current indent by the indent step.
*/
protected void indentIn() {
currentIndent += indentStep;
}
/**
* Decrease the current indent by the indent step.
*/
protected void indentOut() {
currentIndent -= indentStep;
if (currentIndent < 0)
currentIndent = 0;
}
/**
* Indent in.
*/
public void pI() {
indentIn();
}
/**
* Indent out.
*/
public void pO() {
indentOut();
}
/**
* Write string.
*/
public void p(String s) throws IOException {
write(s);
}
/**
* End current line.
*/
public void pln() throws IOException {
newLine();
}
/**
* Write string; end current line.
*/
public void pln(String s) throws IOException {
p(s);
pln();
}
/**
* Write string; end current line; indent in.
*/
public void plnI(String s) throws IOException {
p(s);
pln();
pI();
}
/**
* Indent out; write string.
*/
public void pO(String s) throws IOException {
pO();
p(s);
}
/**
* Indent out; write string; end current line.
*/
public void pOln(String s) throws IOException {
pO(s);
pln();
}
/**
* Indent out; write string; end current line; indent in.
*
* This method is useful for generating lines of code that both
* end and begin nested blocks, like "} else {".
*/
public void pOlnI(String s) throws IOException {
pO(s);
pln();
pI();
}
/**
* Write Object.
*/
public void p(Object o) throws IOException {
write(o.toString());
}
/**
* Write Object; end current line.
*/
public void pln(Object o) throws IOException {
p(o.toString());
pln();
}
/**
* Write Object; end current line; indent in.
*/
public void plnI(Object o) throws IOException {
p(o.toString());
pln();
pI();
}
/**
* Indent out; write Object.
*/
public void pO(Object o) throws IOException {
pO();
p(o.toString());
}
/**
* Indent out; write Object; end current line.
*/
public void pOln(Object o) throws IOException {
pO(o.toString());
pln();
}
/**
* Indent out; write Object; end current line; indent in.
*
* This method is useful for generating lines of code that both
* end and begin nested blocks, like "} else {".
*/
public void pOlnI(Object o) throws IOException {
pO(o.toString());
pln();
pI();
}
}

View File

@@ -0,0 +1,897 @@
/*
* Copyright (c) 1996, 2013, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic;
import java.util.Vector;
import java.util.Enumeration;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.MissingResourceException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import sun.tools.java.ClassFile;
import sun.tools.java.ClassDefinition;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.ClassNotFound;
import sun.tools.java.Identifier;
import sun.tools.java.ClassPath;
import sun.tools.javac.SourceClass;
import sun.tools.util.CommandLine;
import java.lang.reflect.Constructor;
import java.util.Properties;
/**
* Main "rmic" program.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public class Main implements sun.rmi.rmic.Constants {
String sourcePathArg;
String sysClassPathArg;
String extDirsArg;
String classPathString;
File destDir;
int flags;
long tm;
Vector<String> classes;
boolean nowrite;
boolean nocompile;
boolean keepGenerated;
boolean status;
String[] generatorArgs;
Vector<Generator> generators;
Class<? extends BatchEnvironment> environmentClass =
BatchEnvironment.class;
boolean iiopGeneration = false;
/**
* Name of the program.
*/
String program;
/**
* The stream where error message are printed.
*/
OutputStream out;
/**
* Constructor.
*/
public Main(OutputStream out, String program) {
this.out = out;
this.program = program;
}
/**
* Output a message.
*/
public void output(String msg) {
PrintStream out =
this.out instanceof PrintStream ? (PrintStream)this.out
: new PrintStream(this.out, true);
out.println(msg);
}
/**
* Top level error message. This method is called when the
* environment could not be set up yet.
*/
public void error(String msg) {
output(getText(msg));
}
public void error(String msg, String arg1) {
output(getText(msg, arg1));
}
public void error(String msg, String arg1, String arg2) {
output(getText(msg, arg1, arg2));
}
/**
* Usage
*/
public void usage() {
error("rmic.usage", program);
}
/**
* Run the compiler
*/
public synchronized boolean compile(String argv[]) {
/*
* Handle internal option to use the new (and incomplete) rmic
* implementation. This option is handled here, rather than
* in parseArgs, so that none of the arguments will be nulled
* before delegating to the new implementation.
*/
for (int i = 0; i < argv.length; i++) {
if (argv[i].equals("-Xnew")) {
return (new sun.rmi.rmic.newrmic.Main(out,
program)).compile(argv);
}
}
if (!parseArgs(argv)) {
return false;
}
if (classes.size() == 0) {
usage();
return false;
}
if ((flags & F_WARNINGS) != 0) {
for (Generator g : generators) {
if (g instanceof RMIGenerator) {
output(getText("rmic.jrmp.stubs.deprecated", program));
break;
}
}
}
return doCompile();
}
/**
* Get the destination directory.
*/
public File getDestinationDir() {
return destDir;
}
/**
* Parse the arguments for compile.
*/
public boolean parseArgs(String argv[]) {
sourcePathArg = null;
sysClassPathArg = null;
extDirsArg = null;
classPathString = null;
destDir = null;
flags = F_WARNINGS;
tm = System.currentTimeMillis();
classes = new Vector<>();
nowrite = false;
nocompile = false;
keepGenerated = false;
generatorArgs = getArray("generator.args",true);
if (generatorArgs == null) {
return false;
}
generators = new Vector<>();
// Pre-process command line for @file arguments
try {
argv = CommandLine.parse(argv);
} catch (FileNotFoundException e) {
error("rmic.cant.read", e.getMessage());
return false;
} catch (IOException e) {
e.printStackTrace(out instanceof PrintStream ?
(PrintStream) out :
new PrintStream(out, true));
return false;
}
// Parse arguments
for (int i = 0 ; i < argv.length ; i++) {
if (argv[i] != null) {
if (argv[i].equals("-g")) {
flags &= ~F_OPT;
flags |= F_DEBUG_LINES | F_DEBUG_VARS;
argv[i] = null;
} else if (argv[i].equals("-O")) {
flags &= ~F_DEBUG_LINES;
flags &= ~F_DEBUG_VARS;
flags |= F_OPT | F_DEPENDENCIES;
argv[i] = null;
} else if (argv[i].equals("-nowarn")) {
flags &= ~F_WARNINGS;
argv[i] = null;
} else if (argv[i].equals("-debug")) {
flags |= F_DUMP;
argv[i] = null;
} else if (argv[i].equals("-depend")) {
flags |= F_DEPENDENCIES;
argv[i] = null;
} else if (argv[i].equals("-verbose")) {
flags |= F_VERBOSE;
argv[i] = null;
} else if (argv[i].equals("-nowrite")) {
nowrite = true;
argv[i] = null;
} else if (argv[i].equals("-Xnocompile")) {
nocompile = true;
keepGenerated = true;
argv[i] = null;
} else if (argv[i].equals("-keep") ||
argv[i].equals("-keepgenerated")) {
keepGenerated = true;
argv[i] = null;
} else if (argv[i].equals("-show")) {
error("rmic.option.unsupported", "-show");
usage();
return false;
} else if (argv[i].equals("-classpath")) {
if ((i + 1) < argv.length) {
if (classPathString != null) {
error("rmic.option.already.seen", "-classpath");
usage();
return false;
}
argv[i] = null;
classPathString = argv[++i];
argv[i] = null;
} else {
error("rmic.option.requires.argument", "-classpath");
usage();
return false;
}
} else if (argv[i].equals("-sourcepath")) {
if ((i + 1) < argv.length) {
if (sourcePathArg != null) {
error("rmic.option.already.seen", "-sourcepath");
usage();
return false;
}
argv[i] = null;
sourcePathArg = argv[++i];
argv[i] = null;
} else {
error("rmic.option.requires.argument", "-sourcepath");
usage();
return false;
}
} else if (argv[i].equals("-bootclasspath")) {
if ((i + 1) < argv.length) {
if (sysClassPathArg != null) {
error("rmic.option.already.seen", "-bootclasspath");
usage();
return false;
}
argv[i] = null;
sysClassPathArg = argv[++i];
argv[i] = null;
} else {
error("rmic.option.requires.argument", "-bootclasspath");
usage();
return false;
}
} else if (argv[i].equals("-extdirs")) {
if ((i + 1) < argv.length) {
if (extDirsArg != null) {
error("rmic.option.already.seen", "-extdirs");
usage();
return false;
}
argv[i] = null;
extDirsArg = argv[++i];
argv[i] = null;
} else {
error("rmic.option.requires.argument", "-extdirs");
usage();
return false;
}
} else if (argv[i].equals("-d")) {
if ((i + 1) < argv.length) {
if (destDir != null) {
error("rmic.option.already.seen", "-d");
usage();
return false;
}
argv[i] = null;
destDir = new File(argv[++i]);
argv[i] = null;
if (!destDir.exists()) {
error("rmic.no.such.directory", destDir.getPath());
usage();
return false;
}
} else {
error("rmic.option.requires.argument", "-d");
usage();
return false;
}
} else {
if (!checkGeneratorArg(argv,i)) {
usage();
return false;
}
}
}
}
// Now that all generators have had a chance at the args,
// scan what's left for classes and illegal args...
for (int i = 0; i < argv.length; i++) {
if (argv[i] != null) {
if (argv[i].startsWith("-")) {
error("rmic.no.such.option", argv[i]);
usage();
return false;
} else {
classes.addElement(argv[i]);
}
}
}
// If the generators vector is empty, add the default generator...
if (generators.size() == 0) {
addGenerator("default");
}
return true;
}
/**
* If this argument is for a generator, instantiate it, call
* parseArgs(...) and add generator to generators vector.
* Returns false on error.
*/
protected boolean checkGeneratorArg(String[] argv, int currentIndex) {
boolean result = true;
if (argv[currentIndex].startsWith("-")) {
String arg = argv[currentIndex].substring(1).toLowerCase(); // Remove '-'
for (int i = 0; i < generatorArgs.length; i++) {
if (arg.equalsIgnoreCase(generatorArgs[i])) {
// Got a match, add Generator and call parseArgs...
Generator gen = addGenerator(arg);
if (gen == null) {
return false;
}
result = gen.parseArgs(argv,this);
break;
}
}
}
return result;
}
/**
* Instantiate and add a generator to the generators array.
*/
protected Generator addGenerator(String arg) {
Generator gen;
// Create an instance of the generator and add it to
// the array...
String className = getString("generator.class." + arg);
if (className == null) {
error("rmic.missing.property",arg);
return null;
}
try {
gen = (Generator) Class.forName(className).newInstance();
} catch (Exception e) {
error("rmic.cannot.instantiate",className);
return null;
}
generators.addElement(gen);
// Get the environment required by this generator...
Class<?> envClass = BatchEnvironment.class;
String env = getString("generator.env." + arg);
if (env != null) {
try {
envClass = Class.forName(env);
// Is the new class a subclass of the current one?
if (environmentClass.isAssignableFrom(envClass)) {
// Yes, so switch to the new one...
environmentClass = envClass.asSubclass(BatchEnvironment.class);
} else {
// No. Is the current class a subclass of the
// new one?
if (!envClass.isAssignableFrom(environmentClass)) {
// No, so it's a conflict...
error("rmic.cannot.use.both",environmentClass.getName(),envClass.getName());
return null;
}
}
} catch (ClassNotFoundException e) {
error("rmic.class.not.found",env);
return null;
}
}
// If this is the iiop stub generator, cache
// that fact for the jrmp generator...
if (arg.equals("iiop")) {
iiopGeneration = true;
}
return gen;
}
/**
* Grab a resource string and parse it into an array of strings. Assumes
* comma separated list.
* @param name The resource name.
* @param mustExist If true, throws error if resource does not exist. If
* false and resource does not exist, returns zero element array.
*/
protected String[] getArray(String name, boolean mustExist) {
String[] result = null;
String value = getString(name);
if (value == null) {
if (mustExist) {
error("rmic.resource.not.found",name);
return null;
} else {
return new String[0];
}
}
StringTokenizer parser = new StringTokenizer(value,", \t\n\r", false);
int count = parser.countTokens();
result = new String[count];
for (int i = 0; i < count; i++) {
result[i] = parser.nextToken();
}
return result;
}
/**
* Get the correct type of BatchEnvironment
*/
public BatchEnvironment getEnv() {
ClassPath classPath =
BatchEnvironment.createClassPath(classPathString,
sysClassPathArg,
extDirsArg);
BatchEnvironment result = null;
try {
Class<?>[] ctorArgTypes = {OutputStream.class,ClassPath.class,Main.class};
Object[] ctorArgs = {out,classPath,this};
Constructor<? extends BatchEnvironment> constructor =
environmentClass.getConstructor(ctorArgTypes);
result = constructor.newInstance(ctorArgs);
result.reset();
}
catch (Exception e) {
error("rmic.cannot.instantiate",environmentClass.getName());
}
return result;
}
/**
* Do the compile with the switches and files already supplied
*/
public boolean doCompile() {
// Create batch environment
BatchEnvironment env = getEnv();
env.flags |= flags;
// Set the classfile version numbers
// Compat and 1.1 stubs must retain the old version number.
env.majorVersion = 45;
env.minorVersion = 3;
// Preload the "out of memory" error string just in case we run
// out of memory during the compile.
String noMemoryErrorString = getText("rmic.no.memory");
String stackOverflowErrorString = getText("rmic.stack.overflow");
try {
/** Load the classes on the command line
* Replace the entries in classes with the ClassDefinition for the class
*/
for (int i = classes.size()-1; i >= 0; i-- ) {
Identifier implClassName =
Identifier.lookup(classes.elementAt(i));
/*
* Fix bugid 4049354: support using '.' as an inner class
* qualifier on the command line (previously, only mangled
* inner class names were understood, like "pkg.Outer$Inner").
*
* The following method, also used by "javap", resolves the
* given unmangled inner class name to the appropriate
* internal identifier. For example, it translates
* "pkg.Outer.Inner" to "pkg.Outer. Inner".
*/
implClassName = env.resolvePackageQualifiedName(implClassName);
/*
* But if we use such an internal inner class name identifier
* to load the class definition, the Java compiler will notice
* if the impl class is a "private" inner class and then deny
* skeletons (needed unless "-v1.2" is used) the ability to
* cast to it. To work around this problem, we mangle inner
* class name identifiers to their binary "outer" class name:
* "pkg.Outer. Inner" becomes "pkg.Outer$Inner".
*/
implClassName = Names.mangleClass(implClassName);
ClassDeclaration decl = env.getClassDeclaration(implClassName);
try {
ClassDefinition def = decl.getClassDefinition(env);
for (int j = 0; j < generators.size(); j++) {
Generator gen = generators.elementAt(j);
gen.generate(env, def, destDir);
}
} catch (ClassNotFound ex) {
env.error(0, "rmic.class.not.found", implClassName);
}
}
// compile all classes that need compilation
if (!nocompile) {
compileAllClasses(env);
}
} catch (OutOfMemoryError ee) {
// The compiler has run out of memory. Use the error string
// which we preloaded.
env.output(noMemoryErrorString);
return false;
} catch (StackOverflowError ee) {
env.output(stackOverflowErrorString);
return false;
} catch (Error ee) {
// We allow the compiler to take an exception silently if a program
// error has previously been detected. Presumably, this makes the
// compiler more robust in the face of bad error recovery.
if (env.nerrors == 0 || env.dump()) {
env.error(0, "fatal.error");
ee.printStackTrace(out instanceof PrintStream ?
(PrintStream) out :
new PrintStream(out, true));
}
} catch (Exception ee) {
if (env.nerrors == 0 || env.dump()) {
env.error(0, "fatal.exception");
ee.printStackTrace(out instanceof PrintStream ?
(PrintStream) out :
new PrintStream(out, true));
}
}
env.flushErrors();
boolean status = true;
if (env.nerrors > 0) {
String msg = "";
if (env.nerrors > 1) {
msg = getText("rmic.errors", env.nerrors);
} else {
msg = getText("rmic.1error");
}
if (env.nwarnings > 0) {
if (env.nwarnings > 1) {
msg += ", " + getText("rmic.warnings", env.nwarnings);
} else {
msg += ", " + getText("rmic.1warning");
}
}
output(msg);
status = false;
} else {
if (env.nwarnings > 0) {
if (env.nwarnings > 1) {
output(getText("rmic.warnings", env.nwarnings));
} else {
output(getText("rmic.1warning"));
}
}
}
// last step is to delete generated source files
if (!keepGenerated) {
env.deleteGeneratedFiles();
}
// We're done
if (env.verbose()) {
tm = System.currentTimeMillis() - tm;
output(getText("rmic.done_in", Long.toString(tm)));
}
// Shutdown the environment object and release our resources.
// Note that while this is unneccessary when rmic is invoked
// the command line, there are environments in which rmic
// from is invoked within a server process, so resource
// reclamation is important...
env.shutdown();
sourcePathArg = null;
sysClassPathArg = null;
extDirsArg = null;
classPathString = null;
destDir = null;
classes = null;
generatorArgs = null;
generators = null;
environmentClass = null;
program = null;
out = null;
return status;
}
/*
* Compile all classes that need to be compiled.
*/
public void compileAllClasses (BatchEnvironment env)
throws ClassNotFound,
IOException,
InterruptedException {
ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
boolean done;
do {
done = true;
for (Enumeration<?> e = env.getClasses() ; e.hasMoreElements() ; ) {
ClassDeclaration c = (ClassDeclaration)e.nextElement();
done = compileClass(c,buf,env);
}
} while (!done);
}
/*
* Compile a single class.
* Fallthrough is intentional
*/
@SuppressWarnings("fallthrough")
public boolean compileClass (ClassDeclaration c,
ByteArrayOutputStream buf,
BatchEnvironment env)
throws ClassNotFound,
IOException,
InterruptedException {
boolean done = true;
env.flushErrors();
SourceClass src;
switch (c.getStatus()) {
case CS_UNDEFINED:
{
if (!env.dependencies()) {
break;
}
// fall through
}
case CS_SOURCE:
{
done = false;
env.loadDefinition(c);
if (c.getStatus() != CS_PARSED) {
break;
}
// fall through
}
case CS_PARSED:
{
if (c.getClassDefinition().isInsideLocal()) {
break;
}
// If we get to here, then compilation is going
// to occur. If the -Xnocompile switch is set
// then fail. Note that this check is required
// here because this method is called from
// generators, not just from within this class...
if (nocompile) {
throw new IOException("Compilation required, but -Xnocompile option in effect");
}
done = false;
src = (SourceClass)c.getClassDefinition(env);
src.check(env);
c.setDefinition(src, CS_CHECKED);
// fall through
}
case CS_CHECKED:
{
src = (SourceClass)c.getClassDefinition(env);
// bail out if there were any errors
if (src.getError()) {
c.setDefinition(src, CS_COMPILED);
break;
}
done = false;
buf.reset();
src.compile(buf);
c.setDefinition(src, CS_COMPILED);
src.cleanup(env);
if (src.getError() || nowrite) {
break;
}
String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);
String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";
File file;
if (destDir != null) {
if (pkgName.length() > 0) {
file = new File(destDir, pkgName);
if (!file.exists()) {
file.mkdirs();
}
file = new File(file, className);
} else {
file = new File(destDir, className);
}
} else {
ClassFile classfile = (ClassFile)src.getSource();
if (classfile.isZipped()) {
env.error(0, "cant.write", classfile.getPath());
break;
}
file = new File(classfile.getPath());
file = new File(file.getParent(), className);
}
// Create the file
try {
FileOutputStream out = new FileOutputStream(file.getPath());
buf.writeTo(out);
out.close();
if (env.verbose()) {
output(getText("rmic.wrote", file.getPath()));
}
} catch (IOException ee) {
env.error(0, "cant.write", file.getPath());
}
}
}
return done;
}
/**
* Main program
*/
public static void main(String argv[]) {
Main compiler = new Main(System.out, "rmic");
System.exit(compiler.compile(argv) ? 0 : 1);
}
/**
* Return the string value of a named resource in the rmic.properties
* resource bundle. If the resource is not found, null is returned.
*/
public static String getString(String key) {
if (!resourcesInitialized) {
initResources();
}
// To enable extensions, search the 'resourcesExt'
// bundle first, followed by the 'resources' bundle...
if (resourcesExt != null) {
try {
return resourcesExt.getString(key);
} catch (MissingResourceException e) {}
}
try {
return resources.getString(key);
} catch (MissingResourceException ignore) {
}
return null;
}
private static boolean resourcesInitialized = false;
private static ResourceBundle resources;
private static ResourceBundle resourcesExt = null;
private static void initResources() {
try {
resources =
ResourceBundle.getBundle("sun.rmi.rmic.resources.rmic");
resourcesInitialized = true;
try {
resourcesExt =
ResourceBundle.getBundle("sun.rmi.rmic.resources.rmicext");
} catch (MissingResourceException e) {}
} catch (MissingResourceException e) {
throw new Error("fatal: missing resource bundle: " +
e.getClassName());
}
}
public static String getText(String key) {
String message = getString(key);
if (message == null) {
message = "no text found: \"" + key + "\"";
}
return message;
}
public static String getText(String key, int num) {
return getText(key, Integer.toString(num), null, null);
}
public static String getText(String key, String arg0) {
return getText(key, arg0, null, null);
}
public static String getText(String key, String arg0, String arg1) {
return getText(key, arg0, arg1, null);
}
public static String getText(String key,
String arg0, String arg1, String arg2)
{
String format = getString(key);
if (format == null) {
format = "no text found: key = \"" + key + "\", " +
"arguments = \"{0}\", \"{1}\", \"{2}\"";
}
String[] args = new String[3];
args[0] = (arg0 != null ? arg0 : "null");
args[1] = (arg1 != null ? arg1 : "null");
args[2] = (arg2 != null ? arg2 : "null");
return java.text.MessageFormat.format(format, (Object[]) args);
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 1996, 2003, 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.
*/
package sun.rmi.rmic;
import sun.tools.java.Identifier;
/**
* Names provides static utility methods used by other rmic classes
* for dealing with identifiers.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public class Names {
/**
* Return stub class name for impl class name.
*/
static final public Identifier stubFor(Identifier name) {
return Identifier.lookup(name + "_Stub");
}
/**
* Return skeleton class name for impl class name.
*/
static final public Identifier skeletonFor(Identifier name) {
return Identifier.lookup(name + "_Skel");
}
/**
* If necessary, convert a class name to its mangled form, i.e. the
* non-inner class name used in the binary representation of
* inner classes. This is necessary to be able to name inner
* classes in the generated source code in places where the language
* does not permit it, such as when synthetically defining an inner
* class outside of its outer class, and for generating file names
* corresponding to inner classes.
*
* Currently this mangling involves modifying the internal names of
* inner classes by converting occurrences of ". " into "$".
*
* This code is taken from the "mangleInnerType" method of
* the "sun.tools.java.Type" class; this method cannot be accessed
* itself because it is package protected.
*/
static final public Identifier mangleClass(Identifier className) {
if (!className.isInner())
return className;
/*
* Get '.' qualified inner class name (with outer class
* qualification and no package qualification) and replace
* each '.' with '$'.
*/
Identifier mangled = Identifier.lookup(
className.getFlatName().toString()
.replace('.', sun.tools.java.Constants.SIGC_INNERCLASS));
if (mangled.isInner())
throw new Error("failed to mangle inner class name");
// prepend package qualifier back for returned identifier
return Identifier.lookup(className.getQualifier(), mangled);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic;
import sun.tools.java.Identifier;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public interface RMIConstants extends sun.rmi.rmic.Constants {
/*
* identifiers for RMI classes referenced by rmic
*/
public static final Identifier idRemoteObject =
Identifier.lookup("java.rmi.server.RemoteObject");
public static final Identifier idRemoteStub =
Identifier.lookup("java.rmi.server.RemoteStub");
public static final Identifier idRemoteRef =
Identifier.lookup("java.rmi.server.RemoteRef");
public static final Identifier idOperation =
Identifier.lookup("java.rmi.server.Operation");
public static final Identifier idSkeleton =
Identifier.lookup("java.rmi.server.Skeleton");
public static final Identifier idSkeletonMismatchException =
Identifier.lookup("java.rmi.server.SkeletonMismatchException");
public static final Identifier idRemoteCall =
Identifier.lookup("java.rmi.server.RemoteCall");
public static final Identifier idMarshalException =
Identifier.lookup("java.rmi.MarshalException");
public static final Identifier idUnmarshalException =
Identifier.lookup("java.rmi.UnmarshalException");
public static final Identifier idUnexpectedException =
Identifier.lookup("java.rmi.UnexpectedException");
/*
* stub protocol versions
*/
public static final int STUB_VERSION_1_1 = 1;
public static final int STUB_VERSION_FAT = 2;
public static final int STUB_VERSION_1_2 = 3;
/** serialVersionUID for all stubs that can use 1.2 protocol */
public static final long STUB_SERIAL_VERSION_UID = 2;
/** version number used to seed interface hash computation */
public static final int INTERFACE_HASH_STUB_VERSION = 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,876 @@
/*
* Copyright (c) 1997, 2013, 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.
*/
package sun.rmi.rmic;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.DigestOutputStream;
import java.security.NoSuchAlgorithmException;
import sun.tools.java.Type;
import sun.tools.java.ClassDefinition;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.MemberDefinition;
import sun.tools.java.Identifier;
import sun.tools.java.ClassNotFound;
/**
* A RemoteClass object encapsulates RMI-specific information about
* a remote implementation class, i.e. a class that implements
* one or more remote interfaces.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
*/
public class RemoteClass implements sun.rmi.rmic.RMIConstants {
/**
* Create a RemoteClass object representing the remote meta-information
* of the given class.
*
* Returns true if successful. If the class is not a properly formed
* remote implementation class or if some other error occurs, the
* return value will be null, and errors will have been reported to
* the supplied BatchEnvironment.
*/
public static RemoteClass forClass(BatchEnvironment env,
ClassDefinition implClassDef)
{
RemoteClass rc = new RemoteClass(env, implClassDef);
if (rc.initialize()) {
return rc;
} else {
return null;
}
}
/**
* Return the ClassDefinition for this class.
*/
public ClassDefinition getClassDefinition() {
return implClassDef;
}
/**
* Return the name of the class represented by this object.
*/
public Identifier getName() {
return implClassDef.getName();
}
/**
* Return an array of ClassDefinitions representing all of the remote
* interfaces implemented by this class.
*
* A remote interface is any interface that extends Remote,
* directly or indirectly. The remote interfaces of a class
* are the interfaces directly listed in either the class's
* "implements" clause, or the "implements" clause of any
* of its superclasses, that are remote interfaces.
*
* The order of the array returned is arbitrary, and some elements
* may be superfluous (i.e., superinterfaces of other interfaces
* in the array).
*/
public ClassDefinition[] getRemoteInterfaces() {
return remoteInterfaces.clone();
}
/**
* Return an array of RemoteClass.Method objects representing all of
* the remote methods implemented by this class, i.e. all of the
* methods in the class's remote interfaces.
*
* The methods in the array are ordered according to the comparision
* of the strings consisting of their method name followed by their
* type signature, so each method's index in the array corresponds
* to its "operation number" in the JDK 1.1 version of the
* stub/skeleton protocol.
*/
public Method[] getRemoteMethods() {
return remoteMethods.clone();
}
/**
* Return the "interface hash" used to match a stub/skeleton pair for
* this class in the JDK 1.1 version of the stub/skeleton protocol.
*/
public long getInterfaceHash() {
return interfaceHash;
}
/**
* Return string representation of this object, consisting of
* the string "remote class " followed by the class name.
*/
public String toString() {
return "remote class " + implClassDef.getName().toString();
}
/** rmic environment for this object */
private BatchEnvironment env;
/** the remote implementation class this object corresponds to */
private ClassDefinition implClassDef;
/** remote interfaces implemented by this class */
private ClassDefinition[] remoteInterfaces;
/** all the remote methods of this class */
private Method[] remoteMethods;
/** stub/skeleton "interface hash" for this class */
private long interfaceHash;
/** cached definition for certain classes used in this environment */
private ClassDefinition defRemote;
private ClassDefinition defException;
private ClassDefinition defRemoteException;
/**
* Create a RemoteClass instance for the given class. The resulting
* object is not yet initialized.
*/
private RemoteClass(BatchEnvironment env, ClassDefinition implClassDef) {
this.env = env;
this.implClassDef = implClassDef;
}
/**
* Validate that the remote implementation class is properly formed
* and fill in the data structures required by the public interface.
*/
private boolean initialize() {
/*
* Verify that the "impl" is really a class, not an interface.
*/
if (implClassDef.isInterface()) {
env.error(0, "rmic.cant.make.stubs.for.interface",
implClassDef.getName());
return false;
}
/*
* Initialize cached definitions for the Remote interface and
* the RemoteException class.
*/
try {
defRemote =
env.getClassDeclaration(idRemote).getClassDefinition(env);
defException =
env.getClassDeclaration(idJavaLangException).
getClassDefinition(env);
defRemoteException =
env.getClassDeclaration(idRemoteException).
getClassDefinition(env);
} catch (ClassNotFound e) {
env.error(0, "rmic.class.not.found", e.name);
return false;
}
/*
* Here we find all of the remote interfaces of our remote
* implementation class. For each class up the superclass
* chain, add each directly-implemented interface that
* somehow extends Remote to a list.
*/
Vector<ClassDefinition> remotesImplemented = // list of remote interfaces found
new Vector<ClassDefinition>();
for (ClassDefinition classDef = implClassDef;
classDef != null;)
{
try {
ClassDeclaration[] interfaces = classDef.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
ClassDefinition interfaceDef =
interfaces[i].getClassDefinition(env);
/*
* Add interface to the list if it extends Remote and
* it is not already there.
*/
if (!remotesImplemented.contains(interfaceDef) &&
defRemote.implementedBy(env, interfaces[i]))
{
remotesImplemented.addElement(interfaceDef);
/***** <DEBUG> */
if (env.verbose()) {
System.out.println("[found remote interface: " +
interfaceDef.getName() + "]");
/***** </DEBUG> */
}
}
}
/*
* Verify that the candidate remote implementation class
* implements at least one remote interface directly.
*/
if (classDef == implClassDef && remotesImplemented.isEmpty()) {
if (defRemote.implementedBy(env,
implClassDef.getClassDeclaration()))
{
/*
* This error message is used if the class does
* implement a remote interface through one of
* its superclasses, but not directly.
*/
env.error(0, "rmic.must.implement.remote.directly",
implClassDef.getName());
} else {
/*
* This error message is used if the class never
* implements a remote interface.
*/
env.error(0, "rmic.must.implement.remote",
implClassDef.getName());
}
return false;
}
/*
* Get definition for next superclass.
*/
classDef = (classDef.getSuperClass() != null ?
classDef.getSuperClass().getClassDefinition(env) :
null);
} catch (ClassNotFound e) {
env.error(0, "class.not.found", e.name, classDef.getName());
return false;
}
}
/*
* The "remotesImplemented" vector now contains all of the remote
* interfaces directly implemented by the remote class or by any
* of its superclasses.
*
* At this point, we could optimize the list by removing superfluous
* entries, i.e. any interfaces that are implemented by some other
* interface in the list anyway.
*
* This should be correct; would it be worthwhile?
*
* for (int i = 0; i < remotesImplemented.size();) {
* ClassDefinition interfaceDef =
* (ClassDefinition) remotesImplemented.elementAt(i);
* boolean isOtherwiseImplemented = false;
* for (int j = 0; j < remotesImplemented.size; j++) {
* if (j != i &&
* interfaceDef.implementedBy(env, (ClassDefinition)
* remotesImplemented.elementAt(j).
* getClassDeclaration()))
* {
* isOtherwiseImplemented = true;
* break;
* }
* }
* if (isOtherwiseImplemented) {
* remotesImplemented.removeElementAt(i);
* } else {
* ++i;
* }
* }
*/
/*
* Now we collect the methods from all of the remote interfaces
* into a hashtable.
*/
Hashtable<String, Method> methods = new Hashtable<String, Method>();
boolean errors = false;
for (Enumeration<ClassDefinition> enumeration
= remotesImplemented.elements();
enumeration.hasMoreElements();)
{
ClassDefinition interfaceDef = enumeration.nextElement();
if (!collectRemoteMethods(interfaceDef, methods))
errors = true;
}
if (errors)
return false;
/*
* Convert vector of remote interfaces to an array
* (order is not important for this array).
*/
remoteInterfaces = new ClassDefinition[remotesImplemented.size()];
remotesImplemented.copyInto(remoteInterfaces);
/*
* Sort table of remote methods into an array. The elements are
* sorted in ascending order of the string of the method's name
* and type signature, so that each elements index is equal to
* its operation number of the JDK 1.1 version of the stub/skeleton
* protocol.
*/
String[] orderedKeys = new String[methods.size()];
int count = 0;
for (Enumeration<Method> enumeration = methods.elements();
enumeration.hasMoreElements();)
{
Method m = enumeration.nextElement();
String key = m.getNameAndDescriptor();
int i;
for (i = count; i > 0; --i) {
if (key.compareTo(orderedKeys[i - 1]) >= 0) {
break;
}
orderedKeys[i] = orderedKeys[i - 1];
}
orderedKeys[i] = key;
++count;
}
remoteMethods = new Method[methods.size()];
for (int i = 0; i < remoteMethods.length; i++) {
remoteMethods[i] = methods.get(orderedKeys[i]);
/***** <DEBUG> */
if (env.verbose()) {
System.out.print("[found remote method <" + i + ">: " +
remoteMethods[i].getOperationString());
ClassDeclaration[] exceptions =
remoteMethods[i].getExceptions();
if (exceptions.length > 0)
System.out.print(" throws ");
for (int j = 0; j < exceptions.length; j++) {
if (j > 0)
System.out.print(", ");
System.out.print(exceptions[j].getName());
}
System.out.println("]");
}
/***** </DEBUG> */
}
/**
* Finally, pre-compute the interface hash to be used by
* stubs/skeletons for this remote class.
*/
interfaceHash = computeInterfaceHash();
return true;
}
/**
* Collect and validate all methods from given interface and all of
* its superinterfaces as remote methods. Remote methods are added
* to the supplied hashtable. Returns true if successful,
* or false if an error occurred.
*/
private boolean collectRemoteMethods(ClassDefinition interfaceDef,
Hashtable<String, Method> table)
{
if (!interfaceDef.isInterface()) {
throw new Error(
"expected interface, not class: " + interfaceDef.getName());
}
/*
* rmic used to enforce that a remote interface could not extend
* a non-remote interface, i.e. an interface that did not itself
* extend from Remote. The current version of rmic does not have
* this restriction, so the following code is now commented out.
*
* Verify that this interface extends Remote, since all interfaces
* extended by a remote interface must implement Remote.
*
* try {
* if (!defRemote.implementedBy(env,
* interfaceDef.getClassDeclaration()))
* {
* env.error(0, "rmic.can.mix.remote.nonremote",
* interfaceDef.getName());
* return false;
* }
* } catch (ClassNotFound e) {
* env.error(0, "class.not.found", e.name,
* interfaceDef.getName());
* return false;
* }
*/
boolean errors = false;
/*
* Search interface's members for methods.
*/
nextMember:
for (MemberDefinition member = interfaceDef.getFirstMember();
member != null;
member = member.getNextMember())
{
if (member.isMethod() &&
!member.isConstructor() && !member.isInitializer())
{
/*
* Verify that each method throws RemoteException.
*/
ClassDeclaration[] exceptions = member.getExceptions(env);
boolean hasRemoteException = false;
for (int i = 0; i < exceptions.length; i++) {
/*
* rmic used to enforce that a remote method had to
* explicitly list RemoteException in its "throws"
* clause; i.e., just throwing Exception was not
* acceptable. The current version of rmic does not
* have this restriction, so the following code is
* now commented out. Instead, the method is
* considered valid if RemoteException is a subclass
* of any of the methods declared exceptions.
*
* if (exceptions[i].getName().equals(
* idRemoteException))
* {
* hasRemoteException = true;
* break;
* }
*/
try {
if (defRemoteException.subClassOf(
env, exceptions[i]))
{
hasRemoteException = true;
break;
}
} catch (ClassNotFound e) {
env.error(0, "class.not.found", e.name,
interfaceDef.getName());
continue nextMember;
}
}
/*
* If this method did not throw RemoteException as required,
* generate the error but continue, so that multiple such
* errors can be reported.
*/
if (!hasRemoteException) {
env.error(0, "rmic.must.throw.remoteexception",
interfaceDef.getName(), member.toString());
errors = true;
continue nextMember;
}
/*
* Verify that the implementation of this method throws only
* java.lang.Exception or its subclasses (fix bugid 4092486).
* JRMP does not support remote methods throwing
* java.lang.Throwable or other subclasses.
*/
try {
MemberDefinition implMethod = implClassDef.findMethod(
env, member.getName(), member.getType());
if (implMethod != null) { // should not be null
exceptions = implMethod.getExceptions(env);
for (int i = 0; i < exceptions.length; i++) {
if (!defException.superClassOf(
env, exceptions[i]))
{
env.error(0, "rmic.must.only.throw.exception",
implMethod.toString(),
exceptions[i].getName());
errors = true;
continue nextMember;
}
}
}
} catch (ClassNotFound e) {
env.error(0, "class.not.found", e.name,
implClassDef.getName());
continue nextMember;
}
/*
* Create RemoteClass.Method object to represent this method
* found in a remote interface.
*/
Method newMethod = new Method(member);
/*
* Store remote method's representation in the table of
* remote methods found, keyed by its name and parameter
* signature.
*
* If the table already contains an entry with the same
* method name and parameter signature, then we must
* replace the old entry with a Method object that
* represents a legal combination of the old and the new
* methods; specifically, the combined method must have
* a throws list that contains (only) all of the checked
* exceptions that can be thrown by both the old or
* the new method (see bugid 4070653).
*/
String key = newMethod.getNameAndDescriptor();
Method oldMethod = table.get(key);
if (oldMethod != null) {
newMethod = newMethod.mergeWith(oldMethod);
if (newMethod == null) {
errors = true;
continue nextMember;
}
}
table.put(key, newMethod);
}
}
/*
* Recursively collect methods for all superinterfaces.
*/
try {
ClassDeclaration[] superDefs = interfaceDef.getInterfaces();
for (int i = 0; i < superDefs.length; i++) {
ClassDefinition superDef =
superDefs[i].getClassDefinition(env);
if (!collectRemoteMethods(superDef, table))
errors = true;
}
} catch (ClassNotFound e) {
env.error(0, "class.not.found", e.name, interfaceDef.getName());
return false;
}
return !errors;
}
/**
* Compute the "interface hash" of the stub/skeleton pair for this
* remote implementation class. This is the 64-bit value used to
* enforce compatibility between a stub and a skeleton using the
* JDK 1.1 version of the stub/skeleton protocol.
*
* It is calculated using the first 64 bits of a SHA digest. The
* digest is from a stream consisting of the following data:
* (int) stub version number, always 1
* for each remote method, in order of operation number:
* (UTF) method name
* (UTF) method type signature
* for each declared exception, in alphabetical name order:
* (UTF) name of exception class
*
*/
private long computeInterfaceHash() {
long hash = 0;
ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
try {
MessageDigest md = MessageDigest.getInstance("SHA");
DataOutputStream out = new DataOutputStream(
new DigestOutputStream(sink, md));
out.writeInt(INTERFACE_HASH_STUB_VERSION);
for (int i = 0; i < remoteMethods.length; i++) {
MemberDefinition m = remoteMethods[i].getMemberDefinition();
Identifier name = m.getName();
Type type = m.getType();
out.writeUTF(name.toString());
// type signatures already use mangled class names
out.writeUTF(type.getTypeSignature());
ClassDeclaration exceptions[] = m.getExceptions(env);
sortClassDeclarations(exceptions);
for (int j = 0; j < exceptions.length; j++) {
out.writeUTF(Names.mangleClass(
exceptions[j].getName()).toString());
}
}
out.flush();
// use only the first 64 bits of the digest for the hash
byte hashArray[] = md.digest();
for (int i = 0; i < Math.min(8, hashArray.length); i++) {
hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
}
} catch (IOException e) {
throw new Error(
"unexpected exception computing intetrface hash: " + e);
} catch (NoSuchAlgorithmException e) {
throw new Error(
"unexpected exception computing intetrface hash: " + e);
}
return hash;
}
/**
* Sort array of class declarations alphabetically by their mangled
* fully-qualified class name. This is used to feed a method's exceptions
* in a canonical order into the digest stream for the interface hash
* computation.
*/
private void sortClassDeclarations(ClassDeclaration[] decl) {
for (int i = 1; i < decl.length; i++) {
ClassDeclaration curr = decl[i];
String name = Names.mangleClass(curr.getName()).toString();
int j;
for (j = i; j > 0; j--) {
if (name.compareTo(
Names.mangleClass(decl[j - 1].getName()).toString()) >= 0)
{
break;
}
decl[j] = decl[j - 1];
}
decl[j] = curr;
}
}
/**
* A RemoteClass.Method object encapsulates RMI-specific information
* about a particular remote method in the remote implementation class
* represented by the outer instance.
*/
public class Method implements Cloneable {
/**
* Return the definition of the actual class member corresponing
* to this method of a remote interface.
*
* REMIND: Can this method be removed?
*/
public MemberDefinition getMemberDefinition() {
return memberDef;
}
/**
* Return the name of this method.
*/
public Identifier getName() {
return memberDef.getName();
}
/**
* Return the type of this method.
*/
public Type getType() {
return memberDef.getType();
}
/**
* Return an array of the exception classes declared to be
* thrown by this remote method.
*
* For methods with the same name and type signature inherited
* from multiple remote interfaces, the array will contain
* the set of exceptions declared in all of the interfaces'
* methods that can be legally thrown in each of them.
*/
public ClassDeclaration[] getExceptions() {
return exceptions.clone();
}
/**
* Return the "method hash" used to identify this remote method
* in the JDK 1.2 version of the stub protocol.
*/
public long getMethodHash() {
return methodHash;
}
/**
* Return the string representation of this method.
*/
public String toString() {
return memberDef.toString();
}
/**
* Return the string representation of this method appropriate
* for the construction of a java.rmi.server.Operation object.
*/
public String getOperationString() {
return memberDef.toString();
}
/**
* Return a string consisting of this method's name followed by
* its method descriptor, using the Java VM's notation for
* method descriptors (see section 4.3.3 of The Java Virtual
* Machine Specification).
*/
public String getNameAndDescriptor() {
return memberDef.getName().toString() +
memberDef.getType().getTypeSignature();
}
/**
* Member definition for this method, from one of the remote
* interfaces that this method was found in.
*
* Note that this member definition may be only one of several
* member defintions that correspond to this remote method object,
* if several of this class's remote interfaces contain methods
* with the same name and type signature. Therefore, this member
* definition may declare more exceptions thrown that this remote
* method does.
*/
private MemberDefinition memberDef;
/** stub "method hash" to identify this method */
private long methodHash;
/**
* Exceptions declared to be thrown by this remote method.
*
* This list can include superfluous entries, such as
* unchecked exceptions and subclasses of other entries.
*/
private ClassDeclaration[] exceptions;
/**
* Create a new Method object corresponding to the given
* method definition.
*/
/*
* Temporarily comment out the private modifier until
* the VM allows outer class to access inner class's
* private constructor
*/
/* private */ Method(MemberDefinition memberDef) {
this.memberDef = memberDef;
exceptions = memberDef.getExceptions(env);
methodHash = computeMethodHash();
}
/**
* Cloning is supported by returning a shallow copy of this object.
*/
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new Error("clone failed");
}
}
/**
* Return a new Method object that is a legal combination of
* this method object and another one.
*
* This requires determining the exceptions declared by the
* combined method, which must be (only) all of the exceptions
* declared in both old Methods that may thrown in either of
* them.
*/
private Method mergeWith(Method other) {
if (!getName().equals(other.getName()) ||
!getType().equals(other.getType()))
{
throw new Error("attempt to merge method \"" +
other.getNameAndDescriptor() + "\" with \"" +
getNameAndDescriptor());
}
Vector<ClassDeclaration> legalExceptions
= new Vector<ClassDeclaration>();
try {
collectCompatibleExceptions(
other.exceptions, exceptions, legalExceptions);
collectCompatibleExceptions(
exceptions, other.exceptions, legalExceptions);
} catch (ClassNotFound e) {
env.error(0, "class.not.found", e.name,
getClassDefinition().getName());
return null;
}
Method merged = (Method) clone();
merged.exceptions = new ClassDeclaration[legalExceptions.size()];
legalExceptions.copyInto(merged.exceptions);
return merged;
}
/**
* Add to the supplied list all exceptions in the "from" array
* that are subclasses of an exception in the "with" array.
*/
private void collectCompatibleExceptions(ClassDeclaration[] from,
ClassDeclaration[] with,
Vector<ClassDeclaration> list)
throws ClassNotFound
{
for (int i = 0; i < from.length; i++) {
ClassDefinition exceptionDef = from[i].getClassDefinition(env);
if (!list.contains(from[i])) {
for (int j = 0; j < with.length; j++) {
if (exceptionDef.subClassOf(env, with[j])) {
list.addElement(from[i]);
break;
}
}
}
}
}
/**
* Compute the "method hash" of this remote method. The method
* hash is a long containing the first 64 bits of the SHA digest
* from the UTF encoded string of the method name and descriptor.
*
* REMIND: Should this method share implementation code with
* the outer class's computeInterfaceHash() method?
*/
private long computeMethodHash() {
long hash = 0;
ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
try {
MessageDigest md = MessageDigest.getInstance("SHA");
DataOutputStream out = new DataOutputStream(
new DigestOutputStream(sink, md));
String methodString = getNameAndDescriptor();
/***** <DEBUG> */
if (env.verbose()) {
System.out.println("[string used for method hash: \"" +
methodString + "\"]");
}
/***** </DEBUG> */
out.writeUTF(methodString);
// use only the first 64 bits of the digest for the hash
out.flush();
byte hashArray[] = md.digest();
for (int i = 0; i < Math.min(8, hashArray.length); i++) {
hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
}
} catch (IOException e) {
throw new Error(
"unexpected exception computing intetrface hash: " + e);
} catch (NoSuchAlgorithmException e) {
throw new Error(
"unexpected exception computing intetrface hash: " + e);
}
return hash;
}
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 1999, 2013, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic;
import java.io.File;
import sun.tools.java.Identifier;
/**
* Util provides static utility methods used by other rmic classes.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Bryan Atsatt
*/
public class Util implements sun.rmi.rmic.Constants {
/**
* Return the directory that should be used for output for a given
* class.
* @param theClass The fully qualified name of the class.
* @param rootDir The directory to use as the root of the
* package hierarchy. May be null, in which case the current
* working directory is used as the root.
*/
public static File getOutputDirectoryFor(Identifier theClass,
File rootDir,
BatchEnvironment env) {
File outputDir = null;
String className = theClass.getFlatName().toString().replace('.', SIGC_INNERCLASS);
String qualifiedClassName = className;
String packagePath = null;
String packageName = theClass.getQualifier().toString();
if (packageName.length() > 0) {
qualifiedClassName = packageName + "." + className;
packagePath = packageName.replace('.', File.separatorChar);
}
// Do we have a root directory?
if (rootDir != null) {
// Yes, do we have a package name?
if (packagePath != null) {
// Yes, so use it as the root. Open the directory...
outputDir = new File(rootDir, packagePath);
// Make sure the directory exists...
ensureDirectory(outputDir,env);
} else {
// Default package, so use root as output dir...
outputDir = rootDir;
}
} else {
// No root directory. Get the current working directory...
String workingDirPath = System.getProperty("user.dir");
File workingDir = new File(workingDirPath);
// Do we have a package name?
if (packagePath == null) {
// No, so use working directory...
outputDir = workingDir;
} else {
// Yes, so use working directory as the root...
outputDir = new File(workingDir, packagePath);
// Make sure the directory exists...
ensureDirectory(outputDir,env);
}
}
// Finally, return the directory...
return outputDir;
}
private static void ensureDirectory (File dir, BatchEnvironment env) {
if (!dir.exists()) {
dir.mkdirs();
if (!dir.exists()) {
env.error(0,"rmic.cannot.create.dir",dir.getAbsolutePath());
throw new InternalError();
}
}
}
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDefinition;
/**
* AbstractType represents any non-special interface which does not
* inherit from java.rmi.Remote, for which all methods throw RemoteException.
* <p>
* The static forAbstract(...) method must be used to obtain an instance, and will
* return null if the ClassDefinition is non-conforming.
* @author Bryan Atsatt
*/
public class AbstractType extends RemoteType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an AbstractType for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static AbstractType forAbstract(ClassDefinition classDef,
ContextStack stack,
boolean quiet)
{
boolean doPop = false;
AbstractType result = null;
try {
// Do we already have it?
sun.tools.java.Type theType = classDef.getType();
Type existing = getType(theType,stack);
if (existing != null) {
if (!(existing instanceof AbstractType)) return null; // False hit.
// Yep, so return it...
return (AbstractType) existing;
}
// Could this be an abstract?
if (couldBeAbstract(stack,classDef,quiet)) {
// Yes, so try it...
AbstractType it = new AbstractType(stack, classDef);
putType(theType,it,stack);
stack.push(it);
doPop = true;
if (it.initialize(quiet,stack)) {
stack.pop(true);
result = it;
} else {
removeType(theType,stack);
stack.pop(false);
}
}
} catch (CompilerError e) {
if (doPop) stack.pop(false);
}
return result;
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Abstract interface";
}
//_____________________________________________________________________
// Internal/Subclass Interfaces
//_____________________________________________________________________
/**
* Create a AbstractType instance for the given class. The resulting
* object is not yet completely initialized.
*/
private AbstractType(ContextStack stack, ClassDefinition classDef) {
super(stack,classDef,TYPE_ABSTRACT | TM_INTERFACE | TM_COMPOUND);
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
private static boolean couldBeAbstract(ContextStack stack, ClassDefinition classDef,
boolean quiet) {
// Return true if interface and not remote...
boolean result = false;
if (classDef.isInterface()) {
BatchEnvironment env = stack.getEnv();
try {
result = ! env.defRemote.implementedBy(env, classDef.getClassDeclaration());
if (!result) failedConstraint(15,quiet,stack,classDef.getName());
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
} else {
failedConstraint(14,quiet,stack,classDef.getName());
}
return result;
}
/**
* Initialize this instance.
*/
private boolean initialize (boolean quiet,ContextStack stack) {
boolean result = false;
ClassDefinition self = getClassDefinition();
try {
// Get methods...
Vector directMethods = new Vector();
if (addAllMethods(self,directMethods,true,quiet,stack) != null) {
// Do we have any methods?
boolean validMethods = true;
if (directMethods.size() > 0) {
// Yes. Walk 'em, ensuring each is a valid remote method...
for (int i = 0; i < directMethods.size(); i++) {
if (! isConformingRemoteMethod((Method) directMethods.elementAt(i),true)) {
validMethods = false;
}
}
}
if (validMethods) {
// We're ok, so pass 'em up...
result = initialize(null,directMethods,null,stack,quiet);
}
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return result;
}
}

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import java.util.HashSet;
import sun.tools.java.CompilerError;
import sun.tools.java.Identifier;
import sun.tools.java.ClassDefinition;
import java.lang.reflect.Array;
/**
* ArrayType is a wrapper for any of the other types. The getElementType()
* method can be used to get the array element type. The getArrayDimension()
* method can be used to get the array dimension.
*
* @author Bryan Atsatt
*/
public class ArrayType extends Type {
private Type type;
private int arrayDimension;
private String brackets;
private String bracketsSig;
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an ArrayType object for the given type.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static ArrayType forArray( sun.tools.java.Type theType,
ContextStack stack) {
ArrayType result = null;
sun.tools.java.Type arrayType = theType;
if (arrayType.getTypeCode() == TC_ARRAY) {
// Find real type...
while (arrayType.getTypeCode() == TC_ARRAY) {
arrayType = arrayType.getElementType();
}
// Do we already have it?
Type existing = getType(theType,stack);
if (existing != null) {
if (!(existing instanceof ArrayType)) return null; // False hit.
// Yep, so return it...
return (ArrayType) existing;
}
// Now try to make a Type from it...
Type temp = CompoundType.makeType(arrayType,null,stack);
if (temp != null) {
// Got a valid one. Make an array type...
result = new ArrayType(stack,temp,theType.getArrayDimension());
// Add it...
putType(theType,result,stack);
// Do the stack thing in case tracing on...
stack.push(result);
stack.pop(true);
}
}
return result;
}
/**
* Return signature for this type (e.g. com.acme.Dynamite
* would return "com.acme.Dynamite", byte = "B")
*/
public String getSignature() {
return bracketsSig + type.getSignature();
}
/**
* Get element type. Returns null if not an array.
*/
public Type getElementType () {
return type;
}
/**
* Get array dimension. Returns zero if not an array.
*/
public int getArrayDimension () {
return arrayDimension;
}
/**
* Get brackets string. Returns "" if not an array.
*/
public String getArrayBrackets () {
return brackets;
}
/**
* Return a string representation of this type.
*/
public String toString () {
return getQualifiedName() + brackets;
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Array of " + type.getTypeDescription();
}
/**
* Return the name of this type. For arrays, will include "[]" if useIDLNames == false.
* @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
* @param useIDLNames If true, print IDL names; otherwise, print java names.
* @param globalIDLNames If true and useIDLNames true, prepends "::".
*/
public String getTypeName ( boolean useQualifiedNames,
boolean useIDLNames,
boolean globalIDLNames) {
if (useIDLNames) {
return super.getTypeName(useQualifiedNames,useIDLNames,globalIDLNames);
} else {
return super.getTypeName(useQualifiedNames,useIDLNames,globalIDLNames) + brackets;
}
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
/**
* Convert all invalid types to valid ones.
*/
protected void swapInvalidTypes () {
if (type.getStatus() != STATUS_VALID) {
type = getValidType(type);
}
}
/*
* Add matching types to list. Return true if this type has not
* been previously checked, false otherwise.
*/
protected boolean addTypes (int typeCodeFilter,
HashSet checked,
Vector matching) {
// Check self.
boolean result = super.addTypes(typeCodeFilter,checked,matching);
// Have we been checked before?
if (result) {
// No, so add element type...
getElementType().addTypes(typeCodeFilter,checked,matching);
}
return result;
}
/**
* Create an ArrayType instance for the given type. The resulting
* object is not yet completely initialized.
*/
private ArrayType(ContextStack stack, Type type, int arrayDimension) {
super(stack,TYPE_ARRAY);
this.type = type;
this.arrayDimension = arrayDimension;
// Create our brackets string...
brackets = "";
bracketsSig = "";
for (int i = 0; i < arrayDimension; i ++) {
brackets += "[]";
bracketsSig += "[";
}
// Now set our names...
String idlName = IDLNames.getArrayName(type,arrayDimension);
String[] module = IDLNames.getArrayModuleNames(type);
setNames(type.getIdentifier(),module,idlName);
// Set our repositoryID...
setRepositoryID();
}
/*
* Load a Class instance. Return null if fail.
*/
protected Class loadClass() {
Class result = null;
Class elementClass = type.getClassInstance();
if (elementClass != null) {
result = Array.newInstance(elementClass, new int[arrayDimension]).getClass();
}
return result;
}
/**
* Release all resources
*/
protected void destroy () {
super.destroy();
if (type != null) {
type.destroy();
type = null;
}
brackets = null;
bracketsSig = null;
}
}

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.rmi.rmic.Main;
import sun.tools.java.ClassPath;
import java.io.OutputStream;
import sun.tools.java.ClassDefinition;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.Identifier;
import sun.tools.java.ClassNotFound;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Iterator;
/**
* BatchEnvironment for iiop extends rmic's version to add
* parse state.
*/
public class BatchEnvironment extends sun.rmi.rmic.BatchEnvironment implements Constants {
/*
* If the following flag is true, then the IDL generator can map
* the methods and constants of non-conforming types. However,
* this is very expensive, so the default should be false.
*/
private boolean parseNonConforming = false;
/**
* This flag indicates that the stubs and ties need to be generated without
* the package prefix (org.omg.stub).
*/
private boolean standardPackage;
/* Common objects used within package */
HashSet alreadyChecked = new HashSet();
Hashtable allTypes = new Hashtable(3001, 0.5f);
Hashtable invalidTypes = new Hashtable(256, 0.5f);
DirectoryLoader loader = null;
ClassPathLoader classPathLoader = null;
Hashtable nameContexts = null;
Hashtable namesCache = new Hashtable();
NameContext modulesContext = new NameContext(false);
ClassDefinition defRemote = null;
ClassDefinition defError = null;
ClassDefinition defException = null;
ClassDefinition defRemoteException = null;
ClassDefinition defCorbaObject = null;
ClassDefinition defSerializable = null;
ClassDefinition defExternalizable = null;
ClassDefinition defThrowable = null;
ClassDefinition defRuntimeException = null;
ClassDefinition defIDLEntity = null;
ClassDefinition defValueBase = null;
sun.tools.java.Type typeRemoteException = null;
sun.tools.java.Type typeIOException = null;
sun.tools.java.Type typeException = null;
sun.tools.java.Type typeThrowable = null;
ContextStack contextStack = null;
/**
* Create a BatchEnvironment for rmic with the given class path,
* stream for messages and Main.
*/
public BatchEnvironment(OutputStream out, ClassPath path, Main main) {
super(out,path,main);
// Make sure we have our definitions...
try {
defRemote =
getClassDeclaration(idRemote).getClassDefinition(this);
defError =
getClassDeclaration(idJavaLangError).getClassDefinition(this);
defException =
getClassDeclaration(idJavaLangException).getClassDefinition(this);
defRemoteException =
getClassDeclaration(idRemoteException).getClassDefinition(this);
defCorbaObject =
getClassDeclaration(idCorbaObject).getClassDefinition(this);
defSerializable =
getClassDeclaration(idJavaIoSerializable).getClassDefinition(this);
defRuntimeException =
getClassDeclaration(idJavaLangRuntimeException).getClassDefinition(this);
defExternalizable =
getClassDeclaration(idJavaIoExternalizable).getClassDefinition(this);
defThrowable=
getClassDeclaration(idJavaLangThrowable).getClassDefinition(this);
defIDLEntity=
getClassDeclaration(idIDLEntity).getClassDefinition(this);
defValueBase=
getClassDeclaration(idValueBase).getClassDefinition(this);
typeRemoteException = defRemoteException.getClassDeclaration().getType();
typeException = defException.getClassDeclaration().getType();
typeIOException = getClassDeclaration(idJavaIoIOException).getType();
typeThrowable = getClassDeclaration(idJavaLangThrowable).getType();
classPathLoader = new ClassPathLoader(path);
} catch (ClassNotFound e) {
error(0, "rmic.class.not.found", e.name);
throw new Error();
}
}
/**
* Return whether or not to parse non-conforming types.
*/
public boolean getParseNonConforming () {
return parseNonConforming;
}
/**
* Set whether or not to parse non-conforming types.
*/
public void setParseNonConforming (boolean parseEm) {
// If we are transitioning from not parsing to
// parsing, we need to throw out any previously
// parsed types...
if (parseEm && !parseNonConforming) {
reset();
}
parseNonConforming = parseEm;
}
void setStandardPackage(boolean standardPackage) {
this.standardPackage = standardPackage;
}
boolean getStandardPackage() {
return standardPackage;
}
/**
* Clear out any data from previous executions.
*/
public void reset () {
// First, find all Type instances and call destroy()
// on them...
for (Enumeration e = allTypes.elements() ; e.hasMoreElements() ;) {
Type type = (Type) e.nextElement();
type.destroy();
}
for (Enumeration e = invalidTypes.keys() ; e.hasMoreElements() ;) {
Type type = (Type) e.nextElement();
type.destroy();
}
for (Iterator e = alreadyChecked.iterator() ; e.hasNext() ;) {
Type type = (Type) e.next();
type.destroy();
}
if (contextStack != null) contextStack.clear();
// Remove and clear all NameContexts in the
// nameContexts cache...
if (nameContexts != null) {
for (Enumeration e = nameContexts.elements() ; e.hasMoreElements() ;) {
NameContext context = (NameContext) e.nextElement();
context.clear();
}
nameContexts.clear();
}
// Now remove all table entries...
allTypes.clear();
invalidTypes.clear();
alreadyChecked.clear();
namesCache.clear();
modulesContext.clear();
// Clean up remaining...
loader = null;
parseNonConforming = false;
// REVISIT - can't clean up classPathLoader here
}
/**
* Release resources, if any.
*/
public void shutdown() {
if (alreadyChecked != null) {
//System.out.println();
//System.out.println("allTypes.size() = "+ allTypes.size());
//System.out.println(" InstanceCount before reset = "+Type.instanceCount);
reset();
//System.out.println(" InstanceCount AFTER reset = "+Type.instanceCount);
alreadyChecked = null;
allTypes = null;
invalidTypes = null;
nameContexts = null;
namesCache = null;
modulesContext = null;
defRemote = null;
defError = null;
defException = null;
defRemoteException = null;
defCorbaObject = null;
defSerializable = null;
defExternalizable = null;
defThrowable = null;
defRuntimeException = null;
defIDLEntity = null;
defValueBase = null;
typeRemoteException = null;
typeIOException = null;
typeException = null;
typeThrowable = null;
super.shutdown();
}
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2000, 2004, 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.
*/
package sun.rmi.rmic.iiop;
import java.io.*;
import sun.tools.java.ClassPath ;
import sun.tools.java.ClassFile ;
/**
* A ClassLoader that will ultimately use a given sun.tools.java.ClassPath to
* find the desired file. This works for any JAR files specified in the given
* ClassPath as well -- reusing all of that wonderful sun.tools.java code.
*
*@author Everett Anderson
*/
public class ClassPathLoader extends ClassLoader
{
private ClassPath classPath;
public ClassPathLoader(ClassPath classPath) {
this.classPath = classPath;
}
// Called by the super class
protected Class findClass(String name) throws ClassNotFoundException
{
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
/**
* Load the class with the given fully qualified name from the ClassPath.
*/
private byte[] loadClassData(String className)
throws ClassNotFoundException
{
// Build the file name and subdirectory from the
// class name
String filename = className.replace('.', File.separatorChar)
+ ".class";
// Have ClassPath find the file for us, and wrap it in a
// ClassFile. Note: This is where it looks inside jar files that
// are specified in the path.
ClassFile classFile = classPath.getFile(filename);
if (classFile != null) {
// Provide the most specific reason for failure in addition
// to ClassNotFound
Exception reportedError = null;
byte data[] = null;
try {
// ClassFile is beautiful because it shields us from
// knowing if it's a separate file or an entry in a
// jar file.
DataInputStream input
= new DataInputStream(classFile.getInputStream());
// Can't rely on input available() since it will be
// something unusual if it's a jar file! May need
// to worry about a possible problem if someone
// makes a jar file entry with a size greater than
// max int.
data = new byte[(int)classFile.length()];
try {
input.readFully(data);
} catch (IOException ex) {
// Something actually went wrong reading the file. This
// is a real error so save it to report it.
data = null;
reportedError = ex;
} finally {
// Just don't care if there's an exception on close!
// I hate that close can throw an IOException!
try { input.close(); } catch (IOException ex) {}
}
} catch (IOException ex) {
// Couldn't get the input stream for the file. This is
// probably also a real error.
reportedError = ex;
}
if (data == null)
throw new ClassNotFoundException(className, reportedError);
return data;
}
// Couldn't find the file in the class path.
throw new ClassNotFoundException(className);
}
}

View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.ClassDefinition;
import sun.rmi.rmic.IndentingWriter;
import java.io.IOException;
/**
* ClassType is an abstract base representing any non-special class
* type.
*
* @author Bryan Atsatt
*/
public abstract class ClassType extends CompoundType {
private ClassType parent;
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Return the parent class of this type. Returns null if this
* type is an interface or if there is no parent.
*/
public ClassType getSuperclass() {
return parent;
}
/**
* Print this type.
* @param writer The stream to print to.
* @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
* @param useIDLNames If true, print IDL names; otherwise, print java names.
* @param globalIDLNames If true and useIDLNames true, prepends "::".
*/
public void print ( IndentingWriter writer,
boolean useQualifiedNames,
boolean useIDLNames,
boolean globalIDLNames) throws IOException {
if (isInner()) {
writer.p("// " + getTypeDescription() + " (INNER)");
} else {
writer.p("// " + getTypeDescription());
}
writer.pln(" (" + getRepositoryID() + ")\n");
printPackageOpen(writer,useIDLNames);
if (!useIDLNames) {
writer.p("public ");
}
String prefix = "";
writer.p("class " + getTypeName(false,useIDLNames,false));
if (printExtends(writer,useQualifiedNames,useIDLNames,globalIDLNames)) {
prefix = ",";
}
printImplements(writer,prefix,useQualifiedNames,useIDLNames,globalIDLNames);
writer.plnI(" {");
printMembers(writer,useQualifiedNames,useIDLNames,globalIDLNames);
writer.pln();
printMethods(writer,useQualifiedNames,useIDLNames,globalIDLNames);
if (useIDLNames) {
writer.pOln("};");
} else {
writer.pOln("}");
}
printPackageClose(writer,useIDLNames);
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
protected void destroy () {
if (!destroyed) {
super.destroy();
if (parent != null) {
parent.destroy();
parent = null;
}
}
}
/**
* Create a ClassType instance for the given class. NOTE: This constructor
* is ONLY for SpecialClassType.
*/
protected ClassType(ContextStack stack, int typeCode, ClassDefinition classDef) {
super(stack,typeCode,classDef); // Call special parent constructor.
if ((typeCode & TM_CLASS) == 0 && classDef.isInterface()) {
throw new CompilerError("Not a class");
}
parent = null;
}
/**
* Create a ClassType instance for the given class. NOTE: This constructor
* is ONLY for ImplementationType. It does not walk the parent chain.
*/
protected ClassType(int typeCode, ClassDefinition classDef,ContextStack stack) {
super(stack,classDef,typeCode);
if ((typeCode & TM_CLASS) == 0 && classDef.isInterface()) {
throw new CompilerError("Not a class");
}
parent = null;
}
/**
* Create an ClassType instance for the given class. The resulting
* object is not yet completely initialized. Subclasses must call
* initialize(directInterfaces,directInterfaces,directConstants);
*/
protected ClassType(ContextStack stack,
ClassDefinition classDef,
int typeCode) {
super(stack,classDef,typeCode);
if ((typeCode & TM_CLASS) == 0 && classDef.isInterface()) {
throw new CompilerError("Not a class");
}
parent = null;
}
/**
* Convert all invalid types to valid ones.
*/
protected void swapInvalidTypes () {
super.swapInvalidTypes();
if (parent != null && parent.getStatus() != STATUS_VALID) {
parent = (ClassType) getValidType(parent);
}
}
/**
* Modify the type description with exception info.
*/
public String addExceptionDescription (String typeDesc) {
if (isException) {
if (isCheckedException) {
typeDesc = typeDesc + " - Checked Exception";
} else {
typeDesc = typeDesc + " - Unchecked Exception";
}
}
return typeDesc;
}
protected boolean initParents(ContextStack stack) {
stack.setNewContextCode(ContextStack.EXTENDS);
BatchEnvironment env = stack.getEnv();
// Init parent...
boolean result = true;
try {
ClassDeclaration parentDecl = getClassDefinition().getSuperClass(env);
if (parentDecl != null) {
ClassDefinition parentDef = parentDecl.getClassDefinition(env);
parent = (ClassType) makeType(parentDef.getType(),parentDef,stack);
if (parent == null) {
result = false;
}
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
throw new CompilerError("ClassType constructor");
}
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,297 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.tools.java.Identifier;
public interface Constants extends sun.rmi.rmic.Constants {
// Identifiers for referenced classes:
public static final Identifier idReplyHandler =
Identifier.lookup("org.omg.CORBA.portable.ResponseHandler");
public static final Identifier idStubBase =
Identifier.lookup("javax.rmi.CORBA.Stub");
public static final Identifier idTieBase =
Identifier.lookup("org.omg.CORBA.portable.ObjectImpl");
public static final Identifier idTieInterface =
Identifier.lookup("javax.rmi.CORBA.Tie");
public static final Identifier idPOAServantType =
Identifier.lookup( "org.omg.PortableServer.Servant" ) ;
public static final Identifier idDelegate =
Identifier.lookup("org.omg.CORBA.portable.Delegate");
public static final Identifier idOutputStream =
Identifier.lookup("org.omg.CORBA.portable.OutputStream");
public static final Identifier idExtOutputStream =
Identifier.lookup("org.omg.CORBA_2_3.portable.OutputStream");
public static final Identifier idInputStream =
Identifier.lookup("org.omg.CORBA.portable.InputStream");
public static final Identifier idExtInputStream =
Identifier.lookup("org.omg.CORBA_2_3.portable.InputStream");
public static final Identifier idSystemException =
Identifier.lookup("org.omg.CORBA.SystemException");
public static final Identifier idBadMethodException =
Identifier.lookup("org.omg.CORBA.BAD_OPERATION");
public static final Identifier idPortableUnknownException =
Identifier.lookup("org.omg.CORBA.portable.UnknownException");
public static final Identifier idApplicationException =
Identifier.lookup("org.omg.CORBA.portable.ApplicationException");
public static final Identifier idRemarshalException =
Identifier.lookup("org.omg.CORBA.portable.RemarshalException");
public static final Identifier idJavaIoExternalizable =
Identifier.lookup("java.io.Externalizable");
public static final Identifier idCorbaObject =
Identifier.lookup("org.omg.CORBA.Object");
public static final Identifier idCorbaORB =
Identifier.lookup("org.omg.CORBA.ORB");
public static final Identifier idClassDesc =
Identifier.lookup("javax.rmi.CORBA.ClassDesc");
public static final Identifier idJavaIoIOException =
Identifier.lookup("java.io.IOException");
public static final Identifier idIDLEntity =
Identifier.lookup("org.omg.CORBA.portable.IDLEntity");
public static final Identifier idValueBase =
Identifier.lookup("org.omg.CORBA.portable.ValueBase");
public static final Identifier idBoxedRMI =
Identifier.lookup("org.omg.boxedRMI");
public static final Identifier idBoxedIDL =
Identifier.lookup("org.omg.boxedIDL");
public static final Identifier idCorbaUserException =
Identifier.lookup("org.omg.CORBA.UserException");
// Identifiers for primitive types:
public static final Identifier idBoolean =
Identifier.lookup("boolean");
public static final Identifier idByte =
Identifier.lookup("byte");
public static final Identifier idChar =
Identifier.lookup("char");
public static final Identifier idShort =
Identifier.lookup("short");
public static final Identifier idInt =
Identifier.lookup("int");
public static final Identifier idLong =
Identifier.lookup("long");
public static final Identifier idFloat =
Identifier.lookup("float");
public static final Identifier idDouble =
Identifier.lookup("double");
public static final Identifier idVoid =
Identifier.lookup("void");
// IndentingWriter constructor args:
public static final int INDENT_STEP = 4;
public static final int TAB_SIZE = Integer.MAX_VALUE; // No tabs.
// Type status codes:
public static final int STATUS_PENDING = 0;
public static final int STATUS_VALID = 1;
public static final int STATUS_INVALID = 2;
// Java Names:
public static final String NAME_SEPARATOR = ".";
public static final String SERIAL_VERSION_UID = "serialVersionUID";
// IDL Names:
public static final String[] IDL_KEYWORDS = {
"abstract",
"any",
"attribute",
"boolean",
"case",
"char",
"const",
"context",
"custom",
"default",
"double",
"enum",
"exception",
"factory",
"FALSE",
"fixed",
"float",
"in",
"inout",
"interface",
"long",
"module",
"native",
"Object",
"octet",
"oneway",
"out",
"private",
"public",
"raises",
"readonly",
"sequence",
"short",
"string",
"struct",
"supports",
"switch",
"TRUE",
"truncatable",
"typedef",
"unsigned",
"union",
"ValueBase",
"valuetype",
"void",
"wchar",
"wstring",
};
public static final String EXCEPTION_SUFFIX = "Exception";
public static final String ERROR_SUFFIX = "Error";
public static final String EX_SUFFIX = "Ex";
public static final String IDL_REPOSITORY_ID_PREFIX = "IDL:";
public static final String IDL_REPOSITORY_ID_VERSION = ":1.0";
public static final String[] IDL_CORBA_MODULE = {"CORBA"};
public static final String[] IDL_SEQUENCE_MODULE = {"org","omg","boxedRMI"};
public static final String[] IDL_BOXEDIDL_MODULE = {"org","omg","boxedIDL"};
public static final String IDL_CLASS = "ClassDesc";
public static final String[] IDL_CLASS_MODULE = {"javax","rmi","CORBA"};
public static final String IDL_IDLENTITY = "IDLEntity";
public static final String IDL_SERIALIZABLE = "Serializable";
public static final String IDL_EXTERNALIZABLE = "Externalizable";
public static final String[] IDL_JAVA_IO_MODULE = {"java","io"};
public static final String[] IDL_ORG_OMG_CORBA_MODULE = {"org","omg","CORBA"};
public static final String[] IDL_ORG_OMG_CORBA_PORTABLE_MODULE = {"org","omg","CORBA","portable"};
public static final String IDL_JAVA_LANG_OBJECT = "_Object";
public static final String[] IDL_JAVA_LANG_MODULE = {"java","lang"};
public static final String IDL_JAVA_RMI_REMOTE = "Remote";
public static final String[] IDL_JAVA_RMI_MODULE = {"java","rmi"};
public static final String IDL_SEQUENCE = "seq";
public static final String IDL_CONSTRUCTOR = "create";
public static final String IDL_NAME_SEPARATOR = "::";
public static final String IDL_BOOLEAN = "boolean";
public static final String IDL_BYTE = "octet";
public static final String IDL_CHAR = "wchar";
public static final String IDL_SHORT = "short";
public static final String IDL_INT = "long";
public static final String IDL_LONG = "long long";
public static final String IDL_FLOAT = "float";
public static final String IDL_DOUBLE = "double";
public static final String IDL_VOID = "void";
public static final String IDL_STRING = "WStringValue";
public static final String IDL_CONSTANT_STRING = "wstring";
public static final String IDL_CORBA_OBJECT = "Object";
public static final String IDL_ANY = "any";
// File names:
public static final String SOURCE_FILE_EXTENSION = ".java";
public static final String IDL_FILE_EXTENSION = ".idl";
// Type Codes:
public static final int TYPE_VOID = 0x00000001; // In PrimitiveType
public static final int TYPE_BOOLEAN = 0x00000002; // In PrimitiveType
public static final int TYPE_BYTE = 0x00000004; // In PrimitiveType
public static final int TYPE_CHAR = 0x00000008; // In PrimitiveType
public static final int TYPE_SHORT = 0x00000010; // In PrimitiveType
public static final int TYPE_INT = 0x00000020; // In PrimitiveType
public static final int TYPE_LONG = 0x00000040; // In PrimitiveType
public static final int TYPE_FLOAT = 0x00000080; // In PrimitiveType
public static final int TYPE_DOUBLE = 0x00000100; // In PrimitiveType
public static final int TYPE_STRING = 0x00000200; // In SpecialClassType (String)
public static final int TYPE_ANY = 0x00000400; // In SpecialInterfaceType (Serializable,Externalizable)
public static final int TYPE_CORBA_OBJECT = 0x00000800; // In SpecialInterfaceType (CORBA.Object,Remote)
public static final int TYPE_REMOTE = 0x00001000; // In RemoteType
public static final int TYPE_ABSTRACT = 0x00002000; // In AbstractType
public static final int TYPE_NC_INTERFACE = 0x00004000; // In NCInterfaceType
public static final int TYPE_VALUE = 0x00008000; // In ValueType
public static final int TYPE_IMPLEMENTATION = 0x00010000; // In ImplementationType
public static final int TYPE_NC_CLASS = 0x00020000; // In NCClassType
public static final int TYPE_ARRAY = 0x00040000; // In ArrayType
public static final int TYPE_JAVA_RMI_REMOTE = 0x00080000; // In SpecialInterfaceType
// Type code masks:
public static final int TYPE_NONE = 0x00000000;
public static final int TYPE_ALL = 0xFFFFFFFF;
public static final int TYPE_MASK = 0x00FFFFFF;
public static final int TM_MASK = 0xFF000000;
// Type code modifiers:
public static final int TM_PRIMITIVE = 0x01000000;
public static final int TM_COMPOUND = 0x02000000;
public static final int TM_CLASS = 0x04000000;
public static final int TM_INTERFACE = 0x08000000;
public static final int TM_SPECIAL_CLASS = 0x10000000;
public static final int TM_SPECIAL_INTERFACE= 0x20000000;
public static final int TM_NON_CONFORMING = 0x40000000;
public static final int TM_INNER = 0x80000000;
// Attribute kinds...
public static final int ATTRIBUTE_NONE = 0; // Not an attribute.
public static final int ATTRIBUTE_IS = 1; // read-only, had "is" prefix.
public static final int ATTRIBUTE_GET = 2; // read-only, had "get" prefix.
public static final int ATTRIBUTE_IS_RW = 3; // read-write, had "is" prefix.
public static final int ATTRIBUTE_GET_RW = 4; // read-write, had "get" prefix.
public static final int ATTRIBUTE_SET = 5; // had "set" prefix.
public static final String[] ATTRIBUTE_WIRE_PREFIX = {
"",
"_get_",
"_get_",
"_get_",
"_get_",
"_set_",
};
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
/**
* ContextElement provides a common interface for elements of a ContextStack.
* @author Bryan Atsatt
*/
public interface ContextElement {
public String getElementName();
}

View File

@@ -0,0 +1,447 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.tools.java.CompilerError;
/**
* ContextStack provides a mechanism to record parsing state.
*
* @author Bryan Atsatt
*/
public class ContextStack {
// Context codes.
public static final int TOP = 1;
public static final int METHOD = 2;
public static final int METHOD_RETURN = 3;
public static final int METHOD_ARGUMENT = 4;
public static final int METHOD_EXCEPTION = 5;
public static final int MEMBER = 6;
public static final int MEMBER_CONSTANT = 7;
public static final int MEMBER_STATIC = 8;
public static final int MEMBER_TRANSIENT = 9;
public static final int IMPLEMENTS = 10;
public static final int EXTENDS = 11;
// String versions of context codes.
private static final String[] CODE_NAMES = {
"UNKNOWN ",
"Top level type ",
"Method ",
"Return parameter ",
"Parameter ",
"Exception ",
"Member ",
"Constant member ",
"Static member ",
"Transient member ",
"Implements ",
"Extends ",
};
// Member data.
private int currentIndex = -1;
private int maxIndex = 100;
private TypeContext[] stack = new TypeContext[maxIndex];
private int newCode = TOP;
private BatchEnvironment env = null;
private boolean trace = false;
private TypeContext tempContext = new TypeContext();
private static final String TRACE_INDENT = " ";
/**
* Constructor.
*/
public ContextStack (BatchEnvironment env) {
this.env = env;
env.contextStack = this;
}
/**
* Return true if env.nerrors > 0.
*/
public boolean anyErrors () {
return env.nerrors > 0;
}
/**
* Enable/disable tracing.
*/
public void setTrace(boolean trace) {
this.trace = trace;
}
/**
* Check trace flag.
*/
public boolean isTraceOn() {
return trace;
}
/**
* Get the environment.
*/
public BatchEnvironment getEnv() {
return env;
}
/**
* Set the new context.
*/
public void setNewContextCode(int code) {
newCode = code;
}
/**
* Get the current context code.
*/
public int getCurrentContextCode() {
return newCode;
}
/**
* If tracing on, write the current call stack (not the context stack) to
* System.out.
*/
final void traceCallStack () {
if (trace) dumpCallStack();
}
public final static void dumpCallStack() {
new Error().printStackTrace(System.out);
}
/**
* Print a line indented by stack depth.
*/
final private void tracePrint (String text, boolean line) {
int length = text.length() + (currentIndex * TRACE_INDENT.length());
StringBuffer buffer = new StringBuffer(length);
for (int i = 0; i < currentIndex; i++) {
buffer.append(TRACE_INDENT);
}
buffer.append(text);
if (line) {
buffer.append("\n");
}
System.out.print(buffer.toString());
}
/**
* If tracing on, print a line.
*/
final void trace (String text) {
if (trace) {
tracePrint(text,false);
}
}
/**
* If tracing on, print a line followed by a '\n'.
*/
final void traceln (String text) {
if (trace) {
tracePrint(text,true);
}
}
/**
* If tracing on, print a pre-mapped ContextElement.
*/
final void traceExistingType (Type type) {
if (trace) {
tempContext.set(newCode,type);
traceln(toResultString(tempContext,true,true));
}
}
/**
* Push a new element on the stack.
* @return the new element.
*/
public TypeContext push (ContextElement element) {
currentIndex++;
// Grow array if need to...
if (currentIndex == maxIndex) {
int newMax = maxIndex * 2;
TypeContext[] newStack = new TypeContext[newMax];
System.arraycopy(stack,0,newStack,0,maxIndex);
maxIndex = newMax;
stack = newStack;
}
// Make sure we have a context object to use at this position...
TypeContext it = stack[currentIndex];
if (it == null) {
it = new TypeContext();
stack[currentIndex] = it;
}
// Set the context object...
it.set(newCode,element);
// Trace...
traceln(toTrialString(it));
// Return...
return it;
}
/**
* Pop an element from the stack.
* @return the new current element or null if top.
*/
public TypeContext pop (boolean wasValid) {
if (currentIndex < 0) {
throw new CompilerError("Nothing on stack!");
}
newCode = stack[currentIndex].getCode();
traceln(toResultString(stack[currentIndex],wasValid,false));
Type last = stack[currentIndex].getCandidateType();
if (last != null) {
// Set status...
if (wasValid) {
last.setStatus(Constants.STATUS_VALID);
} else {
last.setStatus(Constants.STATUS_INVALID);
}
}
currentIndex--;
if (currentIndex < 0) {
// Done parsing, so update the invalid types
// if this type was valid...
if (wasValid) {
Type.updateAllInvalidTypes(this);
}
return null;
} else {
return stack[currentIndex];
}
}
/**
* Get the current size.
*/
public int size () {
return currentIndex + 1;
}
/**
* Get a specific context.
*/
public TypeContext getContext (int index) {
if (currentIndex < index) {
throw new Error("Index out of range");
}
return stack[index];
}
/**
* Get the current top context.
*/
public TypeContext getContext () {
if (currentIndex < 0) {
throw new Error("Nothing on stack!");
}
return stack[currentIndex];
}
/**
* Is parent context a value type?
*/
public boolean isParentAValue () {
if (currentIndex > 0) {
return stack[currentIndex - 1].isValue();
} else {
return false;
}
}
/**
* Get parent context. Null if none.
*/
public TypeContext getParentContext () {
if (currentIndex > 0) {
return stack[currentIndex - 1];
} else {
return null;
}
}
/**
* Get a string for the context name...
*/
public String getContextCodeString () {
if (currentIndex >= 0) {
return CODE_NAMES[newCode];
} else {
return CODE_NAMES[0];
}
}
/**
* Get a string for the given context code...
*/
public static String getContextCodeString (int contextCode) {
return CODE_NAMES[contextCode];
}
private String toTrialString(TypeContext it) {
int code = it.getCode();
if (code != METHOD && code != MEMBER) {
return it.toString() + " (trying " + it.getTypeDescription() + ")";
} else {
return it.toString();
}
}
private String toResultString (TypeContext it, boolean result, boolean preExisting) {
int code = it.getCode();
if (code != METHOD && code != MEMBER) {
if (result) {
String str = it.toString() + " --> " + it.getTypeDescription();
if (preExisting) {
return str + " [Previously mapped]";
} else {
return str;
}
}
} else {
if (result) {
return it.toString() + " --> [Mapped]";
}
}
return it.toString() + " [Did not map]";
}
public void clear () {
for (int i = 0; i < stack.length; i++) {
if (stack[i] != null) stack[i].destroy();
}
}
}
class TypeContext {
public void set(int code, ContextElement element) {
this.code = code;
this.element = element;
if (element instanceof ValueType) {
isValue = true;
} else {
isValue = false;
}
}
public int getCode() {
return code;
}
public String getName() {
return element.getElementName();
}
public Type getCandidateType() {
if (element instanceof Type) {
return (Type) element;
} else {
return null;
}
}
public String getTypeDescription() {
if (element instanceof Type) {
return ((Type) element).getTypeDescription();
} else {
return "[unknown type]";
}
}
public String toString () {
if (element != null) {
return ContextStack.getContextCodeString(code) + element.getElementName();
} else {
return ContextStack.getContextCodeString(code) + "null";
}
}
public boolean isValue () {
return isValue;
}
public boolean isConstant () {
return code == ContextStack.MEMBER_CONSTANT;
}
public void destroy() {
if (element instanceof Type) {
((Type)element).destroy();
}
element = null;
}
private int code = 0;
private ContextElement element = null;
private boolean isValue = false;
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Hashtable;
import java.io.File;
import java.io.FileInputStream;
/**
* DirectoryLoader is a simple ClassLoader which loads from a specified
* file system directory.
* @author Bryan Atsatt
*/
public class DirectoryLoader extends ClassLoader {
private Hashtable cache;
private File root;
/**
* Constructor.
*/
public DirectoryLoader (File rootDir) {
cache = new Hashtable();
if (rootDir == null || !rootDir.isDirectory()) {
throw new IllegalArgumentException();
}
root = rootDir;
}
private DirectoryLoader () {}
/**
* Convenience version of loadClass which sets 'resolve' == true.
*/
public Class loadClass(String className) throws ClassNotFoundException {
return loadClass(className, true);
}
/**
* This is the required version of loadClass which is called
* both from loadClass above and from the internal function
* FindClassFromClass.
*/
public synchronized Class loadClass(String className, boolean resolve)
throws ClassNotFoundException {
Class result;
byte classData[];
// Do we already have it in the cache?
result = (Class) cache.get(className);
if (result == null) {
// Nope, can we get if from the system class loader?
try {
result = super.findSystemClass(className);
} catch (ClassNotFoundException e) {
// No, so try loading it...
classData = getClassFileData(className);
if (classData == null) {
throw new ClassNotFoundException();
}
// Parse the class file data...
result = defineClass(classData, 0, classData.length);
if (result == null) {
throw new ClassFormatError();
}
// Resolve it...
if (resolve) resolveClass(result);
// Add to cache...
cache.put(className, result);
}
}
return result;
}
/**
* Reurn a byte array containing the contents of the class file. Returns null
* if an exception occurs.
*/
private byte[] getClassFileData (String className) {
byte result[] = null;
FileInputStream stream = null;
// Get the file...
File classFile = new File(root,className.replace('.',File.separatorChar) + ".class");
// Now get the bits...
try {
stream = new FileInputStream(classFile);
result = new byte[stream.available()];
stream.read(result);
} catch(ThreadDeath death) {
throw death;
} catch (Throwable e) {
}
finally {
if (stream != null) {
try {
stream.close();
} catch(ThreadDeath death) {
throw death;
} catch (Throwable e) {
}
}
}
return result;
}
}

View File

@@ -0,0 +1,436 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import sun.tools.java.Identifier;
import sun.tools.java.ClassPath;
import sun.tools.java.ClassFile;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDefinition;
import sun.tools.java.ClassDeclaration;
import sun.rmi.rmic.IndentingWriter;
import sun.rmi.rmic.Main;
import sun.rmi.rmic.iiop.Util;
import java.util.HashSet;
/**
* Generator provides a small framework from which IIOP-specific
* generators can inherit. Common logic is implemented here which uses
* both abstract methods as well as concrete methods which subclasses may
* want to override. The following methods must be present in any subclass:
* <pre>
* Default constructor
* CompoundType getTopType(BatchEnvironment env, ClassDefinition cdef);
* int parseArgs(String argv[], int currentIndex);
* boolean requireNewInstance();
* OutputType[] getOutputTypesFor(CompoundType topType,
* HashSet alreadyChecked);
* String getFileNameExtensionFor(OutputType outputType);
* void writeOutputFor ( OutputType outputType,
* HashSet alreadyChecked,
* IndentingWriter writer) throws IOException;
* </pre>
* @author Bryan Atsatt
*/
public abstract class Generator implements sun.rmi.rmic.Generator,
sun.rmi.rmic.iiop.Constants {
protected boolean alwaysGenerate = false;
protected BatchEnvironment env = null;
protected ContextStack contextStack = null;
private boolean trace = false;
protected boolean idl = false;
/**
* Examine and consume command line arguments.
* @param argv The command line arguments. Ignore null
* and unknown arguments. Set each consumed argument to null.
* @param error Report any errors using the main.error() methods.
* @return true if no errors, false otherwise.
*/
public boolean parseArgs(String argv[], Main main) {
for (int i = 0; i < argv.length; i++) {
if (argv[i] != null) {
if (argv[i].equalsIgnoreCase("-always") ||
argv[i].equalsIgnoreCase("-alwaysGenerate")) {
alwaysGenerate = true;
argv[i] = null;
} else if (argv[i].equalsIgnoreCase("-xtrace")) {
trace = true;
argv[i] = null;
}
}
}
return true;
}
/**
* Return true if non-conforming types should be parsed.
* @param stack The context stack.
*/
protected abstract boolean parseNonConforming(ContextStack stack);
/**
* Create and return a top-level type.
* @param cdef The top-level class definition.
* @param stack The context stack.
* @return The compound type or null if is non-conforming.
*/
protected abstract CompoundType getTopType(ClassDefinition cdef, ContextStack stack);
/**
* Return an array containing all the file names and types that need to be
* generated for the given top-level type. The file names must NOT have an
* extension (e.g. ".java").
* @param topType The type returned by getTopType().
* @param alreadyChecked A set of Types which have already been checked.
* Intended to be passed to Type.collectMatching(filter,alreadyChecked).
*/
protected abstract OutputType[] getOutputTypesFor(CompoundType topType,
HashSet alreadyChecked);
/**
* Return the file name extension for the given file name (e.g. ".java").
* All files generated with the ".java" extension will be compiled. To
* change this behavior for ".java" files, override the compileJavaSourceFile
* method to return false.
* @param outputType One of the items returned by getOutputTypesFor(...)
*/
protected abstract String getFileNameExtensionFor(OutputType outputType);
/**
* Write the output for the given OutputFileName into the output stream.
* @param name One of the items returned by getOutputTypesFor(...)
* @param alreadyChecked A set of Types which have already been checked.
* Intended to be passed to Type.collectMatching(filter,alreadyChecked).
* @param writer The output stream.
*/
protected abstract void writeOutputFor(OutputType outputType,
HashSet alreadyChecked,
IndentingWriter writer) throws IOException;
/**
* Return true if a new instance should be created for each
* class on the command line. Subclasses which return true
* should override newInstance() to return an appropriately
* constructed instance.
*/
protected abstract boolean requireNewInstance();
/**
* Return true if the specified file needs generation.
*/
public boolean requiresGeneration (File target, Type theType) {
boolean result = alwaysGenerate;
if (!result) {
// Get a ClassFile instance for base source or class
// file. We use ClassFile so that if the base is in
// a zip file, we can still get at it's mod time...
ClassFile baseFile;
ClassPath path = env.getClassPath();
String className = theType.getQualifiedName().replace('.',File.separatorChar);
// First try the source file...
baseFile = path.getFile(className + ".source");
if (baseFile == null) {
// Then try class file...
baseFile = path.getFile(className + ".class");
}
// Do we have a baseFile?
if (baseFile != null) {
// Yes, grab baseFile's mod time...
long baseFileMod = baseFile.lastModified();
// Get a File instance for the target. If it is a source
// file, create a class file instead since the source file
// will frequently be deleted...
String targetName = IDLNames.replace(target.getName(),".java",".class");
String parentPath = target.getParent();
File targetFile = new File(parentPath,targetName);
// Does the target file exist?
if (targetFile.exists()) {
// Yes, so grab it's mod time...
long targetFileMod = targetFile.lastModified();
// Set result...
result = targetFileMod < baseFileMod;
} else {
// No, so we must generate...
result = true;
}
} else {
// No, so we must generate...
result = true;
}
}
return result;
}
/**
* Create and return a new instance of self. Subclasses
* which need to do something other than default construction
* must override this method.
*/
protected Generator newInstance() {
Generator result = null;
try {
result = (Generator) getClass().newInstance();
}
catch (Exception e){} // Should ALWAYS work!
return result;
}
/**
* Default constructor for subclasses to use.
*/
protected Generator() {
}
/**
* Generate output. Any source files created which need compilation should
* be added to the compiler environment using the addGeneratedFile(File)
* method.
*
* @param env The compiler environment
* @param cdef The definition for the implementation class or interface from
* which to generate output
* @param destDir The directory for the root of the package hierarchy
* for generated files. May be null.
*/
public void generate(sun.rmi.rmic.BatchEnvironment env, ClassDefinition cdef, File destDir) {
this.env = (BatchEnvironment) env;
contextStack = new ContextStack(this.env);
contextStack.setTrace(trace);
// Make sure the environment knows whether or not to parse
// non-conforming types. This will clear out any previously
// parsed types if necessary...
this.env.setParseNonConforming(parseNonConforming(contextStack));
// Get our top level type...
CompoundType topType = getTopType(cdef,contextStack);
if (topType != null) {
Generator generator = this;
// Do we need to make a new instance?
if (requireNewInstance()) {
// Yes, so make one. 'this' instance is the one instantiated by Main
// and which knows any needed command line args...
generator = newInstance();
}
// Now generate all output files...
generator.generateOutputFiles(topType, this.env, destDir);
}
}
/**
* Create and return a new instance of self. Subclasses
* which need to do something other than default construction
* must override this method.
*/
protected void generateOutputFiles (CompoundType topType,
BatchEnvironment env,
File destDir) {
// Grab the 'alreadyChecked' HashSet from the environment...
HashSet alreadyChecked = env.alreadyChecked;
// Ask subclass for a list of output types...
OutputType[] types = getOutputTypesFor(topType,alreadyChecked);
// Process each file...
for (int i = 0; i < types.length; i++) {
OutputType current = types[i];
String className = current.getName();
File file = getFileFor(current,destDir);
boolean sourceFile = false;
// Do we need to generate this file?
if (requiresGeneration(file,current.getType())) {
// Yes. If java source file, add to environment so will be compiled...
if (file.getName().endsWith(".java")) {
sourceFile = compileJavaSourceFile(current);
// Are we supposeded to compile this one?
if (sourceFile) {
env.addGeneratedFile(file);
}
}
// Now create an output stream and ask subclass to fill it up...
try {
IndentingWriter out = new IndentingWriter(
new OutputStreamWriter(new FileOutputStream(file)),INDENT_STEP,TAB_SIZE);
long startTime = 0;
if (env.verbose()) {
startTime = System.currentTimeMillis();
}
writeOutputFor(types[i],alreadyChecked,out);
out.close();
if (env.verbose()) {
long duration = System.currentTimeMillis() - startTime;
env.output(Main.getText("rmic.generated", file.getPath(), Long.toString(duration)));
}
if (sourceFile) {
env.parseFile(new ClassFile(file));
}
} catch (IOException e) {
env.error(0, "cant.write", file.toString());
return;
}
} else {
// No, say so if we need to...
if (env.verbose()) {
env.output(Main.getText("rmic.previously.generated", file.getPath()));
}
}
}
}
/**
* Return the File object that should be used as the output file
* for the given OutputType.
* @param outputType The type to create a file for.
* @param destinationDir The directory to use as the root of the
* package heirarchy. May be null, in which case the current
* classpath is searched to find the directory in which to create
* the output file. If that search fails (most likely because the
* package directory lives in a zip or jar file rather than the
* file system), the current user directory is used.
*/
protected File getFileFor(OutputType outputType, File destinationDir) {
// Calling this method does some crucial initialization
// in a subclass implementation. Don't skip it.
Identifier id = getOutputId(outputType);
File packageDir = null;
if(idl){
packageDir = Util.getOutputDirectoryForIDL(id,destinationDir,env);
} else {
packageDir = Util.getOutputDirectoryForStub(id,destinationDir,env);
}
String classFileName = outputType.getName() + getFileNameExtensionFor(outputType);
return new File(packageDir, classFileName);
}
/**
* Return an identifier to use for output.
* @param outputType the type for which output is to be generated.
* @return the new identifier. This implementation returns the input parameter.
*/
protected Identifier getOutputId (OutputType outputType) {
return outputType.getType().getIdentifier();
}
/**
* Return true if the given file should be compiled.
* @param outputType One of the items returned by getOutputTypesFor(...) for
* which getFileNameExtensionFor(OutputType) returned ".java".
*/
protected boolean compileJavaSourceFile (OutputType outputType) {
return true;
}
//_____________________________________________________________________
// OutputType is a simple wrapper for a name and a Type
//_____________________________________________________________________
public class OutputType {
private String name;
private Type type;
public OutputType (String name, Type type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public Type getType() {
return type;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDefinition;
import sun.tools.java.MemberDefinition;
/**
* ImplementationType represents any non-special class which implements
* one or more interfaces which inherit from java.rmi.Remote.
* <p>
* The static forImplementation(...) method must be used to obtain an instance,
* and will return null if the ClassDefinition is non-conforming.
*
* @author Bryan Atsatt
*/
public class ImplementationType extends ClassType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an ImplementationType for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static ImplementationType forImplementation(ClassDefinition classDef,
ContextStack stack,
boolean quiet) {
if (stack.anyErrors()) return null;
boolean doPop = false;
ImplementationType result = null;
try {
// Do we already have it?
sun.tools.java.Type theType = classDef.getType();
Type existing = getType(theType,stack);
if (existing != null) {
if (!(existing instanceof ImplementationType)) return null; // False hit.
// Yep, so return it...
return (ImplementationType) existing;
}
// Could this be an implementation?
if (couldBeImplementation(quiet,stack,classDef)) {
// Yes, so check it...
ImplementationType it = new ImplementationType(stack, classDef);
putType(theType,it,stack);
stack.push(it);
doPop = true;
if (it.initialize(stack,quiet)) {
stack.pop(true);
result = it;
} else {
removeType(theType,stack);
stack.pop(false);
}
}
} catch (CompilerError e) {
if (doPop) stack.pop(false);
}
return result;
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Implementation";
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
/**
* Create a ImplementationType instance for the given class. The resulting
* object is not yet completely initialized.
*/
private ImplementationType(ContextStack stack, ClassDefinition classDef) {
super(TYPE_IMPLEMENTATION | TM_CLASS | TM_COMPOUND,classDef,stack); // Use special constructor.
}
private static boolean couldBeImplementation(boolean quiet, ContextStack stack,
ClassDefinition classDef) {
boolean result = false;
BatchEnvironment env = stack.getEnv();
try {
if (!classDef.isClass()) {
failedConstraint(17,quiet,stack,classDef.getName());
} else {
result = env.defRemote.implementedBy(env, classDef.getClassDeclaration());
if (!result) failedConstraint(8,quiet,stack,classDef.getName());
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return result;
}
/**
* Initialize this instance.
*/
private boolean initialize (ContextStack stack, boolean quiet) {
boolean result = false;
ClassDefinition theClass = getClassDefinition();
if (initParents(stack)) {
// Make up our collections...
Vector directInterfaces = new Vector();
Vector directMethods = new Vector();
// Check interfaces...
try {
if (addRemoteInterfaces(directInterfaces,true,stack) != null) {
boolean haveRemote = false;
// Get methods from all interfaces...
for (int i = 0; i < directInterfaces.size(); i++) {
InterfaceType theInt = (InterfaceType) directInterfaces.elementAt(i);
if (theInt.isType(TYPE_REMOTE) ||
theInt.isType(TYPE_JAVA_RMI_REMOTE)) {
haveRemote = true;
}
copyRemoteMethods(theInt,directMethods);
}
// Make sure we have at least one remote interface...
if (!haveRemote) {
failedConstraint(8,quiet,stack,getQualifiedName());
return false;
}
// Now check the methods to ensure we have the
// correct throws clauses...
if (checkMethods(theClass,directMethods,stack,quiet)) {
// We're ok, so pass 'em up...
result = initialize(directInterfaces,directMethods,null,stack,quiet);
}
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
}
return result;
}
private static void copyRemoteMethods(InterfaceType type, Vector list) {
if (type.isType(TYPE_REMOTE)) {
// Copy all the unique methods from type...
Method[] allMethods = type.getMethods();
for (int i = 0; i < allMethods.length; i++) {
Method theMethod = allMethods[i];
if (!list.contains(theMethod)) {
list.addElement(theMethod);
}
}
// Now recurse thru all inherited interfaces...
InterfaceType[] allInterfaces = type.getInterfaces();
for (int i = 0; i < allInterfaces.length; i++) {
copyRemoteMethods(allInterfaces[i],list);
}
}
}
// Walk all methods of the class, and for each that is already in
// the list, call setImplExceptions()...
private boolean checkMethods(ClassDefinition theClass, Vector list,
ContextStack stack, boolean quiet) {
// Convert vector to array...
Method[] methods = new Method[list.size()];
list.copyInto(methods);
for (MemberDefinition member = theClass.getFirstMember();
member != null;
member = member.getNextMember()) {
if (member.isMethod() && !member.isConstructor()
&& !member.isInitializer()) {
// It's a method...
if (!updateExceptions(member,methods,stack,quiet)) {
return false;
}
}
}
return true;
}
private boolean updateExceptions (MemberDefinition implMethod, Method[] list,
ContextStack stack, boolean quiet) {
int length = list.length;
String implMethodSig = implMethod.toString();
for (int i = 0; i < length; i++) {
Method existingMethod = list[i];
MemberDefinition existing = existingMethod.getMemberDefinition();
// Do we have a matching method?
if (implMethodSig.equals(existing.toString())) {
// Yes, so create exception list...
try {
ValueType[] implExcept = getMethodExceptions(implMethod,quiet,stack);
existingMethod.setImplExceptions(implExcept);
} catch (Exception e) {
return false;
}
}
}
return true;
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.io.IOException;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassDefinition;
import sun.rmi.rmic.IndentingWriter;
/**
* InterfaceType is an abstract base representing any non-special
* interface type.
*
* @author Bryan Atsatt
*/
public abstract class InterfaceType extends CompoundType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Print this type.
* @param writer The stream to print to.
* @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
* @param useIDLNames If true, print IDL names; otherwise, print java names.
* @param globalIDLNames If true and useIDLNames true, prepends "::".
*/
public void print ( IndentingWriter writer,
boolean useQualifiedNames,
boolean useIDLNames,
boolean globalIDLNames) throws IOException {
if (isInner()) {
writer.p("// " + getTypeDescription() + " (INNER)");
} else {
writer.p("// " + getTypeDescription() + "");
}
writer.pln(" (" + getRepositoryID() + ")\n");
printPackageOpen(writer,useIDLNames);
if (!useIDLNames) {
writer.p("public ");
}
writer.p("interface " + getTypeName(false,useIDLNames,false));
printImplements(writer,"",useQualifiedNames,useIDLNames,globalIDLNames);
writer.plnI(" {");
printMembers(writer,useQualifiedNames,useIDLNames,globalIDLNames);
writer.pln();
printMethods(writer,useQualifiedNames,useIDLNames,globalIDLNames);
writer.pln();
if (useIDLNames) {
writer.pOln("};");
} else {
writer.pOln("}");
}
printPackageClose(writer,useIDLNames);
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
/**
* Create a InterfaceType instance for the given class. NOTE: This constructor
* is ONLY for SpecialInterfaceType.
*/
protected InterfaceType(ContextStack stack, int typeCode, ClassDefinition classDef) {
super(stack,typeCode,classDef); // Call special parent constructor.
if ((typeCode & TM_INTERFACE) == 0 || ! classDef.isInterface()) {
throw new CompilerError("Not an interface");
}
}
/**
* Create a InterfaceType instance for the given class. The resulting
* object is not yet completely initialized. Subclasses must call
* initialize(directInterfaces,directInterfaces,directConstants);
*/
protected InterfaceType(ContextStack stack,
ClassDefinition classDef,
int typeCode) {
super(stack,classDef,typeCode);
if ((typeCode & TM_INTERFACE) == 0 || ! classDef.isInterface()) {
throw new CompilerError("Not an interface");
}
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDefinition;
/**
* NCClassType represents any non-special class which does not
* extends one or more interfaces which inherit from java.rmi.Remote.
* <p>
* The static forImplementation(...) method must be used to obtain an instance,
* and will return null if the ClassDefinition is non-conforming.
*
* @author Bryan Atsatt
*/
public class NCClassType extends ClassType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an NCClassType for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static NCClassType forNCClass(ClassDefinition classDef,
ContextStack stack) {
if (stack.anyErrors()) return null;
boolean doPop = false;
try {
// Do we already have it?
sun.tools.java.Type theType = classDef.getType();
Type existing = getType(theType,stack);
if (existing != null) {
if (!(existing instanceof NCClassType)) return null; // False hit.
// Yep, so return it...
return (NCClassType) existing;
}
NCClassType it = new NCClassType(stack, classDef);
putType(theType,it,stack);
stack.push(it);
doPop = true;
if (it.initialize(stack)) {
stack.pop(true);
return it;
} else {
removeType(theType,stack);
stack.pop(false);
return null;
}
} catch (CompilerError e) {
if (doPop) stack.pop(false);
return null;
}
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return addExceptionDescription("Non-conforming class");
}
//_____________________________________________________________________
// Internal/Subclass Interfaces
//_____________________________________________________________________
/**
* Create a NCClassType instance for the given class. The resulting
* object is not yet completely initialized.
*/
private NCClassType(ContextStack stack, ClassDefinition classDef) {
super(stack,classDef,TYPE_NC_CLASS | TM_CLASS | TM_COMPOUND);
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
/**
* Initialize this instance.
*/
private boolean initialize (ContextStack stack) {
if (!initParents(stack)) {
return false;
}
if (stack.getEnv().getParseNonConforming()) {
Vector directInterfaces = new Vector();
Vector directMethods = new Vector();
Vector directMembers = new Vector();
try {
// Get methods...
if (addAllMethods(getClassDefinition(),directMethods,false,false,stack) != null) {
// Update parent class methods...
if (updateParentClassMethods(getClassDefinition(),directMethods,false,stack) != null) {
// Get conforming constants...
if (addConformingConstants(directMembers,false,stack)) {
// We're ok, so pass 'em up...
if (!initialize(directInterfaces,directMethods,directMembers,stack,false)) {
return false;
}
}
}
}
return true;
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return false;
} else {
return initialize(null,null,null,stack,false);
}
}
}

View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDefinition;
/**
* NCInterfaceType represents any non-special, non-conforming interface.
* <p>
* The static forNCInterface(...) method must be used to obtain an instance.
* @author Bryan Atsatt
*/
public class NCInterfaceType extends InterfaceType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an NCInterfaceType for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static NCInterfaceType forNCInterface( ClassDefinition classDef,
ContextStack stack) {
if (stack.anyErrors()) return null;
boolean doPop = false;
try {
// Do we already have it?
sun.tools.java.Type theType = classDef.getType();
Type existing = getType(theType,stack);
if (existing != null) {
if (!(existing instanceof NCInterfaceType)) return null; // False hit.
// Yep, so return it...
return (NCInterfaceType) existing;
}
NCInterfaceType it = new NCInterfaceType(stack, classDef);
putType(theType,it,stack);
stack.push(it);
doPop = true;
if (it.initialize(stack)) {
stack.pop(true);
return it;
} else {
removeType(theType,stack);
stack.pop(false);
return null;
}
} catch (CompilerError e) {
if (doPop) stack.pop(false);
return null;
}
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Non-conforming interface";
}
//_____________________________________________________________________
// Internal/Subclass Interfaces
//_____________________________________________________________________
/**
* Create a NCInterfaceType instance for the given class. The resulting
* object is not yet completely initialized.
*/
private NCInterfaceType(ContextStack stack, ClassDefinition classDef) {
super(stack,classDef,TYPE_NC_INTERFACE | TM_INTERFACE | TM_COMPOUND);
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
/**
* Initialize this instance.
*/
private boolean initialize (ContextStack stack) {
if (stack.getEnv().getParseNonConforming()) {
Vector directInterfaces = new Vector();
Vector directMethods = new Vector();
Vector directMembers = new Vector();
try {
// need to include parent interfaces in IDL generation...
addNonRemoteInterfaces( directInterfaces,stack );
// Get methods...
if (addAllMethods(getClassDefinition(),directMethods,false,false,stack) != null) {
// Get conforming constants...
if (addConformingConstants(directMembers,false,stack)) {
// We're ok, so pass 'em up...
if (!initialize(directInterfaces,directMethods,directMembers,stack,false)) {
return false;
}
}
}
return true;
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return false;
} else {
return initialize(null,null,null,stack,false);
}
}
}

View File

@@ -0,0 +1,232 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Hashtable;
/**
* A NameContext enables detection of strings which differ only
* in case.
*
* @author Bryan Atsatt
*/
class NameContext {
private Hashtable table;
private boolean allowCollisions;
/**
* Get a context for the given name. Name may be null, in
* which case this method will return the default context.
*/
public static synchronized NameContext forName (String name,
boolean allowCollisions,
BatchEnvironment env) {
NameContext result = null;
// Do we need to use the default context?
if (name == null) {
// Yes.
name = "null";
}
// Have we initialized our hashtable?
if (env.nameContexts == null) {
// Nope, so do it...
env.nameContexts = new Hashtable();
} else {
// Yes, see if we already have the requested
// context...
result = (NameContext) env.nameContexts.get(name);
}
// Do we have the requested context?
if (result == null) {
// Nope, so create and add it...
result = new NameContext(allowCollisions);
env.nameContexts.put(name,result);
}
return result;
}
/**
* Construct a context.
* @param allowCollisions true if case-sensitive name collisions
* are allowed, false if not.
*/
public NameContext (boolean allowCollisions) {
this.allowCollisions = allowCollisions;
table = new Hashtable();
}
/**
* Add a name to this context. If constructed with allowCollisions
* false and a collision occurs, this method will throw an exception
* in which the message contains the string: "name" and "collision".
*/
public void assertPut (String name) throws Exception {
String message = add(name);
if (message != null) {
throw new Exception(message);
}
}
/**
* Add a name to this context..
*/
public void put (String name) {
if (allowCollisions == false) {
throw new Error("Must use assertPut(name)");
}
add(name);
}
/**
* Add a name to this context. If constructed with allowCollisions
* false and a collision occurs, this method will return a message
* string, otherwise returns null.
*/
private String add (String name) {
// First, create a key by converting name to lowercase...
String key = name.toLowerCase();
// Does this key exist in the context?
Name value = (Name) table.get(key);
if (value != null) {
// Yes, so they match if we ignore case. Do they match if
// we don't ignore case?
if (!name.equals(value.name)) {
// No, so this is a case-sensitive match. Are we
// supposed to allow this?
if (allowCollisions) {
// Yes, make sure it knows that it collides...
value.collisions = true;
} else {
// No, so return a message string...
return new String("\"" + name + "\" and \"" + value.name + "\"");
}
}
} else {
// No, so add it...
table.put(key,new Name(name,false));
}
return null;
}
/**
* Get a name from the context. If it has collisions, the name
* will be converted as specified in section 5.2.7.
*/
public String get (String name) {
Name it = (Name) table.get(name.toLowerCase());
String result = name;
// Do we need to mangle it?
if (it.collisions) {
// Yep, so do it...
int length = name.length();
boolean allLower = true;
for (int i = 0; i < length; i++) {
if (Character.isUpperCase(name.charAt(i))) {
result += "_";
result += i;
allLower = false;
}
}
if (allLower) {
result += "_";
}
}
return result;
}
/**
* Remove all entries.
*/
public void clear () {
table.clear();
}
public class Name {
public String name;
public boolean collisions;
public Name (String name, boolean collisions) {
this.name = name;
this.collisions = collisions;
}
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.tools.java.CompilerError;
import sun.tools.java.Identifier;
import sun.tools.java.ClassDefinition;
/**
* PrimitiveType wraps primitive types and void.
* <p>
* The static forPrimitive(...) method must be used to obtain an instance, and
* will return null if the type is non-conforming.
*
* @author Bryan Atsatt
*/
public class PrimitiveType extends Type {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create a PrimitiveType object for the given type.
*
* If the type is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static PrimitiveType forPrimitive(sun.tools.java.Type type,
ContextStack stack) {
if (stack.anyErrors()) return null;
// Do we already have it?
Type existing = getType(type,stack);
if (existing != null) {
if (!(existing instanceof PrimitiveType)) return null; // False hit.
// Yep, so return it...
return (PrimitiveType) existing;
}
int typeCode;
switch (type.getTypeCode()) {
case TC_VOID: typeCode = TYPE_VOID; break;
case TC_BOOLEAN: typeCode = TYPE_BOOLEAN; break;
case TC_BYTE: typeCode = TYPE_BYTE; break;
case TC_CHAR: typeCode = TYPE_CHAR; break;
case TC_SHORT: typeCode = TYPE_SHORT; break;
case TC_INT: typeCode = TYPE_INT; break;
case TC_LONG: typeCode = TYPE_LONG; break;
case TC_FLOAT: typeCode = TYPE_FLOAT; break;
case TC_DOUBLE: typeCode = TYPE_DOUBLE; break;
default: return null;
}
PrimitiveType it = new PrimitiveType(stack,typeCode);
// Add it...
putType(type,it,stack);
// Do the stack thing in case tracing on...
stack.push(it);
stack.pop(true);
return it;
}
/**
* Return signature for this type (e.g. com.acme.Dynamite
* would return "com.acme.Dynamite", byte = "B")
*/
public String getSignature() {
switch (getTypeCode()) {
case TYPE_VOID: return SIG_VOID;
case TYPE_BOOLEAN: return SIG_BOOLEAN;
case TYPE_BYTE: return SIG_BYTE;
case TYPE_CHAR: return SIG_CHAR;
case TYPE_SHORT: return SIG_SHORT;
case TYPE_INT: return SIG_INT;
case TYPE_LONG: return SIG_LONG;
case TYPE_FLOAT: return SIG_FLOAT;
case TYPE_DOUBLE: return SIG_DOUBLE;
default: return null;
}
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Primitive";
}
/**
* IDL_Naming
* Return the fully qualified IDL name for this type (e.g. com.acme.Dynamite would
* return "com::acme::Dynamite").
* @param global If true, prepends "::".
*/
public String getQualifiedIDLName(boolean global) {
return super.getQualifiedIDLName(false);
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
/*
* Load a Class instance. Return null if fail.
*/
protected Class loadClass() {
switch (getTypeCode()) {
case TYPE_VOID: return Null.class;
case TYPE_BOOLEAN: return boolean.class;
case TYPE_BYTE: return byte.class;
case TYPE_CHAR: return char.class;
case TYPE_SHORT: return short.class;
case TYPE_INT: return int.class;
case TYPE_LONG: return long.class;
case TYPE_FLOAT: return float.class;
case TYPE_DOUBLE: return double.class;
default: throw new CompilerError("Not a primitive type");
}
}
/**
* IDL_Naming
* Create an PrimitiveType instance for the given class.
*/
private PrimitiveType(ContextStack stack, int typeCode) {
super(stack,typeCode | TM_PRIMITIVE);
// Validate type and set names...
String idlName = IDLNames.getTypeName(typeCode,false);
Identifier id = null;
switch (typeCode) {
case TYPE_VOID: id = idVoid; break;
case TYPE_BOOLEAN: id = idBoolean; break;
case TYPE_BYTE: id = idByte; break;
case TYPE_CHAR: id = idChar; break;
case TYPE_SHORT: id = idShort; break;
case TYPE_INT: id = idInt; break;
case TYPE_LONG: id = idLong; break;
case TYPE_FLOAT: id = idFloat; break;
case TYPE_DOUBLE: id = idDouble; break;
default: throw new CompilerError("Not a primitive type");
}
setNames(id,null,idlName);
setRepositoryID();
}
}
class Null {}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassDefinition;
import sun.rmi.rmic.IndentingWriter;
import sun.rmi.rmic.Main;
/**
* An IDL generator for rmic.
*
* @author Bryan Atsatt
*/
public class PrintGenerator implements sun.rmi.rmic.Generator,
sun.rmi.rmic.iiop.Constants {
private static final int JAVA = 0;
private static final int IDL = 1;
private static final int BOTH = 2;
private int whatToPrint; // Initialized in parseArgs.
private boolean global = false;
private boolean qualified = false;
private boolean trace = false;
private boolean valueMethods = false;
private IndentingWriter out;
/**
* Default constructor for Main to use.
*/
public PrintGenerator() {
OutputStreamWriter writer = new OutputStreamWriter(System.out);
out = new IndentingWriter (writer);
}
/**
* Examine and consume command line arguments.
* @param argv The command line arguments. Ignore null
* @param error Report any errors using the main.error() methods.
* @return true if no errors, false otherwise.
*/
public boolean parseArgs(String argv[], Main main) {
for (int i = 0; i < argv.length; i++) {
if (argv[i] != null) {
String arg = argv[i].toLowerCase();
if (arg.equals("-xprint")) {
whatToPrint = JAVA;
argv[i] = null;
if (i+1 < argv.length) {
if (argv[i+1].equalsIgnoreCase("idl")) {
argv[++i] = null;
whatToPrint = IDL;
} else if (argv[i+1].equalsIgnoreCase("both")) {
argv[++i] = null;
whatToPrint = BOTH;
}
}
} else if (arg.equals("-xglobal")) {
global = true;
argv[i] = null;
} else if (arg.equals("-xqualified")) {
qualified = true;
argv[i] = null;
} else if (arg.equals("-xtrace")) {
trace = true;
argv[i] = null;
} else if (arg.equals("-xvaluemethods")) {
valueMethods = true;
argv[i] = null;
}
}
}
return true;
}
/**
* Generate output. Any source files created which need compilation should
* be added to the compiler environment using the addGeneratedFile(File)
* method.
*
* @param env The compiler environment
* @param cdef The definition for the implementation class or interface from
* which to generate output
* @param destDir The directory for the root of the package hierarchy
* for generated files. May be null.
*/
public void generate(sun.rmi.rmic.BatchEnvironment env, ClassDefinition cdef, File destDir) {
BatchEnvironment ourEnv = (BatchEnvironment) env;
ContextStack stack = new ContextStack(ourEnv);
stack.setTrace(trace);
if (valueMethods) {
ourEnv.setParseNonConforming(true);
}
// Get our top level type...
CompoundType topType = CompoundType.forCompound(cdef,stack);
if (topType != null) {
try {
// Collect up all the compound types...
Type[] theTypes = topType.collectMatching(TM_COMPOUND);
for (int i = 0; i < theTypes.length; i++) {
out.pln("\n-----------------------------------------------------------\n");
Type theType = theTypes[i];
switch (whatToPrint) {
case JAVA: theType.println(out,qualified,false,false);
break;
case IDL: theType.println(out,qualified,true,global);
break;
case BOTH: theType.println(out,qualified,false,false);
theType.println(out,qualified,true,global);
break;
default: throw new CompilerError("Unknown type!");
}
}
out.flush();
} catch (IOException e) {
throw new CompilerError("PrintGenerator caught " + e);
}
}
}
}

View File

@@ -0,0 +1,251 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import sun.tools.java.CompilerError;
import sun.tools.java.ClassDefinition;
import sun.tools.java.ClassNotFound;
/**
* RemoteType represents any non-special interface which inherits
* from java.rmi.Remote.
* <p>
* The static forRemote(...) method must be used to obtain an instance, and will
* return null if the ClassDefinition is non-conforming.
* @author Bryan Atsatt
*/
public class RemoteType extends InterfaceType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an RemoteType for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static RemoteType forRemote(ClassDefinition classDef,
ContextStack stack,
boolean quiet) {
if (stack.anyErrors()) return null;
boolean doPop = false;
RemoteType result = null;
try {
// Do we already have it?
sun.tools.java.Type theType = classDef.getType();
Type existing = getType(theType,stack);
if (existing != null) {
if (!(existing instanceof RemoteType)) return null; // False hit.
// Yep, so return it...
return (RemoteType) existing;
}
// Could this be a remote type?
if (couldBeRemote(quiet,stack,classDef)) {
// Yes, so check it...
RemoteType it = new RemoteType(stack,classDef);
putType(theType,it,stack);
stack.push(it);
doPop = true;
if (it.initialize(quiet,stack)) {
stack.pop(true);
result = it;
} else {
removeType(theType,stack);
stack.pop(false);
}
}
} catch (CompilerError e) {
if (doPop) stack.pop(false);
}
return result;
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Remote interface";
}
//_____________________________________________________________________
// Internal/Subclass Interfaces
//_____________________________________________________________________
/**
* Create a RemoteType instance for the given class. The resulting
* object is not yet completely initialized.
*/
protected RemoteType(ContextStack stack, ClassDefinition classDef) {
super(stack,classDef,TYPE_REMOTE | TM_INTERFACE | TM_COMPOUND);
}
/**
* Create a RemoteType instance for the given class. The resulting
* object is not yet completely initialized.
*/
protected RemoteType(ContextStack stack, ClassDefinition classDef, int typeCode) {
super(stack,classDef,typeCode);
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
private static boolean couldBeRemote (boolean quiet, ContextStack stack,
ClassDefinition classDef) {
boolean result = false;
BatchEnvironment env = stack.getEnv();
try {
if (!classDef.isInterface()) {
failedConstraint(16,quiet,stack,classDef.getName());
} else {
result = env.defRemote.implementedBy(env,classDef.getClassDeclaration());
if (!result) failedConstraint(1,quiet,stack,classDef.getName());
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return result;
}
/**
* Initialize this instance.
*/
private boolean initialize (boolean quiet,ContextStack stack) {
boolean result = false;
// Go check it out and gather up the info we need...
Vector directInterfaces = new Vector();
Vector directMethods = new Vector();
Vector directConstants = new Vector();
if (isConformingRemoteInterface(directInterfaces,
directMethods,
directConstants,
quiet,
stack)){
// We're ok, so pass 'em up...
result = initialize(directInterfaces,directMethods,directConstants,stack,quiet);
}
return result;
}
/**
* Check to ensure that the interface and all it's methods and arguments
* conforms to the RMI/IDL java subset for remote interfaces as defined
* by the "Java to IDL Mapping" specification, section 4.
* @param directInterfaces All directly implmented interfaces will be
* added to this list.
* @param directMethods All directly implemented methods (other than
* constructors and initializers) will be added to this list.
* @param directConstants All constants defined by theInterface will be
* added to this list.
* @param quiet True if should not report constraint failures.
* @return true if constraints satisfied, false otherwise.
*/
private boolean isConformingRemoteInterface ( Vector directInterfaces,
Vector directMethods,
Vector directConstants,
boolean quiet,
ContextStack stack) {
ClassDefinition theInterface = getClassDefinition();
try {
// Get all remote interfaces...
if (addRemoteInterfaces(directInterfaces,false,stack) == null ) {
return false;
}
// Make sure all constants are conforming...
if (!addAllMembers(directConstants,true,quiet,stack)) {
return false;
}
// Now, collect up all methods...
if (addAllMethods(theInterface,directMethods,true,quiet,stack) == null) {
// Failed a constraint check...
return false;
}
// Now walk 'em, ensuring each is a valid remote method...
boolean methodsConform = true;
for (int i = 0; i < directMethods.size(); i++) {
if (! isConformingRemoteMethod((Method) directMethods.elementAt(i),quiet)) {
methodsConform = false;
}
}
if (!methodsConform) {
return false;
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
return false;
}
return true;
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.tools.java.ClassNotFound;
import sun.tools.java.CompilerError;
import sun.tools.java.Identifier;
import sun.tools.java.ClassDefinition;
/**
* SpecialClassType represents any one of the following types:
* <pre>
* java.lang.Object
* java.lang.String
* </pre>
* all of which are treated as special cases.
* <p>
* The static forSpecial(...) method must be used to obtain an instance, and
* will return null if the type is non-conforming.
*
* @author Bryan Atsatt
*/
public class SpecialClassType extends ClassType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create a SpecialClassType object for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static SpecialClassType forSpecial (ClassDefinition theClass,
ContextStack stack) {
if (stack.anyErrors()) return null;
sun.tools.java.Type type = theClass.getType();
// Do we already have it?
String typeKey = type.toString() + stack.getContextCodeString();
Type existing = getType(typeKey,stack);
if (existing != null) {
if (!(existing instanceof SpecialClassType)) return null; // False hit.
// Yep, so return it...
return (SpecialClassType) existing;
}
// Is it a special type?
int typeCode = getTypeCode(type,theClass,stack);
if (typeCode != TYPE_NONE) {
// Yes...
SpecialClassType result = new SpecialClassType(stack,typeCode,theClass);
putType(typeKey,result,stack);
stack.push(result);
stack.pop(true);
return result;
} else {
return null;
}
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Special class";
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
/**
* Create an SpecialClassType instance for the given class.
*/
private SpecialClassType(ContextStack stack, int typeCode,
ClassDefinition theClass) {
super(stack,typeCode | TM_SPECIAL_CLASS | TM_CLASS | TM_COMPOUND, theClass);
Identifier id = theClass.getName();
String idlName = null;
String[] idlModuleName = null;
boolean constant = stack.size() > 0 && stack.getContext().isConstant();
// Set names...
switch (typeCode) {
case TYPE_STRING: {
idlName = IDLNames.getTypeName(typeCode,constant);
if (!constant) {
idlModuleName = IDL_CORBA_MODULE;
}
break;
}
case TYPE_ANY: {
idlName = IDL_JAVA_LANG_OBJECT;
idlModuleName = IDL_JAVA_LANG_MODULE;
break;
}
}
setNames(id,idlModuleName,idlName);
// Init parents...
if (!initParents(stack)) {
// Should not be possible!
throw new CompilerError("SpecialClassType found invalid parent.");
}
// Initialize CompoundType...
initialize(null,null,null,stack,false);
}
private static int getTypeCode(sun.tools.java.Type type, ClassDefinition theClass, ContextStack stack) {
if (type.isType(TC_CLASS)) {
Identifier id = type.getClassName();
if (id == idJavaLangString) return TYPE_STRING;
if (id == idJavaLangObject) return TYPE_ANY;
}
return TYPE_NONE;
}
}

View File

@@ -0,0 +1,233 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import sun.tools.java.ClassNotFound;
import sun.tools.java.CompilerError;
import sun.tools.java.Identifier;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.ClassDefinition;
/**
* SpecialInterfaceType represents any one of the following types:
* <pre>
* java.rmi.Remote
* java.io.Serializable
* java.io.Externalizable
* org.omg.CORBA.Object
* org.omg.CORBA.portable.IDLEntity
* </pre>
* all of which are treated as special cases. For all but CORBA.Object,
* the type must match exactly. For CORBA.Object, the type must either be
* CORBA.Object or inherit from it.
* <p>
* The static forSpecial(...) method must be used to obtain an instance, and
* will return null if the type is non-conforming.
*
* @author Bryan Atsatt
*/
public class SpecialInterfaceType extends InterfaceType {
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create a SpecialInterfaceType object for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static SpecialInterfaceType forSpecial ( ClassDefinition theClass,
ContextStack stack) {
if (stack.anyErrors()) return null;
// Do we already have it?
sun.tools.java.Type type = theClass.getType();
Type existing = getType(type,stack);
if (existing != null) {
if (!(existing instanceof SpecialInterfaceType)) return null; // False hit.
// Yep, so return it...
return (SpecialInterfaceType) existing;
}
// Is it special?
if (isSpecial(type,theClass,stack)) {
// Yes...
SpecialInterfaceType result = new SpecialInterfaceType(stack,0,theClass);
putType(type,result,stack);
stack.push(result);
if (result.initialize(type,stack)) {
stack.pop(true);
return result;
} else {
removeType(type,stack);
stack.pop(false);
return null;
}
}
return null;
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
return "Special interface";
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
/**
* Create an SpecialInterfaceType instance for the given class.
*/
private SpecialInterfaceType(ContextStack stack, int typeCode,
ClassDefinition theClass) {
super(stack,typeCode | TM_SPECIAL_INTERFACE | TM_INTERFACE | TM_COMPOUND, theClass);
setNames(theClass.getName(),null,null); // Fixed in initialize.
}
private static boolean isSpecial(sun.tools.java.Type type,
ClassDefinition theClass,
ContextStack stack) {
if (type.isType(TC_CLASS)) {
Identifier id = type.getClassName();
if (id.equals(idRemote)) return true;
if (id == idJavaIoSerializable) return true;
if (id == idJavaIoExternalizable) return true;
if (id == idCorbaObject) return true;
if (id == idIDLEntity) return true;
BatchEnvironment env = stack.getEnv();
try {
if (env.defCorbaObject.implementedBy(env,theClass.getClassDeclaration())) return true;
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
}
return false;
}
private boolean initialize(sun.tools.java.Type type, ContextStack stack) {
int typeCode = TYPE_NONE;
Identifier id = null;
String idlName = null;
String[] idlModuleName = null;
boolean constant = stack.size() > 0 && stack.getContext().isConstant();
if (type.isType(TC_CLASS)) {
id = type.getClassName();
if (id.equals(idRemote)) {
typeCode = TYPE_JAVA_RMI_REMOTE;
idlName = IDL_JAVA_RMI_REMOTE;
idlModuleName = IDL_JAVA_RMI_MODULE;
} else if (id == idJavaIoSerializable) {
typeCode = TYPE_ANY;
idlName = IDL_SERIALIZABLE;
idlModuleName = IDL_JAVA_IO_MODULE;
} else if (id == idJavaIoExternalizable) {
typeCode = TYPE_ANY;
idlName = IDL_EXTERNALIZABLE;
idlModuleName = IDL_JAVA_IO_MODULE;
} else if (id == idIDLEntity) {
typeCode = TYPE_ANY;
idlName = IDL_IDLENTITY;
idlModuleName = IDL_ORG_OMG_CORBA_PORTABLE_MODULE;
} else {
typeCode = TYPE_CORBA_OBJECT;
// Is it exactly org.omg.CORBA.Object?
if (id == idCorbaObject) {
// Yes, so special case...
idlName = IDLNames.getTypeName(typeCode,constant);
idlModuleName = null;
} else {
// No, so get the correct names...
try {
// These can fail if we get case-sensitive name matches...
idlName = IDLNames.getClassOrInterfaceName(id,env);
idlModuleName = IDLNames.getModuleNames(id,isBoxed(),env);
} catch (Exception e) {
failedConstraint(7,false,stack,id.toString(),e.getMessage());
throw new CompilerError("");
}
}
}
}
if (typeCode == TYPE_NONE) {
return false;
}
// Reset type code...
setTypeCode(typeCode | TM_SPECIAL_INTERFACE | TM_INTERFACE | TM_COMPOUND);
// Set names
if (idlName == null) {
throw new CompilerError("Not a special type");
}
setNames(id,idlModuleName,idlName);
// Initialize CompoundType...
return initialize(null,null,null,stack,false);
}
}

View File

@@ -0,0 +1,372 @@
/*
* Copyright (c) 1999, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
/**
* StaticStringsHash takes an array of constant strings and
* uses several different hash methods to try to find the
* 'best' one for that set. The set of methods is currently
* fixed, but with a little work could be made extensible thru
* subclassing.
* <p>
* The current set of methods is:
* <ol>
* <li> length() - works well when all strings are different length.</li>
* <li> charAt(n) - works well when one offset into all strings is different.</li>
* <li> hashCode() - works well with larger arrays.</li>
* </ol>
* After constructing an instance over the set of strings, the
* <code>getKey(String)</code> method can be used to use the selected hash
* method to produce a key. The <code>method</code> string will contain
* "length()", "charAt(n)", or "hashCode()", and is intended for use by
* code generators.
* <p>
* The <code>keys</code> array will contain the full set of unique keys.
* <p>
* The <code>buckets</code> array will contain a set of arrays, one for
* each key in the <code>keys</code>, where <code>buckets[x][y]</code>
* is an index into the <code>strings</code> array.
* @author Bryan Atsatt
*/
public class StaticStringsHash {
/** The set of strings upon which the hash info is created */
public String[] strings = null;
/** Unique hash keys */
public int[] keys = null;
/** Buckets for each key, where buckets[x][y] is an index
* into the strings[] array. */
public int[][] buckets = null;
/** The method to invoke on String to produce the hash key */
public String method = null;
/** Get a key for the given string using the
* selected hash method.
* @param str the string to return a key for.
* @return the key.
*/
public int getKey(String str) {
switch (keyKind) {
case LENGTH: return str.length();
case CHAR_AT: return str.charAt(charAt);
case HASH_CODE: return str.hashCode();
}
throw new Error("Bad keyKind");
}
/** Constructor
* @param strings the set of strings upon which to
* find an optimal hash method. Must not contain
* duplicates.
*/
public StaticStringsHash(String[] strings) {
this.strings = strings;
length = strings.length;
tempKeys = new int[length];
bucketSizes = new int[length];
setMinStringLength();
// Decide on the best algorithm based on
// which one has the smallest maximum
// bucket depth. First, try length()...
int currentMaxDepth = getKeys(LENGTH);
int useCharAt = -1;
boolean useHashCode = false;
if (currentMaxDepth > 1) {
// At least one bucket had more than one
// entry, so try charAt(i). If there
// are a lot of strings in the array,
// and minStringLength is large, limit
// the search to a smaller number of
// characters to avoid spending a lot
// of time here that is most likely to
// be pointless...
int minLength = minStringLength;
if (length > CHAR_AT_MAX_LINES &&
length * minLength > CHAR_AT_MAX_CHARS) {
minLength = length/CHAR_AT_MAX_CHARS;
}
charAt = 0;
for (int i = 0; i < minLength; i++) {
int charAtDepth = getKeys(CHAR_AT);
if (charAtDepth < currentMaxDepth) {
currentMaxDepth = charAtDepth;
useCharAt = i;
if (currentMaxDepth == 1) {
break;
}
}
charAt++;
}
charAt = useCharAt;
if (currentMaxDepth > 1) {
// At least one bucket had more than one
// entry, try hashCode().
//
// Since the cost of computing a full hashCode
// (for the runtime target string) is much higher
// than the previous methods, use it only if it is
// substantially better. The definition of 'substantial'
// here is not very well founded, and could be improved
// with some further analysis ;^)
int hashCodeDepth = getKeys(HASH_CODE);
if (hashCodeDepth < currentMaxDepth-3) {
// Using the full hashCode results in at least
// 3 fewer entries in the worst bucket, so will
// therefore avoid at least 3 calls to equals()
// in the worst case.
//
// Note that using a number smaller than 3 could
// result in using a hashCode when there are only
// 2 strings in the array, and that would surely
// be a poor performance choice.
useHashCode = true;
}
}
// Reset keys if needed...
if (!useHashCode) {
if (useCharAt >= 0) {
// Use the charAt(i) method...
getKeys(CHAR_AT);
} else {
// Use length method...
getKeys(LENGTH);
}
}
}
// Now allocate and fill our real hashKeys array...
keys = new int[bucketCount];
System.arraycopy(tempKeys,0,keys,0,bucketCount);
// Sort keys and bucketSizes arrays...
boolean didSwap;
do {
didSwap = false;
for (int i = 0; i < bucketCount - 1; i++) {
if (keys[i] > keys[i+1]) {
int temp = keys[i];
keys[i] = keys[i+1];
keys[i+1] = temp;
temp = bucketSizes[i];
bucketSizes[i] = bucketSizes[i+1];
bucketSizes[i+1] = temp;
didSwap = true;
}
}
}
while (didSwap == true);
// Allocate our buckets array. Fill the string
// index slot with an unused key so we can
// determine which are free...
int unused = findUnusedKey();
buckets = new int[bucketCount][];
for (int i = 0; i < bucketCount; i++) {
buckets[i] = new int[bucketSizes[i]];
for (int j = 0; j < bucketSizes[i]; j++) {
buckets[i][j] = unused;
}
}
// And fill it in...
for(int i = 0; i < strings.length; i++) {
int key = getKey(strings[i]);
for (int j = 0; j < bucketCount; j++) {
if (keys[j] == key) {
int k = 0;
while (buckets[j][k] != unused) {
k++;
}
buckets[j][k] = i;
break;
}
}
}
}
/** Print an optimized 'contains' method for the
* argument strings
*/
public static void main (String[] args) {
StaticStringsHash hash = new StaticStringsHash(args);
System.out.println();
System.out.println(" public boolean contains(String key) {");
System.out.println(" switch (key."+hash.method+") {");
for (int i = 0; i < hash.buckets.length; i++) {
System.out.println(" case "+hash.keys[i]+": ");
for (int j = 0; j < hash.buckets[i].length; j++) {
if (j > 0) {
System.out.print(" } else ");
} else {
System.out.print(" ");
}
System.out.println("if (key.equals(\""+ hash.strings[hash.buckets[i][j]] +"\")) {");
System.out.println(" return true;");
}
System.out.println(" }");
}
System.out.println(" }");
System.out.println(" return false;");
System.out.println(" }");
}
private int length;
private int[] tempKeys;
private int[] bucketSizes;
private int bucketCount;
private int maxDepth;
private int minStringLength = Integer.MAX_VALUE;
private int keyKind;
private int charAt;
private static final int LENGTH = 0;
private static final int CHAR_AT = 1;
private static final int HASH_CODE = 2;
/* Determines the maximum number of charAt(i)
* tests that will be done. The search is
* limited because if the number of characters
* is large enough, the likelyhood of finding
* a good hash key based on this method is
* low. The CHAR_AT_MAX_CHARS limit only
* applies f there are more strings than
* CHAR_AT_MAX_LINES.
*/
private static final int CHAR_AT_MAX_LINES = 50;
private static final int CHAR_AT_MAX_CHARS = 1000;
private void resetKeys(int keyKind) {
this.keyKind = keyKind;
switch (keyKind) {
case LENGTH: method = "length()"; break;
case CHAR_AT: method = "charAt("+charAt+")"; break;
case HASH_CODE: method = "hashCode()"; break;
}
maxDepth = 1;
bucketCount = 0;
for (int i = 0; i < length; i++) {
tempKeys[i] = 0;
bucketSizes[i] = 0;
}
}
private void setMinStringLength() {
for (int i = 0; i < length; i++) {
if (strings[i].length() < minStringLength) {
minStringLength = strings[i].length();
}
}
}
private int findUnusedKey() {
int unused = 0;
int keysLength = keys.length;
// Note that we just assume that resource
// exhaustion will occur rather than an
// infinite loop here if the set of keys
// is very large.
while (true) {
boolean match = false;
for (int i = 0; i < keysLength; i++) {
if (keys[i] == unused) {
match = true;
break;
}
}
if (match) {
unused--;
} else {
break;
}
}
return unused;
}
private int getKeys(int methodKind) {
resetKeys(methodKind);
for(int i = 0; i < strings.length; i++) {
addKey(getKey(strings[i]));
}
return maxDepth;
}
private void addKey(int key) {
// Have we seen this one before?
boolean addIt = true;
for (int j = 0; j < bucketCount; j++) {
if (tempKeys[j] == key) {
addIt = false;
bucketSizes[j]++;
if (bucketSizes[j] > maxDepth) {
maxDepth = bucketSizes[j];
}
break;
}
}
if (addIt) {
tempKeys[bucketCount] = key;
bucketSizes[bucketCount] = 1;
bucketCount++;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
/*
* Copyright (c) 1999, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.io.File;
import sun.tools.java.Identifier;
import com.sun.corba.se.impl.util.PackagePrefixChecker;
/**
* Util provides static utility methods used by other rmic classes.
* @author Bryan Atsatt
*/
public final class Util implements sun.rmi.rmic.Constants {
public static String packagePrefix(){ return PackagePrefixChecker.packagePrefix();}
/**
* Return the directory that should be used for output for a given
* class.
* @param theClass The fully qualified name of the class.
* @param rootDir The directory to use as the root of the
* package heirarchy. May be null, in which case the current
* working directory is used as the root.
*/
private static File getOutputDirectoryFor(Identifier theClass,
File rootDir,
BatchEnvironment env,
boolean idl ) {
File outputDir = null;
String className = theClass.getFlatName().toString().replace('.', SIGC_INNERCLASS);
String qualifiedClassName = className;
String packagePath = null;
String packageName = theClass.getQualifier().toString();
//Shift package names for stubs generated for interfaces.
/*if(type.isInterface())*/
packageName = correctPackageName(packageName, idl, env.getStandardPackage());
//Done.
if (packageName.length() > 0) {
qualifiedClassName = packageName + "." + className;
packagePath = packageName.replace('.', File.separatorChar);
}
// Do we have a root directory?
if (rootDir != null) {
// Yes, do we have a package name?
if (packagePath != null) {
// Yes, so use it as the root. Open the directory...
outputDir = new File(rootDir, packagePath);
// Make sure the directory exists...
ensureDirectory(outputDir,env);
} else {
// Default package, so use root as output dir...
outputDir = rootDir;
}
} else {
// No root directory. Get the current working directory...
String workingDirPath = System.getProperty("user.dir");
File workingDir = new File(workingDirPath);
// Do we have a package name?
if (packagePath == null) {
// No, so use working directory...
outputDir = workingDir;
} else {
// Yes, so use working directory as the root...
outputDir = new File(workingDir, packagePath);
// Make sure the directory exists...
ensureDirectory(outputDir,env);
}
}
// Finally, return the directory...
return outputDir;
}
public static File getOutputDirectoryForIDL(Identifier theClass,
File rootDir,
BatchEnvironment env) {
return getOutputDirectoryFor(theClass, rootDir, env, true);
}
public static File getOutputDirectoryForStub(Identifier theClass,
File rootDir,
BatchEnvironment env) {
return getOutputDirectoryFor(theClass, rootDir, env, false);
}
private static void ensureDirectory (File dir, BatchEnvironment env) {
if (!dir.exists()) {
dir.mkdirs();
if (!dir.exists()) {
env.error(0,"rmic.cannot.create.dir",dir.getAbsolutePath());
throw new InternalError();
}
}
}
public static String correctPackageName(
String p, boolean idl, boolean standardPackage){
if (idl){
return p;
} else {
if (standardPackage) {
return p;
} else {
return PackagePrefixChecker.correctPackageName(p);
}
}
}
public static boolean isOffendingPackage(String p){
return PackagePrefixChecker.isOffendingPackage(p);
}
public static boolean hasOffendingPrefix(String p){
return PackagePrefixChecker.hasOffendingPrefix(p);
}
}

View File

@@ -0,0 +1,488 @@
/*
* Copyright (c) 1998, 2007, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package sun.rmi.rmic.iiop;
import java.util.Vector;
import sun.tools.java.ClassNotFound;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.ClassDefinition;
import sun.tools.java.MemberDefinition;
import java.util.Hashtable;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;
/**
* ValueType represents any non-special class which does inherit from
* java.io.Serializable and does not inherit from java.rmi.Remote.
* <p>
* The static forValue(...) method must be used to obtain an instance, and
* will return null if the ClassDefinition is non-conforming.
*
* @author Bryan Atsatt
*/
public class ValueType extends ClassType {
private boolean isCustom;
//_____________________________________________________________________
// Public Interfaces
//_____________________________________________________________________
/**
* Create an ValueType object for the given class.
*
* If the class is not a properly formed or if some other error occurs, the
* return value will be null, and errors will have been reported to the
* supplied BatchEnvironment.
*/
public static ValueType forValue(ClassDefinition classDef,
ContextStack stack,
boolean quiet) {
if (stack.anyErrors()) return null;
// Do we already have it?
sun.tools.java.Type theType = classDef.getType();
String typeKey = theType.toString();
Type existing = getType(typeKey,stack);
if (existing != null) {
if (!(existing instanceof ValueType)) return null; // False hit.
// Yep, so return it...
return (ValueType) existing;
}
// Is this java.lang.Class?
boolean javaLangClass = false;
if (classDef.getClassDeclaration().getName() == idJavaLangClass) {
// Yes, so replace classDef with one for
// javax.rmi.CORBA.ClassDesc...
javaLangClass = true;
BatchEnvironment env = stack.getEnv();
ClassDeclaration decl = env.getClassDeclaration(idClassDesc);
ClassDefinition def = null;
try {
def = decl.getClassDefinition(env);
} catch (ClassNotFound ex) {
classNotFound(stack,ex);
return null;
}
classDef = def;
}
// Could this be a value?
if (couldBeValue(stack,classDef)) {
// Yes, so check it...
ValueType it = new ValueType(classDef,stack,javaLangClass);
putType(typeKey,it,stack);
stack.push(it);
if (it.initialize(stack,quiet)) {
stack.pop(true);
return it;
} else {
removeType(typeKey,stack);
stack.pop(false);
return null;
}
} else {
return null;
}
}
/**
* Return a string describing this type.
*/
public String getTypeDescription () {
String result = addExceptionDescription("Value");
if (isCustom) {
result = "Custom " + result;
}
if (isIDLEntity) {
result = result + " [IDLEntity]";
}
return result;
}
/**
* Return true if this type is a "custom" type (i.e.
* it implements java.io.Externalizable or has a
* method with the following signature:
*
* private void writeObject(java.io.ObjectOutputStream out);
*
*/
public boolean isCustom () {
return isCustom;
}
//_____________________________________________________________________
// Subclass/Internal Interfaces
//_____________________________________________________________________
/**
* Create a ValueType instance for the given class. The resulting
* object is not yet completely initialized.
*/
private ValueType(ClassDefinition classDef,
ContextStack stack,
boolean isMappedJavaLangClass) {
super(stack,classDef,TYPE_VALUE | TM_CLASS | TM_COMPOUND);
isCustom = false;
// If this is the mapped version of java.lang.Class,
// set the non-IDL names back to java.lang.Class...
if (isMappedJavaLangClass) {
setNames(idJavaLangClass,IDL_CLASS_MODULE,IDL_CLASS);
}
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
/**
* Initialize this instance.
*/
private static boolean couldBeValue(ContextStack stack, ClassDefinition classDef) {
boolean result = false;
ClassDeclaration classDecl = classDef.getClassDeclaration();
BatchEnvironment env = stack.getEnv();
try {
// Make sure it's not remote...
if (env.defRemote.implementedBy(env, classDecl)) {
failedConstraint(10,false,stack,classDef.getName());
} else {
// Make sure it's Serializable...
if (!env.defSerializable.implementedBy(env, classDecl)) {
failedConstraint(11,false,stack,classDef.getName());
} else {
result = true;
}
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return result;
}
/**
* Initialize this instance.
*/
private boolean initialize (ContextStack stack, boolean quiet) {
ClassDefinition ourDef = getClassDefinition();
ClassDeclaration ourDecl = getClassDeclaration();
try {
// Make sure our parentage is ok...
if (!initParents(stack)) {
failedConstraint(12,quiet,stack,getQualifiedName());
return false;
}
// We're ok, so make up our collections...
Vector directInterfaces = new Vector();
Vector directMethods = new Vector();
Vector directMembers = new Vector();
// Get interfaces...
if (addNonRemoteInterfaces(directInterfaces,stack) != null) {
// Get methods...
if (addAllMethods(ourDef,directMethods,false,false,stack) != null) {
// Update parent class methods
if (updateParentClassMethods(ourDef,directMethods,false,stack) != null) {
// Get constants and members...
if (addAllMembers(directMembers,false,false,stack)) {
// We're ok, so pass 'em up...
if (!initialize(directInterfaces,directMethods,directMembers,stack,quiet)) {
return false;
}
// Is this class Externalizable?
boolean externalizable = false;
if (!env.defExternalizable.implementedBy(env, ourDecl)) {
// No, so check to see if we have a serialPersistentField
// that will modify the members.
if (!checkPersistentFields(getClassInstance(),quiet)) {
return false;
}
} else {
// Yes.
externalizable = true;
}
// Should this class be considered "custom"? It is if
// it is Externalizable OR if it has a method with the
// following signature:
//
// private void writeObject(java.io.ObjectOutputStream out);
//
if (externalizable) {
isCustom = true;
} else {
for (MemberDefinition member = ourDef.getFirstMember();
member != null;
member = member.getNextMember()) {
if (member.isMethod() &&
!member.isInitializer() &&
member.isPrivate() &&
member.getName().toString().equals("writeObject")) {
// Check return type, arguments and exceptions...
sun.tools.java.Type methodType = member.getType();
sun.tools.java.Type rtnType = methodType.getReturnType();
if (rtnType == sun.tools.java.Type.tVoid) {
// Return type is correct. How about arguments?
sun.tools.java.Type[] args = methodType.getArgumentTypes();
if (args.length == 1 &&
args[0].getTypeSignature().equals("Ljava/io/ObjectOutputStream;")) {
// Arguments are correct, so it is a custom
// value type...
isCustom = true;
}
}
}
}
}
}
return true;
}
}
}
} catch (ClassNotFound e) {
classNotFound(stack,e);
}
return false;
}
private boolean checkPersistentFields (Class clz, boolean quiet) {
// Do we have a writeObject method?
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals("writeObject") &&
methods[i].getArguments().length == 1) {
Type returnType = methods[i].getReturnType();
Type arg = methods[i].getArguments()[0];
String id = arg.getQualifiedName();
if (returnType.isType(TYPE_VOID) &&
id.equals("java.io.ObjectOutputStream")) {
// Got one, so there's nothing to do...
return true;
}
}
}
// Do we have a valid serialPersistentField array?
MemberDefinition spfDef = null;
for (int i = 0; i < members.length; i++) {
if (members[i].getName().equals("serialPersistentFields")) {
Member member = members[i];
Type type = member.getType();
Type elementType = type.getElementType();
// We have a member with the correct name. Make sure
// we have the correct signature...
if (elementType != null &&
elementType.getQualifiedName().equals(
"java.io.ObjectStreamField")
) {
if (member.isStatic() &&
member.isFinal() &&
member.isPrivate()) {
// We have the correct signature
spfDef = member.getMemberDefinition();
} else {
// Bad signature...
failedConstraint(4,quiet,stack,getQualifiedName());
return false;
}
}
}
}
// If we do not have a serialPersistentField,
// there's nothing to do, so return with no error...
if (spfDef == null) {
return true;
}
// Ok, now we must examine the contents of the array -
// then validate them...
Hashtable fields = getPersistentFields(clz);
boolean result = true;
for (int i = 0; i < members.length; i++) {
String fieldName = members[i].getName();
String fieldType = members[i].getType().getSignature();
// Is this field present in the array?
String type = (String) fields.get(fieldName);
if (type == null) {
// No, so mark it transient...
members[i].setTransient();
} else {
// Yes, does the type match?
if (type.equals(fieldType)) {
// Yes, so remove it from the fields table...
fields.remove(fieldName);
} else {
// No, so error...
result = false;
failedConstraint(2,quiet,stack,fieldName,getQualifiedName());
}
}
}
// Ok, we've checked all of our fields. Are there any left in the "array"?
// If so, it's an error...
if (result && fields.size() > 0) {
result = false;
failedConstraint(9,quiet,stack,getQualifiedName());
}
// Return result...
return result;
}
/**
* Get the names and types of all the persistent fields of a Class.
*/
private Hashtable getPersistentFields (Class clz) {
Hashtable result = new Hashtable();
ObjectStreamClass osc = ObjectStreamClass.lookup(clz);
if (osc != null) {
ObjectStreamField[] fields = osc.getFields();
for (int i = 0; i < fields.length; i++) {
String typeSig;
String typePrefix = String.valueOf(fields[i].getTypeCode());
if (fields[i].isPrimitive()) {
typeSig = typePrefix;
} else {
if (fields[i].getTypeCode() == '[') {
typePrefix = "";
}
typeSig = typePrefix + fields[i].getType().getName().replace('.','/');
if (typeSig.endsWith(";")) {
typeSig = typeSig.substring(0,typeSig.length()-1);
}
}
result.put(fields[i].getName(),typeSig);
}
}
return result;
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2003, 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.
*/
package sun.rmi.rmic.newrmic;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.RootDoc;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static sun.rmi.rmic.newrmic.Constants.*;
/**
* The environment for an rmic compilation batch.
*
* A BatchEnvironment contains a RootDoc, which is the entry point
* into the doclet environment for the associated rmic compilation
* batch. A BatchEnvironment collects the source files generated
* during the batch's execution, for eventual source code compilation
* and, possibly, deletion. Errors that occur during generation
* activity should be reported through the BatchEnvironment's "error"
* method.
*
* A protocol-specific generator class may require the use of a
* particular BatchEnvironment subclass for enhanced environment
* functionality. A BatchEnvironment subclass must declare a
* public constructor with one parameter of type RootDoc.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
public class BatchEnvironment {
private final RootDoc rootDoc;
/** cached ClassDoc for certain types used by rmic */
private final ClassDoc docRemote;
private final ClassDoc docException;
private final ClassDoc docRemoteException;
private final ClassDoc docRuntimeException;
private boolean verbose = false;
private final List<File> generatedFiles = new ArrayList<File>();
/**
* Creates a new BatchEnvironment with the specified RootDoc.
**/
public BatchEnvironment(RootDoc rootDoc) {
this.rootDoc = rootDoc;
/*
* Initialize cached ClassDoc for types used by rmic. Note
* that any of these could be null if the boot class path is
* incorrect, which could cause a NullPointerException later.
*/
docRemote = rootDoc().classNamed(REMOTE);
docException = rootDoc().classNamed(EXCEPTION);
docRemoteException = rootDoc().classNamed(REMOTE_EXCEPTION);
docRuntimeException = rootDoc().classNamed(RUNTIME_EXCEPTION);
}
/**
* Returns the RootDoc for this environment.
**/
public RootDoc rootDoc() {
return rootDoc;
}
public ClassDoc docRemote() { return docRemote; }
public ClassDoc docException() { return docException; }
public ClassDoc docRemoteException() { return docRemoteException; }
public ClassDoc docRuntimeException() { return docRuntimeException; }
/**
* Sets this environment's verbosity status.
**/
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
/**
* Returns this environment's verbosity status.
**/
public boolean verbose() {
return verbose;
}
/**
* Adds the specified file to the list of source files generated
* during this batch.
**/
public void addGeneratedFile(File file) {
generatedFiles.add(file);
}
/**
* Returns the list of files generated during this batch.
**/
public List<File> generatedFiles() {
return Collections.unmodifiableList(generatedFiles);
}
/**
* Outputs the specified (non-error) message.
**/
public void output(String msg) {
rootDoc.printNotice(msg);
}
/**
* Reports an error using the specified resource key and text
* formatting arguments.
**/
public void error(String key, String... args) {
rootDoc.printError(Resources.getText(key, args));
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2003, 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.
*/
package sun.rmi.rmic.newrmic;
/**
* Constants potentially useful to all rmic generators.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
public final class Constants {
private Constants() { throw new AssertionError(); }
/*
* fully-qualified names of types used by rmic
*/
public static final String REMOTE = "java.rmi.Remote";
public static final String EXCEPTION = "java.lang.Exception";
public static final String REMOTE_EXCEPTION = "java.rmi.RemoteException";
public static final String RUNTIME_EXCEPTION = "java.lang.RuntimeException";
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2003, 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.
*/
package sun.rmi.rmic.newrmic;
import com.sun.javadoc.ClassDoc;
import java.io.File;
import java.util.Set;
/**
* The interface to rmic back end implementations. Classes that
* implement this interface correspond to the various generation modes
* of rmic (JRMP, IIOP, IDL, etc.).
*
* A Generator instance corresponds to a particular rmic compilation
* batch, and its instance state represents the generator-specific
* command line options for that batch. Main will instantiate a
* generator class when the command line arguments indicate selection
* of the corresponding generation mode. Main will then invoke the
* "parseArgs" method to allow the generator to process any
* generator-specific command line options and set its instance state
* accordingly.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
public interface Generator {
/**
* Processes the command line options specific to this generator.
* Processed options are set to null in the specified array.
* Returns true if successful or false if an error occurs. Errors
* are output to the specific Main instance.
**/
public boolean parseArgs(String[] args, Main main);
/**
* Returns the most specific environment class required by this
* generator.
**/
public Class<? extends BatchEnvironment> envClass();
/**
* Returns the names of the classes that must be available through
* the doclet API in order for this generator to function.
**/
public Set<String> bootstrapClassNames();
/**
* Generates the protocol-specific rmic output files for the
* specified remote class. This method is invoked once for each
* class or interface specified on the command line for the rmic
* compilation batch associated with this instance.
*
* Any generated source files (to be compiled with javac) are
* passed to the addGeneratedFile method of the specified
* BatchEnvironment.
**/
public void generate(BatchEnvironment env,
ClassDoc inputClass,
File destDir);
}

View File

@@ -0,0 +1,291 @@
/*
* Copyright (c) 2003, 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.
*/
package sun.rmi.rmic.newrmic;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.IOException;
/**
* A BufferedWriter that supports automatic indentation of lines of
* text written to the underlying Writer.
*
* Methods are provided for compact/convenient indenting in and out,
* writing text, and writing lines of text in various combinations.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
public class IndentingWriter extends BufferedWriter {
/** number of spaces to change indent when indenting in or out */
private final int indentStep;
/** number of spaces to convert into tabs (use MAX_VALUE to disable) */
private final int tabSize;
/** true if the next character written is the first on a line */
private boolean beginningOfLine = true;
/** current number of spaces to prepend to lines */
private int currentIndent = 0;
/**
* Creates a new IndentingWriter that writes indented text to the
* given Writer. Use the default indent step of four spaces.
**/
public IndentingWriter(Writer out) {
this(out, 4);
}
/**
* Creates a new IndentingWriter that writes indented text to the
* given Writer and uses the supplied indent step.
**/
public IndentingWriter(Writer out, int indentStep) {
this(out, indentStep, 8);
}
/**
* Creates a new IndentingWriter that writes indented text to the
* given Writer and uses the supplied indent step and tab size.
**/
public IndentingWriter(Writer out, int indentStep, int tabSize) {
super(out);
if (indentStep < 0) {
throw new IllegalArgumentException("negative indent step");
}
if (tabSize < 0) {
throw new IllegalArgumentException("negative tab size");
}
this.indentStep = indentStep;
this.tabSize = tabSize;
}
/**
* Writes a single character.
**/
public void write(int c) throws IOException {
checkWrite();
super.write(c);
}
/**
* Writes a portion of an array of characters.
**/
public void write(char[] cbuf, int off, int len) throws IOException {
if (len > 0) {
checkWrite();
}
super.write(cbuf, off, len);
}
/**
* Writes a portion of a String.
**/
public void write(String s, int off, int len) throws IOException {
if (len > 0) {
checkWrite();
}
super.write(s, off, len);
}
/**
* Writes a line separator. The next character written will be
* preceded by an indent.
**/
public void newLine() throws IOException {
super.newLine();
beginningOfLine = true;
}
/**
* Checks if an indent needs to be written before writing the next
* character.
*
* The indent generation is optimized (and made consistent with
* certain coding conventions) by condensing groups of eight
* spaces into tab characters.
**/
protected void checkWrite() throws IOException {
if (beginningOfLine) {
beginningOfLine = false;
int i = currentIndent;
while (i >= tabSize) {
super.write('\t');
i -= tabSize;
}
while (i > 0) {
super.write(' ');
i--;
}
}
}
/**
* Increases the current indent by the indent step.
**/
protected void indentIn() {
currentIndent += indentStep;
}
/**
* Decreases the current indent by the indent step.
**/
protected void indentOut() {
currentIndent -= indentStep;
if (currentIndent < 0)
currentIndent = 0;
}
/**
* Indents in.
**/
public void pI() {
indentIn();
}
/**
* Indents out.
**/
public void pO() {
indentOut();
}
/**
* Writes string.
**/
public void p(String s) throws IOException {
write(s);
}
/**
* Ends current line.
**/
public void pln() throws IOException {
newLine();
}
/**
* Writes string; ends current line.
**/
public void pln(String s) throws IOException {
p(s);
pln();
}
/**
* Writes string; ends current line; indents in.
**/
public void plnI(String s) throws IOException {
p(s);
pln();
pI();
}
/**
* Indents out; writes string.
**/
public void pO(String s) throws IOException {
pO();
p(s);
}
/**
* Indents out; writes string; ends current line.
**/
public void pOln(String s) throws IOException {
pO(s);
pln();
}
/**
* Indents out; writes string; ends current line; indents in.
*
* This method is useful for generating lines of code that both
* end and begin nested blocks, like "} else {".
**/
public void pOlnI(String s) throws IOException {
pO(s);
pln();
pI();
}
/**
* Writes object.
**/
public void p(Object o) throws IOException {
write(o.toString());
}
/**
* Writes object; ends current line.
**/
public void pln(Object o) throws IOException {
p(o.toString());
pln();
}
/**
* Writes object; ends current line; indents in.
**/
public void plnI(Object o) throws IOException {
p(o.toString());
pln();
pI();
}
/**
* Indents out; writes object.
**/
public void pO(Object o) throws IOException {
pO();
p(o.toString());
}
/**
* Indents out; writes object; ends current line.
**/
public void pOln(Object o) throws IOException {
pO(o.toString());
pln();
}
/**
* Indents out; writes object; ends current line; indents in.
*
* This method is useful for generating lines of code that both
* end and begin nested blocks, like "} else {".
**/
public void pOlnI(Object o) throws IOException {
pO(o.toString());
pln();
pI();
}
}

View File

@@ -0,0 +1,689 @@
/*
* Copyright (c) 2003, 2012, 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.
*/
package sun.rmi.rmic.newrmic;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.RootDoc;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import sun.rmi.rmic.newrmic.jrmp.JrmpGenerator;
import sun.tools.util.CommandLine;
/**
* The rmic front end. This class contains the "main" method for rmic
* command line invocation.
*
* A Main instance contains the stream to output error messages and
* other diagnostics to.
*
* An rmic compilation batch (for example, one rmic command line
* invocation) is executed by invoking the "compile" method of a Main
* instance.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* NOTE: If and when there is a J2SE API for invoking SDK tools, this
* class should be updated to support that API.
*
* NOTE: This class is the front end for a "new" rmic implementation,
* which uses javadoc and the doclet API for reading class files and
* javac for compiling generated source files. This implementation is
* incomplete: it lacks any CORBA-based back end implementations, and
* thus the command line options "-idl", "-iiop", and their related
* options are not yet supported. The front end for the "old",
* oldjavac-based rmic implementation is sun.rmi.rmic.Main.
*
* @author Peter Jones
**/
public class Main {
/*
* Implementation note:
*
* In order to use the doclet API to read class files, much of
* this implementation of rmic executes as a doclet within an
* invocation of javadoc. This class is used as the doclet class
* for such javadoc invocations, via its static "start" and
* "optionLength" methods. There is one javadoc invocation per
* rmic compilation batch.
*
* The only guaranteed way to pass data to a doclet through a
* javadoc invocation is through doclet-specific options on the
* javadoc "command line". Rather than passing numerous pieces of
* individual data in string form as javadoc options, we use a
* single doclet-specific option ("-batchID") to pass a numeric
* identifier that uniquely identifies the rmic compilation batch
* that the javadoc invocation is for, and that identifier can
* then be used as a key in a global table to retrieve an object
* containing all of batch-specific data (rmic command line
* arguments, etc.).
*/
/** guards "batchCount" */
private static final Object batchCountLock = new Object();
/** number of batches run; used to generated batch IDs */
private static long batchCount = 0;
/** maps batch ID to batch data */
private static final Map<Long,Batch> batchTable =
Collections.synchronizedMap(new HashMap<Long,Batch>());
/** stream to output error messages and other diagnostics to */
private final PrintStream out;
/** name of this program, to use in error messages */
private final String program;
/**
* Command line entry point.
**/
public static void main(String[] args) {
Main rmic = new Main(System.err, "rmic");
System.exit(rmic.compile(args) ? 0 : 1);
}
/**
* Creates a Main instance that writes output to the specified
* stream. The specified program name is used in error messages.
**/
public Main(OutputStream out, String program) {
this.out = out instanceof PrintStream ?
(PrintStream) out : new PrintStream(out);
this.program = program;
}
/**
* Compiles a batch of input classes, as given by the specified
* command line arguments. Protocol-specific generators are
* determined by the choice options on the command line. Returns
* true if successful, or false if an error occurred.
*
* NOTE: This method is retained for transitional consistency with
* previous implementations.
**/
public boolean compile(String[] args) {
long startTime = System.currentTimeMillis();
long batchID;
synchronized (batchCountLock) {
batchID = batchCount++; // assign batch ID
}
// process command line
Batch batch = parseArgs(args);
if (batch == null) {
return false; // terminate if error occurred
}
/*
* With the batch data retrievable in the global table, run
* javadoc to continue the rest of the batch's compliation as
* a doclet.
*/
boolean status;
try {
batchTable.put(batchID, batch);
status = invokeJavadoc(batch, batchID);
} finally {
batchTable.remove(batchID);
}
if (batch.verbose) {
long deltaTime = System.currentTimeMillis() - startTime;
output(Resources.getText("rmic.done_in",
Long.toString(deltaTime)));
}
return status;
}
/**
* Prints the specified string to the output stream of this Main
* instance.
**/
public void output(String msg) {
out.println(msg);
}
/**
* Prints an error message to the output stream of this Main
* instance. The first argument is used as a key in rmic's
* resource bundle, and the rest of the arguments are used as
* arguments in the formatting of the resource string.
**/
public void error(String msg, String... args) {
output(Resources.getText(msg, args));
}
/**
* Prints rmic's usage message to the output stream of this Main
* instance.
*
* This method is public so that it can be used by the "parseArgs"
* methods of Generator implementations.
**/
public void usage() {
error("rmic.usage", program);
}
/**
* Processes rmic command line arguments. Returns a Batch object
* representing the command line arguments if successful, or null
* if an error occurred. Processed elements of the args array are
* set to null.
**/
private Batch parseArgs(String[] args) {
Batch batch = new Batch();
/*
* Pre-process command line for @file arguments.
*/
try {
args = CommandLine.parse(args);
} catch (FileNotFoundException e) {
error("rmic.cant.read", e.getMessage());
return null;
} catch (IOException e) {
e.printStackTrace(out);
return null;
}
for (int i = 0; i < args.length; i++) {
if (args[i] == null) {
// already processed by a generator
continue;
} else if (args[i].equals("-Xnew")) {
// we're already using the "new" implementation
args[i] = null;
} else if (args[i].equals("-show")) {
// obselete: fail
error("rmic.option.unsupported", args[i]);
usage();
return null;
} else if (args[i].equals("-O")) {
// obselete: warn but tolerate
error("rmic.option.unsupported", args[i]);
args[i] = null;
} else if (args[i].equals("-debug")) {
// obselete: warn but tolerate
error("rmic.option.unsupported", args[i]);
args[i] = null;
} else if (args[i].equals("-depend")) {
// obselete: warn but tolerate
// REMIND: should this fail instead?
error("rmic.option.unsupported", args[i]);
args[i] = null;
} else if (args[i].equals("-keep") ||
args[i].equals("-keepgenerated"))
{
batch.keepGenerated = true;
args[i] = null;
} else if (args[i].equals("-g")) {
batch.debug = true;
args[i] = null;
} else if (args[i].equals("-nowarn")) {
batch.noWarn = true;
args[i] = null;
} else if (args[i].equals("-nowrite")) {
batch.noWrite = true;
args[i] = null;
} else if (args[i].equals("-verbose")) {
batch.verbose = true;
args[i] = null;
} else if (args[i].equals("-Xnocompile")) {
batch.noCompile = true;
batch.keepGenerated = true;
args[i] = null;
} else if (args[i].equals("-bootclasspath")) {
if ((i + 1) >= args.length) {
error("rmic.option.requires.argument", args[i]);
usage();
return null;
}
if (batch.bootClassPath != null) {
error("rmic.option.already.seen", args[i]);
usage();
return null;
}
args[i] = null;
batch.bootClassPath = args[++i];
assert batch.bootClassPath != null;
args[i] = null;
} else if (args[i].equals("-extdirs")) {
if ((i + 1) >= args.length) {
error("rmic.option.requires.argument", args[i]);
usage();
return null;
}
if (batch.extDirs != null) {
error("rmic.option.already.seen", args[i]);
usage();
return null;
}
args[i] = null;
batch.extDirs = args[++i];
assert batch.extDirs != null;
args[i] = null;
} else if (args[i].equals("-classpath")) {
if ((i + 1) >= args.length) {
error("rmic.option.requires.argument", args[i]);
usage();
return null;
}
if (batch.classPath != null) {
error("rmic.option.already.seen", args[i]);
usage();
return null;
}
args[i] = null;
batch.classPath = args[++i];
assert batch.classPath != null;
args[i] = null;
} else if (args[i].equals("-d")) {
if ((i + 1) >= args.length) {
error("rmic.option.requires.argument", args[i]);
usage();
return null;
}
if (batch.destDir != null) {
error("rmic.option.already.seen", args[i]);
usage();
return null;
}
args[i] = null;
batch.destDir = new File(args[++i]);
assert batch.destDir != null;
args[i] = null;
if (!batch.destDir.exists()) {
error("rmic.no.such.directory", batch.destDir.getPath());
usage();
return null;
}
} else if (args[i].equals("-v1.1") ||
args[i].equals("-vcompat") ||
args[i].equals("-v1.2"))
{
Generator gen = new JrmpGenerator();
batch.generators.add(gen);
// JrmpGenerator only requires base BatchEnvironment class
if (!gen.parseArgs(args, this)) {
return null;
}
} else if (args[i].equalsIgnoreCase("-iiop")) {
error("rmic.option.unimplemented", args[i]);
return null;
// Generator gen = new IiopGenerator();
// batch.generators.add(gen);
// if (!batch.envClass.isAssignableFrom(gen.envClass())) {
// error("rmic.cannot.use.both",
// batch.envClass.getName(), gen.envClass().getName());
// return null;
// }
// batch.envClass = gen.envClass();
// if (!gen.parseArgs(args, this)) {
// return null;
// }
} else if (args[i].equalsIgnoreCase("-idl")) {
error("rmic.option.unimplemented", args[i]);
return null;
// see implementation sketch above
} else if (args[i].equalsIgnoreCase("-xprint")) {
error("rmic.option.unimplemented", args[i]);
return null;
// see implementation sketch above
}
}
/*
* At this point, all that remains non-null in the args
* array are input class names or illegal options.
*/
for (int i = 0; i < args.length; i++) {
if (args[i] != null) {
if (args[i].startsWith("-")) {
error("rmic.no.such.option", args[i]);
usage();
return null;
} else {
batch.classes.add(args[i]);
}
}
}
if (batch.classes.isEmpty()) {
usage();
return null;
}
/*
* If options did not specify at least one protocol-specific
* generator, then JRMP is the default.
*/
if (batch.generators.isEmpty()) {
batch.generators.add(new JrmpGenerator());
}
return batch;
}
/**
* Doclet class entry point.
**/
public static boolean start(RootDoc rootDoc) {
/*
* Find batch ID among javadoc options, and retrieve
* corresponding batch data from global table.
*/
long batchID = -1;
for (String[] option : rootDoc.options()) {
if (option[0].equals("-batchID")) {
try {
batchID = Long.parseLong(option[1]);
} catch (NumberFormatException e) {
throw new AssertionError(e);
}
}
}
Batch batch = batchTable.get(batchID);
assert batch != null;
/*
* Construct batch environment using class agreed upon by
* generator implementations.
*/
BatchEnvironment env;
try {
Constructor<? extends BatchEnvironment> cons =
batch.envClass.getConstructor(new Class<?>[] { RootDoc.class });
env = cons.newInstance(rootDoc);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
throw new AssertionError(e);
}
env.setVerbose(batch.verbose);
/*
* Determine the destination directory (the top of the package
* hierarchy) for the output of this batch; if no destination
* directory was specified on the command line, then the
* default is the current working directory.
*/
File destDir = batch.destDir;
if (destDir == null) {
destDir = new File(System.getProperty("user.dir"));
}
/*
* Run each input class through each generator.
*/
for (String inputClassName : batch.classes) {
ClassDoc inputClass = rootDoc.classNamed(inputClassName);
try {
for (Generator gen : batch.generators) {
gen.generate(env, inputClass, destDir);
}
} catch (NullPointerException e) {
/*
* We assume that this means that some class that was
* needed (perhaps even a bootstrap class) was not
* found, and that javadoc has already reported this
* as an error. There is nothing for us to do here
* but try to continue with the next input class.
*
* REMIND: More explicit error checking throughout
* would be preferable, however.
*/
}
}
/*
* Compile any generated source files, if configured to do so.
*/
boolean status = true;
List<File> generatedFiles = env.generatedFiles();
if (!batch.noCompile && !batch.noWrite && !generatedFiles.isEmpty()) {
status = batch.enclosingMain().invokeJavac(batch, generatedFiles);
}
/*
* Delete any generated source files, if configured to do so.
*/
if (!batch.keepGenerated) {
for (File file : generatedFiles) {
file.delete();
}
}
return status;
}
/**
* Doclet class method that indicates that this doclet class
* recognizes (only) the "-batchID" option on the javadoc command
* line, and that the "-batchID" option comprises two arguments on
* the javadoc command line.
**/
public static int optionLength(String option) {
if (option.equals("-batchID")) {
return 2;
} else {
return 0;
}
}
/**
* Runs the javadoc tool to invoke this class as a doclet, passing
* command line options derived from the specified batch data and
* indicating the specified batch ID.
*
* NOTE: This method currently uses a J2SE-internal API to run
* javadoc. If and when there is a J2SE API for invoking SDK
* tools, this method should be updated to use that API instead.
**/
private boolean invokeJavadoc(Batch batch, long batchID) {
List<String> javadocArgs = new ArrayList<String>();
// include all types, regardless of language-level access
javadocArgs.add("-private");
// inputs are class names, not source files
javadocArgs.add("-Xclasses");
// reproduce relevant options from rmic invocation
if (batch.verbose) {
javadocArgs.add("-verbose");
}
if (batch.bootClassPath != null) {
javadocArgs.add("-bootclasspath");
javadocArgs.add(batch.bootClassPath);
}
if (batch.extDirs != null) {
javadocArgs.add("-extdirs");
javadocArgs.add(batch.extDirs);
}
if (batch.classPath != null) {
javadocArgs.add("-classpath");
javadocArgs.add(batch.classPath);
}
// specify batch ID
javadocArgs.add("-batchID");
javadocArgs.add(Long.toString(batchID));
/*
* Run javadoc on union of rmic input classes and all
* generators' bootstrap classes, so that they will all be
* available to the doclet code.
*/
Set<String> classNames = new HashSet<String>();
for (Generator gen : batch.generators) {
classNames.addAll(gen.bootstrapClassNames());
}
classNames.addAll(batch.classes);
for (String s : classNames) {
javadocArgs.add(s);
}
// run javadoc with our program name and output stream
int status = com.sun.tools.javadoc.Main.execute(
program,
new PrintWriter(out, true),
new PrintWriter(out, true),
new PrintWriter(out, true),
this.getClass().getName(), // doclet class is this class
javadocArgs.toArray(new String[javadocArgs.size()]));
return status == 0;
}
/**
* Runs the javac tool to compile the specified source files,
* passing command line options derived from the specified batch
* data.
*
* NOTE: This method currently uses a J2SE-internal API to run
* javac. If and when there is a J2SE API for invoking SDK tools,
* this method should be updated to use that API instead.
**/
private boolean invokeJavac(Batch batch, List<File> files) {
List<String> javacArgs = new ArrayList<String>();
// rmic never wants to display javac warnings
javacArgs.add("-nowarn");
// reproduce relevant options from rmic invocation
if (batch.debug) {
javacArgs.add("-g");
}
if (batch.verbose) {
javacArgs.add("-verbose");
}
if (batch.bootClassPath != null) {
javacArgs.add("-bootclasspath");
javacArgs.add(batch.bootClassPath);
}
if (batch.extDirs != null) {
javacArgs.add("-extdirs");
javacArgs.add(batch.extDirs);
}
if (batch.classPath != null) {
javacArgs.add("-classpath");
javacArgs.add(batch.classPath);
}
/*
* For now, rmic still always produces class files that have a
* class file format version compatible with JDK 1.1.
*/
javacArgs.add("-source");
javacArgs.add("1.3");
javacArgs.add("-target");
javacArgs.add("1.1");
// add source files to compile
for (File file : files) {
javacArgs.add(file.getPath());
}
// run javac with our output stream
int status = com.sun.tools.javac.Main.compile(
javacArgs.toArray(new String[javacArgs.size()]),
new PrintWriter(out, true));
return status == 0;
}
/**
* The data for an rmic compliation batch: the processed command
* line arguments.
**/
private class Batch {
boolean keepGenerated = false; // -keep or -keepgenerated
boolean debug = false; // -g
boolean noWarn = false; // -nowarn
boolean noWrite = false; // -nowrite
boolean verbose = false; // -verbose
boolean noCompile = false; // -Xnocompile
String bootClassPath = null; // -bootclasspath
String extDirs = null; // -extdirs
String classPath = null; // -classpath
File destDir = null; // -d
List<Generator> generators = new ArrayList<Generator>();
Class<? extends BatchEnvironment> envClass = BatchEnvironment.class;
List<String> classes = new ArrayList<String>();
Batch() { }
/**
* Returns the Main instance for this batch.
**/
Main enclosingMain() {
return Main.this;
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2003, 2012, 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.
*/
package sun.rmi.rmic.newrmic;
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Provides resource support for rmic.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
public final class Resources {
private static ResourceBundle resources = null;
private static ResourceBundle resourcesExt = null;
static {
try {
resources =
ResourceBundle.getBundle("sun.rmi.rmic.resources.rmic");
} catch (MissingResourceException e) {
// gracefully handle this later
}
try {
resourcesExt =
ResourceBundle.getBundle("sun.rmi.rmic.resources.rmicext");
} catch (MissingResourceException e) {
// OK if this isn't found
}
}
private Resources() { throw new AssertionError(); }
/**
* Returns the text of the rmic resource for the specified key
* formatted with the specified arguments.
**/
public static String getText(String key, String... args) {
String format = getString(key);
if (format == null) {
format = "missing resource key: key = \"" + key + "\", " +
"arguments = \"{0}\", \"{1}\", \"{2}\"";
}
return MessageFormat.format(format, (Object[]) args);
}
/**
* Returns the rmic resource string for the specified key.
**/
private static String getString(String key) {
if (resourcesExt != null) {
try {
return resourcesExt.getString(key);
} catch (MissingResourceException e) {
}
}
if (resources != null) {
try {
return resources.getString(key);
} catch (MissingResourceException e) {
return null;
}
}
return "missing resource bundle: key = \"" + key + "\", " +
"arguments = \"{0}\", \"{1}\", \"{2}\"";
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2003, 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.
*/
package sun.rmi.rmic.newrmic.jrmp;
/**
* Constants specific to the JRMP rmic generator.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
final class Constants {
private Constants() { throw new AssertionError(); }
/*
* fully-qualified names of types used by rmic
*/
static final String REMOTE_OBJECT = "java.rmi.server.RemoteObject";
static final String REMOTE_STUB = "java.rmi.server.RemoteStub";
static final String REMOTE_REF = "java.rmi.server.RemoteRef";
static final String OPERATION = "java.rmi.server.Operation";
static final String SKELETON = "java.rmi.server.Skeleton";
static final String SKELETON_MISMATCH_EXCEPTION =
"java.rmi.server.SkeletonMismatchException";
static final String REMOTE_CALL = "java.rmi.server.RemoteCall";
static final String MARSHAL_EXCEPTION = "java.rmi.MarshalException";
static final String UNMARSHAL_EXCEPTION = "java.rmi.UnmarshalException";
static final String UNEXPECTED_EXCEPTION = "java.rmi.UnexpectedException";
/*
* stub protocol versions
*/
enum StubVersion { V1_1, VCOMPAT, V1_2 };
/*
* serialVersionUID for all stubs that can use 1.2 protocol
*/
static final long STUB_SERIAL_VERSION_UID = 2;
/*
* version number used to seed interface hash computation
*/
static final int INTERFACE_HASH_STUB_VERSION = 1;
}

View File

@@ -0,0 +1,226 @@
/*
* Copyright (c) 2003, 2005, 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.
*/
package sun.rmi.rmic.newrmic.jrmp;
import com.sun.javadoc.ClassDoc;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import sun.rmi.rmic.newrmic.BatchEnvironment;
import sun.rmi.rmic.newrmic.Generator;
import sun.rmi.rmic.newrmic.IndentingWriter;
import sun.rmi.rmic.newrmic.Main;
import sun.rmi.rmic.newrmic.Resources;
import static sun.rmi.rmic.newrmic.jrmp.Constants.*;
/**
* JRMP rmic back end; generates source code for JRMP stub and
* skeleton classes.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
public class JrmpGenerator implements Generator {
private static final Map<String,StubVersion> versionOptions =
new HashMap<String,StubVersion>();
static {
versionOptions.put("-v1.1", StubVersion.V1_1);
versionOptions.put("-vcompat", StubVersion.VCOMPAT);
versionOptions.put("-v1.2", StubVersion.V1_2);
}
private static final Set<String> bootstrapClassNames =
new HashSet<String>();
static {
bootstrapClassNames.add("java.lang.Exception");
bootstrapClassNames.add("java.rmi.Remote");
bootstrapClassNames.add("java.rmi.RemoteException");
bootstrapClassNames.add("java.lang.RuntimeException");
};
/** version of the JRMP stub protocol to generate code for */
private StubVersion version = StubVersion.V1_2; // default is -v1.2
/**
* Creates a new JrmpGenerator.
**/
public JrmpGenerator() { }
/**
* The JRMP generator recognizes command line options for
* selecting the JRMP stub protocol version to generate classes
* for. Only one such option is allowed.
**/
public boolean parseArgs(String[] args, Main main) {
String explicitVersion = null;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (versionOptions.containsKey(arg)) {
if (explicitVersion != null && !explicitVersion.equals(arg)) {
main.error("rmic.cannot.use.both", explicitVersion, arg);
return false;
}
explicitVersion = arg;
version = versionOptions.get(arg);
args[i] = null;
}
}
return true;
}
/**
* The JRMP generator does not require an environment class more
* specific than BatchEnvironment.
**/
public Class<? extends BatchEnvironment> envClass() {
return BatchEnvironment.class;
}
public Set<String> bootstrapClassNames() {
return Collections.unmodifiableSet(bootstrapClassNames);
}
/**
* Generates the source file(s) for the JRMP stub class and
* (optionally) skeleton class for the specified remote
* implementation class.
**/
public void generate(BatchEnvironment env,
ClassDoc inputClass,
File destDir)
{
RemoteClass remoteClass = RemoteClass.forClass(env, inputClass);
if (remoteClass == null) {
return; // an error must have occurred
}
StubSkeletonWriter writer =
new StubSkeletonWriter(env, remoteClass, version);
File stubFile = sourceFileForClass(writer.stubClassName(), destDir);
try {
IndentingWriter out = new IndentingWriter(
new OutputStreamWriter(new FileOutputStream(stubFile)));
writer.writeStub(out);
out.close();
if (env.verbose()) {
env.output(Resources.getText("rmic.wrote",
stubFile.getPath()));
}
env.addGeneratedFile(stubFile);
} catch (IOException e) {
env.error("rmic.cant.write", stubFile.toString());
return;
}
File skeletonFile =
sourceFileForClass(writer.skeletonClassName(), destDir);
if (version == StubVersion.V1_1 ||
version == StubVersion.VCOMPAT)
{
try {
IndentingWriter out = new IndentingWriter(
new OutputStreamWriter(
new FileOutputStream(skeletonFile)));
writer.writeSkeleton(out);
out.close();
if (env.verbose()) {
env.output(Resources.getText("rmic.wrote",
skeletonFile.getPath()));
}
env.addGeneratedFile(skeletonFile);
} catch (IOException e) {
env.error("rmic.cant.write", skeletonFile.toString());
return;
}
} else {
/*
* If skeleton files are not being generated for this run,
* delete old skeleton source or class files for this
* remote implementation class that were (presumably) left
* over from previous runs, to avoid user confusion from
* extraneous or inconsistent generated files.
*/
File skeletonClassFile =
classFileForClass(writer.skeletonClassName(), destDir);
skeletonFile.delete(); // ignore failures (no big deal)
skeletonClassFile.delete();
}
}
/**
* Returns the File object to be used as the source file for a
* class with the specified binary name, with the specified
* destination directory as the top of the package hierarchy.
**/
private File sourceFileForClass(String binaryName, File destDir) {
return fileForClass(binaryName, destDir, ".java");
}
/**
* Returns the File object to be used as the class file for a
* class with the specified binary name, with the supplied
* destination directory as the top of the package hierarchy.
**/
private File classFileForClass(String binaryName, File destDir) {
return fileForClass(binaryName, destDir, ".class");
}
private File fileForClass(String binaryName, File destDir, String ext) {
int i = binaryName.lastIndexOf('.');
String classFileName = binaryName.substring(i + 1) + ext;
if (i != -1) {
String packageName = binaryName.substring(0, i);
String packagePath = packageName.replace('.', File.separatorChar);
File packageDir = new File(destDir, packagePath);
/*
* Make sure that the directory for this package exists.
* We assume that the caller has verified that the top-
* level destination directory exists, so we need not
* worry about creating it unintentionally.
*/
if (!packageDir.exists()) {
packageDir.mkdirs();
}
return new File(packageDir, classFileName);
} else {
return new File(destDir, classFileName);
}
}
}

View File

@@ -0,0 +1,710 @@
/*
* Copyright (c) 2003, 2008, 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.
*/
package sun.rmi.rmic.newrmic.jrmp;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.Type;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.DigestOutputStream;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import sun.rmi.rmic.newrmic.BatchEnvironment;
import static sun.rmi.rmic.newrmic.Constants.*;
import static sun.rmi.rmic.newrmic.jrmp.Constants.*;
/**
* Encapsulates RMI-specific information about a remote implementation
* class (a class that implements one or more remote interfaces).
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
final class RemoteClass {
/** rmic environment for this object */
private final BatchEnvironment env;
/** the remote implementation class this object represents */
private final ClassDoc implClass;
/** remote interfaces implemented by this class */
private ClassDoc[] remoteInterfaces;
/** the remote methods of this class */
private Method[] remoteMethods;
/** stub/skeleton "interface hash" for this class */
private long interfaceHash;
/**
* Creates a RemoteClass instance that represents the RMI-specific
* information about the specified remote implementation class.
*
* If the class is not a valid remote implementation class or if
* some other error occurs, the return value will be null, and
* errors will have been reported to the supplied
* BatchEnvironment.
**/
static RemoteClass forClass(BatchEnvironment env, ClassDoc implClass) {
RemoteClass remoteClass = new RemoteClass(env, implClass);
if (remoteClass.init()) {
return remoteClass;
} else {
return null;
}
}
/**
* Creates a RemoteClass instance for the specified class. The
* resulting object is not yet initialized.
**/
private RemoteClass(BatchEnvironment env, ClassDoc implClass) {
this.env = env;
this.implClass = implClass;
}
/**
* Returns the ClassDoc for this remote implementation class.
**/
ClassDoc classDoc() {
return implClass;
}
/**
* Returns the remote interfaces implemented by this remote
* implementation class.
*
* A remote interface is an interface that is a subinterface of
* java.rmi.Remote. The remote interfaces of a class are the
* direct superinterfaces of the class and all of its superclasses
* that are remote interfaces.
*
* The order of the array returned is arbitrary, and some elements
* may be superfluous (i.e., superinterfaces of other interfaces
* in the array).
**/
ClassDoc[] remoteInterfaces() {
return remoteInterfaces.clone();
}
/**
* Returns an array of RemoteClass.Method objects representing all
* of the remote methods of this remote implementation class (all
* of the member methods of the class's remote interfaces).
*
* The methods in the array are ordered according to a comparison
* of strings consisting of their name followed by their
* descriptor, so each method's index in the array corresponds to
* its "operation number" in the JDK 1.1 version of the JRMP
* stub/skeleton protocol.
**/
Method[] remoteMethods() {
return remoteMethods.clone();
}
/**
* Returns the "interface hash" used to match a stub/skeleton pair
* for this remote implementation class in the JDK 1.1 version of
* the JRMP stub/skeleton protocol.
**/
long interfaceHash() {
return interfaceHash;
}
/**
* Validates this remote implementation class and computes the
* RMI-specific information. Returns true if successful, or false
* if an error occurred.
**/
private boolean init() {
/*
* Verify that it is really a class, not an interface.
*/
if (implClass.isInterface()) {
env.error("rmic.cant.make.stubs.for.interface",
implClass.qualifiedName());
return false;
}
/*
* Find all of the remote interfaces of our remote
* implementation class-- for each class up the superclass
* chain, add each directly-implemented interface that somehow
* extends Remote to a list.
*/
List<ClassDoc> remotesImplemented = new ArrayList<ClassDoc>();
for (ClassDoc cl = implClass; cl != null; cl = cl.superclass()) {
for (ClassDoc intf : cl.interfaces()) {
/*
* Add interface to the list if it extends Remote and
* it is not already there.
*/
if (!remotesImplemented.contains(intf) &&
intf.subclassOf(env.docRemote()))
{
remotesImplemented.add(intf);
if (env.verbose()) {
env.output("[found remote interface: " +
intf.qualifiedName() + "]");
}
}
}
/*
* Verify that the candidate remote implementation class
* implements at least one remote interface directly.
*/
if (cl == implClass && remotesImplemented.isEmpty()) {
if (implClass.subclassOf(env.docRemote())) {
/*
* This error message is used if the class does
* implement a remote interface through one of its
* superclasses, but not directly.
*/
env.error("rmic.must.implement.remote.directly",
implClass.qualifiedName());
} else {
/*
* This error message is used if the class does
* not implement a remote interface at all.
*/
env.error("rmic.must.implement.remote",
implClass.qualifiedName());
}
return false;
}
}
/*
* Convert list of remote interfaces to an array
* (order is not important for this array).
*/
remoteInterfaces =
remotesImplemented.toArray(
new ClassDoc[remotesImplemented.size()]);
/*
* Collect the methods from all of the remote interfaces into
* a table, which maps from method name-and-descriptor string
* to Method object.
*/
Map<String,Method> methods = new HashMap<String,Method>();
boolean errors = false;
for (ClassDoc intf : remotesImplemented) {
if (!collectRemoteMethods(intf, methods)) {
/*
* Continue iterating despite errors in order to
* generate more complete error report.
*/
errors = true;
}
}
if (errors) {
return false;
}
/*
* Sort table of remote methods into an array. The elements
* are sorted in ascending order of the string of the method's
* name and descriptor, so that each elements index is equal
* to its operation number in the JDK 1.1 version of the JRMP
* stub/skeleton protocol.
*/
String[] orderedKeys =
methods.keySet().toArray(new String[methods.size()]);
Arrays.sort(orderedKeys);
remoteMethods = new Method[methods.size()];
for (int i = 0; i < remoteMethods.length; i++) {
remoteMethods[i] = methods.get(orderedKeys[i]);
if (env.verbose()) {
String msg = "[found remote method <" + i + ">: " +
remoteMethods[i].operationString();
ClassDoc[] exceptions = remoteMethods[i].exceptionTypes();
if (exceptions.length > 0) {
msg += " throws ";
for (int j = 0; j < exceptions.length; j++) {
if (j > 0) {
msg += ", ";
}
msg += exceptions[j].qualifiedName();
}
}
msg += "\n\tname and descriptor = \"" +
remoteMethods[i].nameAndDescriptor();
msg += "\n\tmethod hash = " +
remoteMethods[i].methodHash() + "]";
env.output(msg);
}
}
/*
* Finally, pre-compute the interface hash to be used by
* stubs/skeletons for this remote class in the JDK 1.1
* version of the JRMP stub/skeleton protocol.
*/
interfaceHash = computeInterfaceHash();
return true;
}
/**
* Collects and validates all methods from the specified interface
* and all of its superinterfaces as remote methods. Remote
* methods are added to the supplied table. Returns true if
* successful, or false if an error occurred.
**/
private boolean collectRemoteMethods(ClassDoc intf,
Map<String,Method> table)
{
if (!intf.isInterface()) {
throw new AssertionError(
intf.qualifiedName() + " not an interface");
}
boolean errors = false;
/*
* Search interface's declared methods.
*/
nextMethod:
for (MethodDoc method : intf.methods()) {
/*
* Verify that each method throws RemoteException (or a
* superclass of RemoteException).
*/
boolean hasRemoteException = false;
for (ClassDoc ex : method.thrownExceptions()) {
if (env.docRemoteException().subclassOf(ex)) {
hasRemoteException = true;
break;
}
}
/*
* If this method did not throw RemoteException as required,
* generate the error but continue, so that multiple such
* errors can be reported.
*/
if (!hasRemoteException) {
env.error("rmic.must.throw.remoteexception",
intf.qualifiedName(),
method.name() + method.signature());
errors = true;
continue nextMethod;
}
/*
* Verify that the implementation of this method throws only
* java.lang.Exception or its subclasses (fix bugid 4092486).
* JRMP does not support remote methods throwing
* java.lang.Throwable or other subclasses.
*/
MethodDoc implMethod = findImplMethod(method);
if (implMethod != null) { // should not be null
for (ClassDoc ex : implMethod.thrownExceptions()) {
if (!ex.subclassOf(env.docException())) {
env.error("rmic.must.only.throw.exception",
implMethod.name() + implMethod.signature(),
ex.qualifiedName());
errors = true;
continue nextMethod;
}
}
}
/*
* Create RemoteClass.Method object to represent this method
* found in a remote interface.
*/
Method newMethod = new Method(method);
/*
* Store remote method's representation in the table of
* remote methods found, keyed by its name and descriptor.
*
* If the table already contains an entry with the same
* method name and descriptor, then we must replace the
* old entry with a Method object that represents a legal
* combination of the old and the new methods;
* specifically, the combined method must have a throws
* clause that contains (only) all of the checked
* exceptions that can be thrown by both the old and the
* new method (see bugid 4070653).
*/
String key = newMethod.nameAndDescriptor();
Method oldMethod = table.get(key);
if (oldMethod != null) {
newMethod = newMethod.mergeWith(oldMethod);
}
table.put(key, newMethod);
}
/*
* Recursively collect methods for all superinterfaces.
*/
for (ClassDoc superintf : intf.interfaces()) {
if (!collectRemoteMethods(superintf, table)) {
errors = true;
}
}
return !errors;
}
/**
* Returns the MethodDoc for the method of this remote
* implementation class that implements the specified remote
* method of a remote interface. Returns null if no matching
* method was found in this remote implementation class.
**/
private MethodDoc findImplMethod(MethodDoc interfaceMethod) {
String name = interfaceMethod.name();
String desc = Util.methodDescriptorOf(interfaceMethod);
for (MethodDoc implMethod : implClass.methods()) {
if (name.equals(implMethod.name()) &&
desc.equals(Util.methodDescriptorOf(implMethod)))
{
return implMethod;
}
}
return null;
}
/**
* Computes the "interface hash" of the stub/skeleton pair for
* this remote implementation class. This is the 64-bit value
* used to enforce compatibility between a stub class and a
* skeleton class in the JDK 1.1 version of the JRMP stub/skeleton
* protocol.
*
* It is calculated using the first 64 bits of an SHA digest. The
* digest is of a stream consisting of the following data:
* (int) stub version number, always 1
* for each remote method, in order of operation number:
* (UTF-8) method name
* (UTF-8) method descriptor
* for each declared exception, in alphabetical name order:
* (UTF-8) name of exception class
* (where "UTF-8" includes a 16-bit length prefix as written by
* java.io.DataOutput.writeUTF).
**/
private long computeInterfaceHash() {
long hash = 0;
ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
try {
MessageDigest md = MessageDigest.getInstance("SHA");
DataOutputStream out = new DataOutputStream(
new DigestOutputStream(sink, md));
out.writeInt(INTERFACE_HASH_STUB_VERSION);
for (Method method : remoteMethods) {
MethodDoc methodDoc = method.methodDoc();
out.writeUTF(methodDoc.name());
out.writeUTF(Util.methodDescriptorOf(methodDoc));
// descriptors already use binary names
ClassDoc exceptions[] = methodDoc.thrownExceptions();
Arrays.sort(exceptions, new ClassDocComparator());
for (ClassDoc ex : exceptions) {
out.writeUTF(Util.binaryNameOf(ex));
}
}
out.flush();
// use only the first 64 bits of the digest for the hash
byte hashArray[] = md.digest();
for (int i = 0; i < Math.min(8, hashArray.length); i++) {
hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
}
} catch (IOException e) {
throw new AssertionError(e);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
return hash;
}
/**
* Compares ClassDoc instances according to the lexicographic
* order of their binary names.
**/
private static class ClassDocComparator implements Comparator<ClassDoc> {
public int compare(ClassDoc o1, ClassDoc o2) {
return Util.binaryNameOf(o1).compareTo(Util.binaryNameOf(o2));
}
}
/**
* Encapsulates RMI-specific information about a particular remote
* method in the remote implementation class represented by the
* enclosing RemoteClass.
**/
final class Method implements Cloneable {
/**
* MethodDoc for this remove method, from one of the remote
* interfaces that this method was found in.
*
* Note that this MethodDoc may be only one of multiple that
* correspond to this remote method object, if multiple of
* this class's remote interfaces contain methods with the
* same name and descriptor. Therefore, this MethodDoc may
* declare more exceptions thrown that this remote method
* does.
**/
private final MethodDoc methodDoc;
/** java.rmi.server.Operation string for this remote method */
private final String operationString;
/** name and descriptor of this remote method */
private final String nameAndDescriptor;
/** JRMP "method hash" for this remote method */
private final long methodHash;
/**
* Exceptions declared to be thrown by this remote method.
*
* This list may include superfluous entries, such as
* unchecked exceptions and subclasses of other entries.
**/
private ClassDoc[] exceptionTypes;
/**
* Creates a new Method instance for the specified method.
**/
Method(MethodDoc methodDoc) {
this.methodDoc = methodDoc;
exceptionTypes = methodDoc.thrownExceptions();
/*
* Sort exception types to improve consistency with
* previous implementations.
*/
Arrays.sort(exceptionTypes, new ClassDocComparator());
operationString = computeOperationString();
nameAndDescriptor =
methodDoc.name() + Util.methodDescriptorOf(methodDoc);
methodHash = computeMethodHash();
}
/**
* Returns the MethodDoc object corresponding to this method
* of a remote interface.
**/
MethodDoc methodDoc() {
return methodDoc;
}
/**
* Returns the parameter types declared by this method.
**/
Type[] parameterTypes() {
Parameter[] parameters = methodDoc.parameters();
Type[] paramTypes = new Type[parameters.length];
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = parameters[i].type();
}
return paramTypes;
}
/**
* Returns the exception types declared to be thrown by this
* remote method.
*
* For methods with the same name and descriptor inherited
* from multiple remote interfaces, the array will contain the
* set of exceptions declared in all of the interfaces'
* methods that can be legally thrown by all of them.
**/
ClassDoc[] exceptionTypes() {
return exceptionTypes.clone();
}
/**
* Returns the JRMP "method hash" used to identify this remote
* method in the JDK 1.2 version of the stub protocol.
**/
long methodHash() {
return methodHash;
}
/**
* Returns the string representation of this method
* appropriate for the construction of a
* java.rmi.server.Operation object.
**/
String operationString() {
return operationString;
}
/**
* Returns a string consisting of this method's name followed
* by its descriptor.
**/
String nameAndDescriptor() {
return nameAndDescriptor;
}
/**
* Returns a new Method object that is a legal combination of
* this Method object and another one.
*
* Doing this requires determining the exceptions declared by
* the combined method, which must be (only) all of the
* exceptions declared in both old Methods that may thrown in
* either of them.
**/
Method mergeWith(Method other) {
if (!nameAndDescriptor().equals(other.nameAndDescriptor())) {
throw new AssertionError(
"attempt to merge method \"" +
other.nameAndDescriptor() + "\" with \"" +
nameAndDescriptor());
}
List<ClassDoc> legalExceptions = new ArrayList<ClassDoc>();
collectCompatibleExceptions(
other.exceptionTypes, exceptionTypes, legalExceptions);
collectCompatibleExceptions(
exceptionTypes, other.exceptionTypes, legalExceptions);
Method merged = clone();
merged.exceptionTypes =
legalExceptions.toArray(new ClassDoc[legalExceptions.size()]);
return merged;
}
/**
* Cloning is supported by returning a shallow copy of this
* object.
**/
protected Method clone() {
try {
return (Method) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
/**
* Adds to the supplied list all exceptions in the "froms"
* array that are subclasses of an exception in the "withs"
* array.
**/
private void collectCompatibleExceptions(ClassDoc[] froms,
ClassDoc[] withs,
List<ClassDoc> list)
{
for (ClassDoc from : froms) {
if (!list.contains(from)) {
for (ClassDoc with : withs) {
if (from.subclassOf(with)) {
list.add(from);
break;
}
}
}
}
}
/**
* Computes the JRMP "method hash" of this remote method. The
* method hash is a long containing the first 64 bits of the
* SHA digest from the UTF-8 encoded string of the method name
* and descriptor.
**/
private long computeMethodHash() {
long hash = 0;
ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
try {
MessageDigest md = MessageDigest.getInstance("SHA");
DataOutputStream out = new DataOutputStream(
new DigestOutputStream(sink, md));
String methodString = nameAndDescriptor();
out.writeUTF(methodString);
// use only the first 64 bits of the digest for the hash
out.flush();
byte hashArray[] = md.digest();
for (int i = 0; i < Math.min(8, hashArray.length); i++) {
hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
}
} catch (IOException e) {
throw new AssertionError(e);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
return hash;
}
/**
* Computes the string representation of this method
* appropriate for the construction of a
* java.rmi.server.Operation object.
**/
private String computeOperationString() {
/*
* To be consistent with previous implementations, we use
* the deprecated style of placing the "[]" for the return
* type (if any) after the parameter list.
*/
Type returnType = methodDoc.returnType();
String op = returnType.qualifiedTypeName() + " " +
methodDoc.name() + "(";
Parameter[] parameters = methodDoc.parameters();
for (int i = 0; i < parameters.length; i++) {
if (i > 0) {
op += ", ";
}
op += parameters[i].type().toString();
}
op += ")" + returnType.dimension();
return op;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 2003, 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.
*/
package sun.rmi.rmic.newrmic.jrmp;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.Type;
/**
* Provides static utility methods.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*
* @author Peter Jones
**/
final class Util {
private Util() { throw new AssertionError(); }
/**
* Returns the binary name of the class or interface represented
* by the specified ClassDoc.
**/
static String binaryNameOf(ClassDoc cl) {
String flat = cl.name().replace('.', '$');
String packageName = cl.containingPackage().name();
return packageName.equals("") ? flat : packageName + "." + flat;
}
/**
* Returns the method descriptor for the specified method.
*
* See section 4.3.3 of The Java Virtual Machine Specification
* Second Edition for the definition of a "method descriptor".
**/
static String methodDescriptorOf(MethodDoc method) {
String desc = "(";
Parameter[] parameters = method.parameters();
for (int i = 0; i < parameters.length; i++) {
desc += typeDescriptorOf(parameters[i].type());
}
desc += ")" + typeDescriptorOf(method.returnType());
return desc;
}
/**
* Returns the descriptor for the specified type, as appropriate
* for either a parameter or return type in a method descriptor.
**/
private static String typeDescriptorOf(Type type) {
String desc;
ClassDoc classDoc = type.asClassDoc();
if (classDoc == null) {
/*
* Handle primitive types.
*/
String name = type.typeName();
if (name.equals("boolean")) {
desc = "Z";
} else if (name.equals("byte")) {
desc = "B";
} else if (name.equals("char")) {
desc = "C";
} else if (name.equals("short")) {
desc = "S";
} else if (name.equals("int")) {
desc = "I";
} else if (name.equals("long")) {
desc = "J";
} else if (name.equals("float")) {
desc = "F";
} else if (name.equals("double")) {
desc = "D";
} else if (name.equals("void")) {
desc = "V";
} else {
throw new AssertionError(
"unrecognized primitive type: " + name);
}
} else {
/*
* Handle non-array reference types.
*/
desc = "L" + binaryNameOf(classDoc).replace('.', '/') + ";";
}
/*
* Handle array types.
*/
int dimensions = type.dimension().length() / 2;
for (int i = 0; i < dimensions; i++) {
desc = "[" + desc;
}
return desc;
}
/**
* Returns a reader-friendly string representation of the
* specified method's signature. Names of reference types are not
* package-qualified.
**/
static String getFriendlyUnqualifiedSignature(MethodDoc method) {
String sig = method.name() + "(";
Parameter[] parameters = method.parameters();
for (int i = 0; i < parameters.length; i++) {
if (i > 0) {
sig += ", ";
}
Type paramType = parameters[i].type();
sig += paramType.typeName() + paramType.dimension();
}
sig += ")";
return sig;
}
/**
* Returns true if the specified type is void.
**/
static boolean isVoid(Type type) {
return type.asClassDoc() == null && type.typeName().equals("void");
}
}