📄 rmiutilities.java
字号:
/* RmiUtilities.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath.GNU Classpath is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU Classpath is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; see the file COPYING. If not, write to theFree Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA02110-1301 USA.Linking this library statically or dynamically with other modules ismaking a combined work based on this library. Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule. An independent module is a module which is not derived fromor based on this library. If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so. If you do not wish to do so, delete thisexception statement from your version. */package gnu.javax.rmi.CORBA;import gnu.CORBA.OrbFunctional;import gnu.CORBA.Minor;import gnu.CORBA.Unexpected;import gnu.CORBA.CDR.Vio;import gnu.CORBA.CDR.gnuRuntime;import gnu.CORBA.CDR.gnuValueStream;import gnu.CORBA.CDR.HeadlessInput;import org.omg.CORBA.MARSHAL;import org.omg.CORBA.StringValueHelper;import org.omg.CORBA.WStringValueHelper;import org.omg.CORBA.portable.Delegate;import org.omg.CORBA.portable.InputStream;import org.omg.CORBA.portable.ObjectImpl;import org.omg.CORBA.portable.OutputStream;import org.omg.CORBA.portable.ValueBase;import org.omg.PortableServer.POA;import org.omg.PortableServer.POAHelper;import org.omg.PortableServer.Servant;import org.omg.PortableServer.POAManagerPackage.State;import org.omg.SendingContext.RunTime;import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import java.io.Externalizable;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.rmi.Remote;import java.security.MessageDigest;import java.util.Arrays;import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;import java.util.WeakHashMap;import javax.rmi.PortableRemoteObject;import javax.rmi.CORBA.Stub;import javax.rmi.CORBA.Tie;import javax.rmi.CORBA.Util;/** * Defines methods that must be accessible in several derived classes. * * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) */public class RmiUtilities{ /** * The currently used RMI-IIOP version format. */ public static byte VERSION = 1; /** * The non - writable class fields. */ static final int NON_WRITABLE = Modifier.STATIC | Modifier.TRANSIENT; /** * The standard String repository Id. */ public static final String RMI_STRING_ID = StringValueHelper.id(); /** * The standard Class repository Id. */ public static final String RMI_CLASS_ID = "RMI:javax.rmi.CORBA.ClassDesc:2BABDA04587ADCCC:CFBF02CF5294176B"; /** * The standard string array repository Id. */ public static final String RMI_STRING_ARRAY_ID = "RMI:[Ljava.lang.String;:071DA8BE7F971128:A0F0A4387A3BB342"; /** * An instance of the wide string value helper for writing strings. */ static WStringValueHelper wStringValueHelper = new WStringValueHelper(); /** * Set of serializable classes that have .writeObject and .readObject defined. * Contains weak references to ensure that the classes will be unloadable. */ WeakHashMap io_format = new WeakHashMap(); /** * The standard IO format with no .writeObject and .readObject defined. */ static final Object STANDARD = new Object(); /** * The custom IO format with .writeObject and .readObject defined, * defaultWriteObject called. */ static final Object CUSTOM_DWO = new Object(); /** * The custom IO format with .writeObject and .readObject defined, * defaultWriteObject has not been called. */ static final Object CUSTOM_NO_DWO = new Object(); /** * The arguments for readObject. */ static final Class[] READ_OBJECT_ARGS = new Class[] { ObjectInputStream.class }; /** * The arguments for writeObject. */ static final Class[] WRITE_OBJECT_ARGS = new Class[] { ObjectOutputStream.class }; /** * The undocumented field that is heading the Sun's object data, written with * writeObject. */ static final int S_X = 16908034; /** * Write all fields of the passed value. */ void writeFields(OutputStream an_output, Serializable object) { org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output; try { Class o_class = object.getClass(); Field[] fields = getWritableFields(o_class); Field f; Class fc; for (int i = 0; i < fields.length; i++) { f = fields[i]; fc = f.getType(); Object v = f.get(object); if (fc == String.class) { output.write_value((Serializable) v, wStringValueHelper); } else if (fc == int.class) output.write_long(((Integer) v).intValue()); else if (fc == long.class) output.write_longlong(((Number) v).longValue()); else if (fc == double.class) output.write_double(((Number) v).doubleValue()); else if (fc == float.class) output.write_float(((Number) v).floatValue()); else if (fc == boolean.class) output.write_boolean(((Boolean) v).booleanValue()); else if (fc == short.class) output.write_short(((Number) v).shortValue()); else if (fc == byte.class) output.write_octet(((Number) v).byteValue()); else if (fc == char.class) output.write_wchar(((Character) v).charValue()); else { if (!fc.isInterface() && Remote.class.isAssignableFrom(fc)) fc = getExportedInterface(fc); writeMember(output, v, fc); } } } catch (Exception ex) { MARSHAL m = new MARSHAL("Cannot write " + object); m.minor = Minor.ValueFields; m.initCause(ex); throw m; } } /** * Write a memeber (field) of the data structure. */ void writeMember(org.omg.CORBA_2_3.portable.OutputStream output, Object object, Class xClass) { if (output instanceof gnuValueStream) { gnuRuntime g = ((gnuValueStream) output).getRunTime(); // Reset the target as we are already beyond the critical point // where is must have the value being written. if (g != null) g.target = null; } if (Serializable.class.isAssignableFrom(xClass) || Remote.class.isAssignableFrom(xClass)) { // Object handles null reference on its own. if (org.omg.CORBA.Object.class.isAssignableFrom(xClass) || Remote.class.isAssignableFrom(xClass)) { if (object == null) output.write_Object(null); else if (isTieRequired(object)) exportTie(output, object, xClass); else writeValue(output, (Serializable) object); } else output.write_value((Serializable) object, xClass); } else { MARSHAL m = new MARSHAL(xClass + " is not Serializable"); m.minor = Minor.NonSerializable; throw m; } } /** * Check if the object must be wrapped into Tie, connected to the ORB and then * the corresponding Stub be written. */ public boolean isTieRequired(Object object) { return object instanceof Remote && !(object instanceof Stub); } /** * Get the interface under that the class of this object must be exposed. The * interface must be derived from Remote. */ Class getExportedInterface(Object object) throws MARSHAL { Class fc = null; Class[] interfaces = object.getClass().getInterfaces(); for (int i = 0; i < interfaces.length; i++) { if (!Remote.class.equals(interfaces[i])) if (Remote.class.isAssignableFrom(interfaces[i])) { if (fc == null) fc = interfaces[i]; else { MARSHAL m = new MARSHAL("Both " + fc + " and " + interfaces[i] + " extends Remote"); m.minor = Minor.TargetConversion; throw m; } } } if (fc == null) { MARSHAL m = new MARSHAL(object.getClass() + " does not implement any interface, derived from Remote"); m.minor = Minor.TargetConversion; throw m; } return fc; } /** * Get the persistent hash code for the given class, as defined by OMG * standard. The inheritance, field names and types (but not the visibility) * are taken into consideration as well as the presence of the writeObject * method are taken into consideration. The class name and methods, if any, * are not taken into consideration. */ public static long getHashCode(Class c) { Class of = c.isArray() ? c.getComponentType() : null; if (c.isArray() && ((!Serializable.class.isAssignableFrom(of) || of.isPrimitive() || Remote.class.isAssignableFrom(of)))) return 0; if (!Serializable.class.isAssignableFrom(c)) return 0; try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(bout); Class superClass = c.getSuperclass(); if (superClass != null) out.writeLong(getHashCode(superClass)); int writeObjectPresentCode; try { c.getDeclaredMethod("writeObject", new Class[] { ObjectOutputStream.class }); writeObjectPresentCode = 2; // Exists. } catch (NoSuchMethodException e) { writeObjectPresentCode = 1; // Missing. } out.writeInt(writeObjectPresentCode); Field[] fields = c.getDeclaredFields(); Arrays.sort(fields, new Comparator() { public int compare(Object a, Object b) { Field fa = (Field) a; Field fb = (Field) b; return fa.getName().compareTo(fb.getName()); } }); Field f; for (int i = 0; i < fields.length; i++) { f = fields[i]; if ((f.getModifiers() & NON_WRITABLE) == 0) { out.writeUTF(f.getName()); out.writeUTF(getDescriptor(f.getType())); } } out.flush(); out.close(); MessageDigest shaDigest; try { shaDigest = MessageDigest.getInstance("SHA"); } catch (Exception ex) { throw new InternalError("SHA digesting algorithm is not available"); } // Return the digest value to the calling // method as an array of bytes. byte[] sha = shaDigest.digest(bout.toByteArray()); long hash = 0; for (int i = 0; i < Math.min(8, sha.length); i++) { hash += (long) (sha[i] & 255) << (i * 8); } return hash; } catch (IOException ioex) { throw new Unexpected(ioex); } } /** * Converts to hexadecimal string, supplementing leading zeros. */ public static String toHex(long l) { StringBuffer b = new StringBuffer(); b.append(Long.toHexString(l).toUpperCase()); while (b.length() < 16) b.insert(0, '0'); return b.toString(); } /** * Returns a <code>String</code> representing the type-encoding of a class. */ static String getDescriptor(Class type) { if (type.equals(boolean.class)) return "Z"; if (type.equals(byte.class)) return "B"; if (type.equals(short.class)) return "S"; if (type.equals(char.class)) return "C"; if (type.equals(int.class)) return "I"; if (type.equals(long.class)) return "J"; if (type.equals(float.class)) return "F"; if (type.equals(double.class)) return "D"; if (type.equals(void.class)) return "V"; else if (type.isArray()) { StringBuffer l = new StringBuffer("["); Class component = type.getComponentType(); while (component.isArray()) { l.append('['); component = component.getComponentType(); } l.append('L'); l.append(component.getName().replace('.', '/')); l.append(';'); return l.toString(); } else return "L" + type.getName().replace('.', '/') + ';'; } public static Field[] getWritableFields(Class c) { TreeSet set = new TreeSet(new Comparator() { public int compare(Object a, Object b) { return ((Field) a).getName().compareTo(((Field) b).getName()); } }); while (!c.equals(Object.class)) { Field[] f = c.getDeclaredFields(); for (int i = 0; i < f.length; i++) { if ((f[i].getModifiers() & NON_WRITABLE) == 0) { f[i].setAccessible(true); set.add(f[i]); } } c = c.getSuperclass(); } Field[] r = new Field[set.size()]; int p = 0; Iterator it = set.iterator(); while (it.hasNext()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -