feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
70
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/Constants.java
Normal file
70
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/Constants.java
Normal 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;
|
||||
}
|
||||
226
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/JrmpGenerator.java
Normal file
226
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/JrmpGenerator.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
710
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java
Normal file
710
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
1079
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/StubSkeletonWriter.java
Normal file
1079
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/StubSkeletonWriter.java
Normal file
File diff suppressed because it is too large
Load Diff
149
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/Util.java
Normal file
149
jdkSrc/jdk8/sun/rmi/rmic/newrmic/jrmp/Util.java
Normal 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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user