Author: peter_firmstone Date: Wed Dec 29 07:04:25 2010 New Revision: 1053550
URL: http://svn.apache.org/viewvc?rev=1053550&view=rev Log: Delayed unmarshalling Added: incubator/river/jtsk/skunk/pepe/test/src/net/jini/io/MarshalledInstanceTest.java (with props) Modified: incubator/river/jtsk/skunk/pepe/src/net/jini/io/MarshalledInstance.java incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java Modified: incubator/river/jtsk/skunk/pepe/src/net/jini/io/MarshalledInstance.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/net/jini/io/MarshalledInstance.java?rev=1053550&r1=1053549&r2=1053550&view=diff ============================================================================== --- incubator/river/jtsk/skunk/pepe/src/net/jini/io/MarshalledInstance.java (original) +++ incubator/river/jtsk/skunk/pepe/src/net/jini/io/MarshalledInstance.java Wed Dec 29 07:04:25 2010 @@ -66,7 +66,6 @@ import org.apache.river.impl.util.Concur * with java.rmi.MarshalledObject the fully qualified class names * are used for both classes. */ - /** * A <code>MarshalledInstance</code> contains an object in serialized * form. The contained object can be deserialized on demand when @@ -99,9 +98,8 @@ import org.apache.river.impl.util.Concur public class MarshalledInstance implements Serializable { /* Change this later to be read from a configuration. - */ + */ private static volatile boolean verifyState = true; - /* Hold references to a constructed MarshalledInstance until the object * key is garbage collected. It may need to hold duplicates if * more than one marshalled instance is created with different annotations. @@ -110,51 +108,46 @@ public class MarshalledInstance implemen * the deserialization verifier, while the object it holds hasn't been * garbage collected. * DGC cannot be used since it would pose a Denial Of Service Risk. - */ - private static final ConcurrentMap<Object,Cup> pool - = new ConcurrentWeakMap<Object,Cup>(); - + */ + private static final ConcurrentMap<Object, Cup> pool = new ConcurrentWeakMap<Object, Cup>(); + /* Add an Object key, MarshalledInstance value to the pool if it * doesn't already exist, if it does, return the value in the pool * this will be used to avoid duplicating the exported MD. * Duplicates may exist where the MarshalledInstance is equal but not * fullyEqual. This prevents an explosion of MarshalledInstance * objects when they are created often. - */ - private static MarshalledInstance addToPool(Object o, MarshalledInstance i){ - Cup c = pool.get(o); - if (c == null){ - c = new Cup(); - Cup existed = pool.putIfAbsent(o, c); - if ( existed != null ){ - c = existed; - } - } - MarshalledInstance existed = c.putIfAbsent(i); - return existed; + */ + private static MarshalledInstance addToPool(Object o, MarshalledInstance i) { + Cup c = pool.get(o); + if (c == null) { + c = new Cup(); + Cup existed = pool.putIfAbsent(o, c); + if (existed != null) { + c = existed; + } + } + MarshalledInstance existed = c.putIfAbsent(i); + return existed; } - /** * @serial Bytes of serialized representation. If <code>objBytes</code> is * <code>null</code> then the object marshalled was a <code>null</code> * reference. - */ + */ private byte[] objBytes = null; - /** * @serial Bytes of location annotations, which are ignored by * <code>equals</code>. If <code>locBytes</code> is null, there were no * non-<code>null</code> annotations during marshalling. - */ + */ private byte[] locBytes = null; - /** * @serial Stored hash code of contained object. * * @see #hashCode - */ + */ private int hash; - /** * @serial MarshalledInstance deserialization authentication and * MessageDigest based verifier, may be null. The serialized form @@ -167,10 +160,8 @@ public class MarshalledInstance implemen * away, so does the MarshalledInstance. */ private AuthCheckMDIntegrity authDeserializationMDIntegrityCheck = null; - - static final long serialVersionUID = -5187033771082433496L; - + /** * Creates a new <code>MarshalledInstance</code> that contains the * marshalled representation of the current state of the supplied @@ -185,7 +176,7 @@ public class MarshalledInstance implemen * @throws IOException if the object cannot be serialized */ public MarshalledInstance(Object obj) throws IOException { - this(obj, Collections.EMPTY_SET); + this(obj, Collections.EMPTY_SET); } /** @@ -204,60 +195,59 @@ public class MarshalledInstance implemen * @throws NullPointerException if <code>context</code> is <code>null</code> */ public MarshalledInstance(Object obj, Collection context) - throws IOException - { - if (context == null) - throw new NullPointerException(); - - if (obj == null) { - hash = 13; // null hash for java.rmi.MarshalledObject - return; - } - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - ByteArrayOutputStream lout = new ByteArrayOutputStream(); - MarshalledInstanceOutputStream out = - new MarshalledInstanceOutputStream(bout, lout, context); - out.writeObject(obj); - out.flush(); - objBytes = bout.toByteArray(); - // locBytes is null if no annotations - locBytes = (out.hadAnnotations() ? lout.toByteArray() : null); - - // Calculate hash from the marshalled representation of object - // so the hashcode will be comparable when sent between VMs. - // - // Note: This calculation must match the calculation in - // java.rmi.MarshalledObject since we use this hash - // in the converted MarshalledObject. The reverse is - // also true in that we use the MarshalledObject's - // hash for our hash. (see the MarshalledInstance( - // MarshalledObject) constructor) - // - int h = 0; - for (int i = 0; i < objBytes.length; i++) { - h = 31 * h + objBytes[i]; - } - hash = h; - createDeserializationIntegrityCheck(); - MarshalledInstance exists = addToPool(obj, this); - if (exists != null){ - // we just created a duplicate marshalled instance best we share - // the deserialization check so we don't have to retain too many - // unnecessary strong references. - authDeserializationMDIntegrityCheck - = exists.authDeserializationMDIntegrityCheck; - } - } - - private void createDeserializationIntegrityCheck(){ - // Should we bomb out, or just leave it without a verifier? - try { - authDeserializationMDIntegrityCheck = new IntegrityCheck(objBytes, locBytes, hash ,"SHA"); - } catch (NoSuchAlgorithmException ex) { - Logger.getLogger(MarshalledInstance.class.getName()).log(Level.SEVERE, null, ex); - } catch (ExportException ex) { - Logger.getLogger(MarshalledInstance.class.getName()).log(Level.SEVERE, null, ex); - } + throws IOException { + if (context == null) { + throw new NullPointerException(); + } + + if (obj == null) { + hash = 13; // null hash for java.rmi.MarshalledObject + return; + } + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ByteArrayOutputStream lout = new ByteArrayOutputStream(); + MarshalledInstanceOutputStream out = + new MarshalledInstanceOutputStream(bout, lout, context); + out.writeObject(obj); + out.flush(); + objBytes = bout.toByteArray(); + // locBytes is null if no annotations + locBytes = (out.hadAnnotations() ? lout.toByteArray() : null); + + // Calculate hash from the marshalled representation of object + // so the hashcode will be comparable when sent between VMs. + // + // Note: This calculation must match the calculation in + // java.rmi.MarshalledObject since we use this hash + // in the converted MarshalledObject. The reverse is + // also true in that we use the MarshalledObject's + // hash for our hash. (see the MarshalledInstance( + // MarshalledObject) constructor) + // + int h = 0; + for (int i = 0; i < objBytes.length; i++) { + h = 31 * h + objBytes[i]; + } + hash = h; + createDeserializationIntegrityCheck(); + MarshalledInstance exists = addToPool(obj, this); + if (exists != null) { + // we just created a duplicate marshalled instance best we share + // the deserialization check so we don't have to retain too many + // unnecessary strong references. + authDeserializationMDIntegrityCheck = exists.authDeserializationMDIntegrityCheck; + } + } + + private void createDeserializationIntegrityCheck() { + // Should we bomb out, or just leave it without a verifier? + try { + authDeserializationMDIntegrityCheck = new IntegrityCheck(objBytes, locBytes, hash, "SHA"); + } catch (NoSuchAlgorithmException ex) { + Logger.getLogger(MarshalledInstance.class.getName()).log(Level.SEVERE, null, ex); + } catch (ExportException ex) { + Logger.getLogger(MarshalledInstance.class.getName()).log(Level.SEVERE, null, ex); + } } /** @@ -276,41 +266,42 @@ public class MarshalledInstance implemen */ public MarshalledInstance(java.rmi.MarshalledObject mo) { - if (mo == null) - throw new NullPointerException(); - - // To extract the java.rmi.MarshalledObject's fields we - // convert the mo into a net.jini.io.MarshalledObject. - // (See resolveClass() in FromMOInputStream) The private - // version of MarshalledObject allows access to the needed - // fields. - // - net.jini.io.MarshalledObject privateMO = null; - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(mo); - oos.flush(); - byte[] bytes = baos.toByteArray(); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - ObjectInputStream ois = new FromMOInputStream(bais); - privateMO = - (net.jini.io.MarshalledObject)ois.readObject(); - } catch (IOException ioe) { - throw new AssertionError(ioe); - } catch (ClassNotFoundException cnfe) { - throw new AssertionError(cnfe); - } - objBytes = privateMO.objBytes; - locBytes = privateMO.locBytes; - hash = privateMO.hash; - // We shouldn't create a verifier proxy for MarshalledInstance - // created from a MarshalledObject, since the actual object may - // not be local, how can we vouch for it if we don't have the - // original object? + if (mo == null) { + throw new NullPointerException(); + } + + // To extract the java.rmi.MarshalledObject's fields we + // convert the mo into a net.jini.io.MarshalledObject. + // (See resolveClass() in FromMOInputStream) The private + // version of MarshalledObject allows access to the needed + // fields. + // + net.jini.io.MarshalledObject privateMO = null; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(mo); + oos.flush(); + byte[] bytes = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new FromMOInputStream(bais); + privateMO = + (net.jini.io.MarshalledObject) ois.readObject(); + } catch (IOException ioe) { + throw new AssertionError(ioe); + } catch (ClassNotFoundException cnfe) { + throw new AssertionError(cnfe); + } + objBytes = privateMO.objBytes; + locBytes = privateMO.locBytes; + hash = privateMO.hash; + // We shouldn't create a verifier proxy for MarshalledInstance + // created from a MarshalledObject, since the actual object may + // not be local, how can we vouch for it if we don't have the + // original object? // createDeserializationIntegrityCheck(); } - + /** * Creates a new <code>MarshalledObject</code> that will * contain an object equivalent to the object contained @@ -324,36 +315,36 @@ public class MarshalledInstance implemen */ public java.rmi.MarshalledObject convertToMarshalledObject() { - // To create a java.rmi.MarshalledObject with previously - // serialized data we first create a private - // net.jini.io.MarshalledObject with the - // data and then convert it to the final object by changing - // the class during readObject(). (See resolveClass() in - // ToMOInputStream) - // - net.jini.io.MarshalledObject privateMO = - new net.jini.io.MarshalledObject(); - - privateMO.objBytes = objBytes; - privateMO.locBytes = locBytes; - privateMO.hash = hash; - - java.rmi.MarshalledObject mo = null; - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(privateMO); - oos.flush(); - byte[] bytes = baos.toByteArray(); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - ObjectInputStream ois = new ToMOInputStream(bais); - mo = (java.rmi.MarshalledObject)ois.readObject(); - } catch (IOException ioe) { - throw new AssertionError(ioe); - } catch (ClassNotFoundException cnfe) { - throw new AssertionError(cnfe); - } - return mo; + // To create a java.rmi.MarshalledObject with previously + // serialized data we first create a private + // net.jini.io.MarshalledObject with the + // data and then convert it to the final object by changing + // the class during readObject(). (See resolveClass() in + // ToMOInputStream) + // + net.jini.io.MarshalledObject privateMO = + new net.jini.io.MarshalledObject(); + + privateMO.objBytes = objBytes; + privateMO.locBytes = locBytes; + privateMO.hash = hash; + + java.rmi.MarshalledObject mo = null; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(privateMO); + oos.flush(); + byte[] bytes = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ToMOInputStream(bais); + mo = (java.rmi.MarshalledObject) ois.readObject(); + } catch (IOException ioe) { + throw new AssertionError(ioe); + } catch (ClassNotFoundException cnfe) { + throw new AssertionError(cnfe); + } + return mo; } /** @@ -383,10 +374,9 @@ public class MarshalledInstance implemen * is <code>true</code> and the integrity of the * contained object's codebase cannot be confirmed */ - public Object get(final boolean verifyCodebaseIntegrity) - throws IOException, ClassNotFoundException - { - return get(null, verifyCodebaseIntegrity, null, null); + public Object get(final boolean verifyCodebaseIntegrity) + throws IOException, ClassNotFoundException { + return get(null, verifyCodebaseIntegrity, null, null); } /** @@ -430,36 +420,38 @@ public class MarshalledInstance implemen * contained object's codebase cannot be confirmed */ public Object get(ClassLoader defaultLoader, - final boolean verifyCodebaseIntegrity, - ClassLoader verifierLoader, - Collection context) - throws IOException, ClassNotFoundException - { - if (objBytes == null) // must have been a null object - return null; - - if (context == null) { - context = Collections.singleton( - new IntegrityEnforcement() { - public boolean integrityEnforced() { - return verifyCodebaseIntegrity; - } - } ); - } - ByteArrayInputStream bin = new ByteArrayInputStream(objBytes); - // locBytes is null if no annotations - ByteArrayInputStream lin = - (locBytes == null ? null : new ByteArrayInputStream(locBytes)); - MarshalledInstanceInputStream in = - new MarshalledInstanceInputStream(bin, lin, - defaultLoader, - verifyCodebaseIntegrity, - verifierLoader, - context); - in.useCodebaseAnnotations(); - Object obj = in.readObject(); - in.close(); - return obj; + final boolean verifyCodebaseIntegrity, + ClassLoader verifierLoader, + Collection context) + throws IOException, ClassNotFoundException { + if (objBytes == null) // must have been a null object + { + return null; + } + + if (context == null) { + context = Collections.singleton( + new IntegrityEnforcement() { + + public boolean integrityEnforced() { + return verifyCodebaseIntegrity; + } + }); + } + ByteArrayInputStream bin = new ByteArrayInputStream(objBytes); + // locBytes is null if no annotations + ByteArrayInputStream lin = + (locBytes == null ? null : new ByteArrayInputStream(locBytes)); + MarshalledInstanceInputStream in = + new MarshalledInstanceInputStream(bin, lin, + defaultLoader, + verifyCodebaseIntegrity, + verifierLoader, + context); + in.useCodebaseAnnotations(); + Object obj = in.readObject(); + in.close(); + return obj; } /** @@ -476,11 +468,11 @@ public class MarshalledInstance implemen * otherwise returns <code>false</code> */ public boolean fullyEquals(Object obj) { - if (equals(obj)) { - MarshalledInstance other = (MarshalledInstance)obj; - return Arrays.equals(locBytes, other.locBytes); - } - return false; + if (equals(obj)) { + MarshalledInstance other = (MarshalledInstance) obj; + return Arrays.equals(locBytes, other.locBytes); + } + return false; } /** @@ -499,16 +491,18 @@ public class MarshalledInstance implemen * <code>false</code> */ public boolean equals(Object obj) { - if (obj == this) - return true; - - if (obj instanceof MarshalledInstance) { - MarshalledInstance other = (MarshalledInstance)obj; - if (hash != other.hash) - return false; - return Arrays.equals(objBytes, other.objBytes); - } - return false; + if (obj == this) { + return true; + } + + if (obj instanceof MarshalledInstance) { + MarshalledInstance other = (MarshalledInstance) obj; + if (hash != other.hash) { + return false; + } + return Arrays.equals(objBytes, other.objBytes); + } + return false; } /** @@ -518,90 +512,86 @@ public class MarshalledInstance implemen * @return The hash code for this object */ public int hashCode() { - return hash; + return hash; } /** * Verify the case of null contained object. */ private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - // This allows backward compatible evolution of serialized form. - in.defaultReadObject(); - - // If contained object is null, then hash and locBytes must be - // proper - // - if ((objBytes == null) && ((hash != 13) || (locBytes != null))) { - throw new InvalidObjectException("Bad hash or annotation"); - } - // Defensive copy mutable arrays. - objBytes = objBytes.clone(); - locBytes = locBytes.clone(); - // During deserialization we verify the MarshalledInstance using - // the proxy, for now until we get some proper tests up and - // running, I'm not going to require authentication. - // Later this will require authentication and a server - // minimum principal. - if (authDeserializationMDIntegrityCheck == null && verifyState == true ){ - throw new IOException("MarshalledInstance deserialization aborted" + - "unable to verify state, uable to " + - "authenticate or prevent codebase download denial of " + - "service, missing deserialization integrity check proxy"); - } - if (authDeserializationMDIntegrityCheck != null){ - ProxyPreparer preparer = new BasicProxyPreparer(); - // Don't overwrite proxy reference we might want to serialize it again. - AuthCheckMDIntegrity proxy = (AuthCheckMDIntegrity) preparer.prepareProxy(authDeserializationMDIntegrityCheck); - // Verify state has been transferred successfully. - String algorithm = proxy.getAlgorithm(); - MessageDigest md = null; - try{ - md = MessageDigest.getInstance(algorithm); - } catch (NoSuchAlgorithmException ex) { - if (verifyState == true){ - throw new IOException("Unable to verify state", ex); - } else { - Logger.getLogger(MarshalledInstance.class.getName()).log( - Level.SEVERE, null, ex); - } - } - if ( md != null){ - md.update(objBytes); - byte[] objMD = md.digest(); - md.reset(); - md.update(locBytes); - byte[] locMD = md.digest(); - if ( Arrays.equals(proxy.getLocMD(), locMD) - && Arrays.equals(proxy.getObjMD(), objMD) - && hash == proxy.getHashCode() - ) { - // It would now be safe, if we have authenticated the proxy - // with the minimum server principal and confirmed the - // Codebase annotation is correct, to grant DownloadPermission. - // WE COULD ASSUME THAT DownloadPermission MUST BE GRANTED - // IF DESERIALIZATION HAS BEEN SUCCESSFUL. - // Granting DownloadPermission prevents a trusted service - // from returning another proxy that we don't trust, and - // having it's codebase downloaded automatically. - return; - } else { - throw new IOException("MarshalledInstance serial form is corrupt"); - } - } - } + throws IOException, ClassNotFoundException { + // This allows backward compatible evolution of serialized form. + in.defaultReadObject(); + + // If contained object is null, then hash and locBytes must be + // proper + // + if ((objBytes == null) && ((hash != 13) || (locBytes != null))) { + throw new InvalidObjectException("Bad hash or annotation"); + } + // Defensive copy mutable arrays. + objBytes = objBytes.clone(); + locBytes = locBytes.clone(); + // During deserialization we verify the MarshalledInstance using + // the proxy, for now until we get some proper tests up and + // running, I'm not going to require authentication. + // Later this will require authentication and a server + // minimum principal. + if (authDeserializationMDIntegrityCheck == null && verifyState == true) { + throw new IOException("MarshalledInstance deserialization aborted" + + "unable to verify state, uable to " + + "authenticate or prevent codebase download denial of " + + "service, missing deserialization integrity check proxy"); + } + if (authDeserializationMDIntegrityCheck != null) { + ProxyPreparer preparer = new BasicProxyPreparer(); + // Don't overwrite proxy reference we might want to serialize it again. + AuthCheckMDIntegrity proxy = (AuthCheckMDIntegrity) preparer.prepareProxy(authDeserializationMDIntegrityCheck); + // Verify state has been transferred successfully. + String algorithm = proxy.getAlgorithm(); + MessageDigest md = null; + try { + md = MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + if (verifyState == true) { + throw new IOException("Unable to verify state", ex); + } else { + Logger.getLogger(MarshalledInstance.class.getName()).log( + Level.SEVERE, null, ex); + } + } + if (md != null) { + md.update(objBytes); + byte[] objMD = md.digest(); + md.reset(); + md.update(locBytes); + byte[] locMD = md.digest(); + if (Arrays.equals(proxy.getLocMD(), locMD) && Arrays.equals(proxy.getObjMD(), objMD) && hash == proxy.getHashCode()) { + // It would now be safe, if we have authenticated the proxy + // with the minimum server principal and confirmed the + // Codebase annotation is correct, to grant DownloadPermission. + // WE COULD ASSUME THAT DownloadPermission MUST BE GRANTED + // IF DESERIALIZATION HAS BEEN SUCCESSFUL. + // Granting DownloadPermission prevents a trusted service + // from returning another proxy that we don't trust, and + // having it's codebase downloaded automatically. + return; + } else { + throw new IOException("MarshalledInstance serial form is corrupt"); + } + } + } } - private void writeObject(ObjectOutputStream out) throws IOException{ - out.defaultWriteObject(); + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); } /** * Protect against missing superclass. */ private void readObjectNoData() throws ObjectStreamException { - throw new InvalidObjectException("Bad class hierarchy"); + throw new InvalidObjectException("Bad class hierarchy"); } /** @@ -613,105 +603,101 @@ public class MarshalledInstance implemen * from a <code>MarshalledInstanceInputStream</code>. * * @see MarshalledInstanceInputStream - */ + */ private static class MarshalledInstanceOutputStream - extends MarshalOutputStream - { - /** The stream on which location objects are written. */ - private ObjectOutputStream locOut; - - /** <code>true</code> if non-<code>null</code> annotations are - * written. - */ - private boolean hadAnnotations; - - /** - * Creates a new <code>MarshalledObjectOutputStream</code> whose - * non-location bytes will be written to <code>objOut</code> and whose - * location annotations (if any) will be written to - * <code>locOut</code>. - */ - public MarshalledInstanceOutputStream(OutputStream objOut, - OutputStream locOut, - Collection context) - throws IOException - { - super(objOut, context); - this.locOut = new ObjectOutputStream(locOut); - hadAnnotations = false; - } - - /** - * Returns <code>true</code> if any non-<code>null</code> location - * annotations have been written to this stream. - */ - public boolean hadAnnotations() { - return hadAnnotations; - } - - /** - * Overrides <code>MarshalOutputStream.writeAnnotation</code> - * implementation to write annotations to the location stream. - */ - protected void writeAnnotation(String loc) throws IOException { - hadAnnotations |= (loc != null); - locOut.writeObject(loc); - } - - public void flush() throws IOException { - super.flush(); - locOut.flush(); - } + extends MarshalOutputStream { + + /** The stream on which location objects are written. */ + private ObjectOutputStream locOut; + /** <code>true</code> if non-<code>null</code> annotations are + * written. + */ + private boolean hadAnnotations; + + /** + * Creates a new <code>MarshalledObjectOutputStream</code> whose + * non-location bytes will be written to <code>objOut</code> and whose + * location annotations (if any) will be written to + * <code>locOut</code>. + */ + public MarshalledInstanceOutputStream(OutputStream objOut, + OutputStream locOut, + Collection context) + throws IOException { + super(objOut, context); + this.locOut = new ObjectOutputStream(locOut); + hadAnnotations = false; + } + + /** + * Returns <code>true</code> if any non-<code>null</code> location + * annotations have been written to this stream. + */ + public boolean hadAnnotations() { + return hadAnnotations; + } + + /** + * Overrides <code>MarshalOutputStream.writeAnnotation</code> + * implementation to write annotations to the location stream. + */ + protected void writeAnnotation(String loc) throws IOException { + hadAnnotations |= (loc != null); + locOut.writeObject(loc); + } + + public void flush() throws IOException { + super.flush(); + locOut.flush(); + } } /** * The counterpart to <code>MarshalledInstanceOutputStream</code>. * * @see MarshalledInstanceOutputStream - */ + */ private static class MarshalledInstanceInputStream - extends MarshalInputStream - { - /** - * The stream from which annotations will be read. If this is - * <code>null</code>, then all annotations were <code>null</code>. - */ - private ObjectInputStream locIn; - - /** - * Creates a new <code>MarshalledObjectInputStream</code> that - * reads its objects from <code>objIn</code> and annotations - * from <code>locIn</code>. If <code>locIn</code> is - * <code>null</code>, then all annotations will be - * <code>null</code>. - */ - MarshalledInstanceInputStream(InputStream objIn, - InputStream locIn, - ClassLoader defaultLoader, - boolean verifyCodebaseIntegrity, - ClassLoader verifierLoader, - Collection context) - throws IOException - { - super(objIn, - defaultLoader, - verifyCodebaseIntegrity, - verifierLoader, - context); - this.locIn = (locIn == null ? null : new ObjectInputStream(locIn)); - } - - /** - * Overrides <code>MarshalInputStream.readAnnotation</code> to - * return locations from the stream we were given, or <code>null</code> - * if we were given a <code>null</code> location stream. - */ - protected String readAnnotation() - throws IOException, ClassNotFoundException - { - return (locIn == null ? null : (String)locIn.readObject()); - } - } + extends MarshalInputStream { + + /** + * The stream from which annotations will be read. If this is + * <code>null</code>, then all annotations were <code>null</code>. + */ + private ObjectInputStream locIn; + + /** + * Creates a new <code>MarshalledObjectInputStream</code> that + * reads its objects from <code>objIn</code> and annotations + * from <code>locIn</code>. If <code>locIn</code> is + * <code>null</code>, then all annotations will be + * <code>null</code>. + */ + MarshalledInstanceInputStream(InputStream objIn, + InputStream locIn, + ClassLoader defaultLoader, + boolean verifyCodebaseIntegrity, + ClassLoader verifierLoader, + Collection context) + throws IOException { + super(objIn, + defaultLoader, + verifyCodebaseIntegrity, + verifierLoader, + context); + this.locIn = (locIn == null ? null : new ObjectInputStream(locIn)); + } + + /** + * Overrides <code>MarshalInputStream.readAnnotation</code> to + * return locations from the stream we were given, or <code>null</code> + * if we were given a <code>null</code> location stream. + */ + protected String readAnnotation() + throws IOException, ClassNotFoundException { + return (locIn == null ? null : (String) locIn.readObject()); + } + } /** * Input stream to convert <code>java.rmi.MarshalledObject</code> @@ -719,23 +705,22 @@ public class MarshalledInstance implemen */ private static class FromMOInputStream extends ObjectInputStream { - public FromMOInputStream(InputStream in) throws IOException { - super(in); - } - - /** - * Overrides <code>ObjectInputStream.resolveClass</code> to change - * an occurence of class <code>java.rmi.MarshalledObject</code> to - * class <code>net.jini.io.MarshalledObject</code>. - */ - protected Class resolveClass(ObjectStreamClass desc) - throws IOException, ClassNotFoundException - { - if (desc.getName().equals("java.rmi.MarshalledObject")) { - return net.jini.io.MarshalledObject.class; - } - return super.resolveClass(desc); - } + public FromMOInputStream(InputStream in) throws IOException { + super(in); + } + + /** + * Overrides <code>ObjectInputStream.resolveClass</code> to change + * an occurence of class <code>java.rmi.MarshalledObject</code> to + * class <code>net.jini.io.MarshalledObject</code>. + */ + protected Class resolveClass(ObjectStreamClass desc) + throws IOException, ClassNotFoundException { + if (desc.getName().equals("java.rmi.MarshalledObject")) { + return net.jini.io.MarshalledObject.class; + } + return super.resolveClass(desc); + } } /** @@ -745,137 +730,142 @@ public class MarshalledInstance implemen */ private static class ToMOInputStream extends ObjectInputStream { - public ToMOInputStream(InputStream in) throws IOException { - super(in); - } - - /** - * Overrides <code>ObjectInputStream.resolveClass</code> - * to change an occurence of class - * <code>net.jini.io.MarshalledObject</code> - * to class <code>java.rmi.MarshalledObject</code>. - */ - protected Class resolveClass(ObjectStreamClass desc) - throws IOException, ClassNotFoundException - { - if (desc.getName().equals("net.jini.io.MarshalledObject")) { - return java.rmi.MarshalledObject.class; - } - return super.resolveClass(desc); - } + public ToMOInputStream(InputStream in) throws IOException { + super(in); + } + + /** + * Overrides <code>ObjectInputStream.resolveClass</code> + * to change an occurence of class + * <code>net.jini.io.MarshalledObject</code> + * to class <code>java.rmi.MarshalledObject</code>. + */ + protected Class resolveClass(ObjectStreamClass desc) + throws IOException, ClassNotFoundException { + if (desc.getName().equals("net.jini.io.MarshalledObject")) { + return java.rmi.MarshalledObject.class; + } + return super.resolveClass(desc); + } } - + interface AuthCheckMDIntegrity { - byte [] getLocMD() throws IOException; - byte [] getObjMD() throws IOException; - String getAlgorithm() throws IOException; - int getHashCode() throws IOException; -} - + + byte[] getLocMD() throws IOException; + + byte[] getObjMD() throws IOException; + + String getAlgorithm() throws IOException; + + int getHashCode() throws IOException; + } + private static class IntegrityCheck implements AuthCheckMDIntegrity, - ServerProxyTrust, Remote, Serializable { - private static final long serialVersionUID = 1L; - private final byte[] objMD; - private final byte[] locMD; - private final int hash; - private final String algorithm; - private final Object proxy; - IntegrityCheck(byte[] object, byte[] annotation, int hashCode, - String algorithm) - throws NoSuchAlgorithmException, ExportException{ - hash = hashCode; - MessageDigest md = MessageDigest.getInstance(algorithm); - md.update(object); - objMD = md.digest(); - md.reset(); - md.update(annotation); - locMD = md.digest(); - this.algorithm = algorithm; - /* We could get the exporter from a configuration, but that would - * risk inadequate Confidentiality, worse, it may keep the vm - * alive while the exporter remains exported, or worse still the - * server may be subject to DOS attacks if DGC is enabled, - * which is what we're trying to avoid in the first place, - * since the proxy is used to allow the client to Authenticate - * the server to prevent DOS attacks in the client, the fix would be - * worse than the original bug. - * - * I'll add a configuration item later to allow for different - * secure ServerEndpoint's - * - * This exported object only remains exported while a strong - * reference is kept to the enclosing MarshalledInstance. Since - * it is the registrar proxy (reggie) that creates a - * MarshalledInstance, a reference would need to be maintained in the - * client. - */ - Exporter exporter = - new BasicJeriExporter( - SslServerEndpoint.getInstance(0), - new ProxyTrustILFactory( - new BasicMethodConstraints( - new InvocationConstraints( - new InvocationConstraint[] { - Confidentiality.YES, - ConfidentialityStrength.STRONG - }, null - ) //End InvocationConstraints constructor - )//End BasicMethodConstraints constructor - , null - )//End ProxyTrustILFactory constructor - ,false, false - );//End BasiceJeriExporter constructor - proxy = exporter.export(this); - } - - public TrustVerifier getProxyVerifier() throws RemoteException { - return new BasicProxyTrustVerifier(proxy); - //return new ProxyTrustVerifier(); - } - - public byte[] getLocMD() throws RemoteException { - return locMD; - } - - public byte[] getObjMD() throws RemoteException { - return objMD; - } - - public String getAlgorithm() throws RemoteException { - return algorithm; - } - - public int getHashCode() throws IOException { - return hash; - } - - private Object writeReplace(){ - return proxy; - } - - // Prevent an attacker fabricating an instance. - private void readObject(ObjectInputStream in) - throws InvalidObjectException{ - throw new InvalidObjectException("Proxy Required"); - } - + ServerProxyTrust, Remote, Serializable { + + private static final long serialVersionUID = 1L; + private final byte[] objMD; + private final byte[] locMD; + private final int hash; + private final String algorithm; + private final Object proxy; + + IntegrityCheck(byte[] object, byte[] annotation, int hashCode, + String algorithm) + throws NoSuchAlgorithmException, ExportException { + hash = hashCode; + MessageDigest md = MessageDigest.getInstance(algorithm); + md.update(object); + objMD = md.digest(); + md.reset(); + md.update(annotation); + locMD = md.digest(); + this.algorithm = algorithm; + /* We could get the exporter from a configuration, but that would + * risk inadequate Confidentiality, worse, it may keep the vm + * alive while the exporter remains exported, or worse still the + * server may be subject to DOS attacks if DGC is enabled, + * which is what we're trying to avoid in the first place, + * since the proxy is used to allow the client to Authenticate + * the server to prevent DOS attacks in the client, the fix would be + * worse than the original bug. + * + * I'll add a configuration item later to allow for different + * secure ServerEndpoint's + * + * This exported object only remains exported while a strong + * reference is kept to the enclosing MarshalledInstance. Since + * it is the registrar proxy (reggie) that creates a + * MarshalledInstance, a reference would need to be maintained in the + * client. + */ + Exporter exporter = + new BasicJeriExporter( + SslServerEndpoint.getInstance(0), + new ProxyTrustILFactory( + new BasicMethodConstraints( + new InvocationConstraints( + new InvocationConstraint[]{ + Confidentiality.YES, + ConfidentialityStrength.STRONG + }, null) //End InvocationConstraints constructor + )//End BasicMethodConstraints constructor + , null)//End ProxyTrustILFactory constructor + , false, false);//End BasiceJeriExporter constructor + proxy = exporter.export(this); + } + + public TrustVerifier getProxyVerifier() throws RemoteException { + return new BasicProxyTrustVerifier(proxy); + //return new ProxyTrustVerifier(); + } + + public byte[] getLocMD() throws RemoteException { + return locMD; + } + + public byte[] getObjMD() throws RemoteException { + return objMD; + } + + public String getAlgorithm() throws RemoteException { + return algorithm; + } + + public int getHashCode() throws IOException { + return hash; + } + + private Object writeReplace() { + return proxy; + } + + // Prevent an attacker fabricating an instance. + private void readObject(ObjectInputStream in) + throws InvalidObjectException { + throw new InvalidObjectException("Proxy Required"); + } } - + /* Stores unique marshalled Instance references, as defined by fullyEquals() * duplicates are only added if they are not fullyEqual. - */ + */ private static class Cup { - List<MarshalledInstance> items = new ArrayList<MarshalledInstance>(2); - MarshalledInstance putIfAbsent(MarshalledInstance t){ - synchronized (items){ - Iterator<MarshalledInstance> it = items.iterator(); - while (it.hasNext()){ - MarshalledInstance i = it.next(); - if (t.fullyEquals(i)) return i; - } - items.add(t); - return null; - } - } + + List<MarshalledInstance> items = new ArrayList<MarshalledInstance>(2); + + MarshalledInstance putIfAbsent(MarshalledInstance t) { + synchronized (items) { + Iterator<MarshalledInstance> it = items.iterator(); + while (it.hasNext()) { + MarshalledInstance i = it.next(); + if (t.fullyEquals(i)) { + return i; + } + } + items.add(t); + return null; + } + } } } Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java?rev=1053550&r1=1053549&r2=1053550&view=diff ============================================================================== --- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java (original) +++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java Wed Dec 29 07:04:25 2010 @@ -1,13 +1,25 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.river.api.lookup; import java.net.URI; import java.security.CodeSource; -import java.util.Collection; import net.jini.core.entry.Entry; import net.jini.core.lookup.ServiceID; import net.jini.core.lookup.ServiceItem; @@ -17,7 +29,8 @@ import net.jini.core.lookup.ServiceItem; * ServiceItem can. A MarshalledServiceItem implementation instance * contains the marshalled form of a Service and it's Entry's, * the corresponding superclass ServiceItem however contains null values - * for the service and can exclude any Entry's. + * for the service and can exclude any Entry's, however where Entry + * classes already exist at the client, that they be unmarshalled. * * The ServiceID shall be in unmarshalled form always in the ServiceItem super class. * Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java?rev=1053550&r1=1053549&r2=1053550&view=diff ============================================================================== --- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java (original) +++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java Wed Dec 29 07:04:25 2010 @@ -17,8 +17,10 @@ */ package org.apache.river.api.lookup; -import net.jini.core.lookup.*; import java.io.IOException; +import net.jini.core.lookup.ServiceRegistrar; +import net.jini.core.lookup.ServiceTemplate; +import net.jini.core.lookup.ServiceItem; import org.apache.river.api.util.ResultStream; /** Added: incubator/river/jtsk/skunk/pepe/test/src/net/jini/io/MarshalledInstanceTest.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/test/src/net/jini/io/MarshalledInstanceTest.java?rev=1053550&view=auto ============================================================================== --- incubator/river/jtsk/skunk/pepe/test/src/net/jini/io/MarshalledInstanceTest.java (added) +++ incubator/river/jtsk/skunk/pepe/test/src/net/jini/io/MarshalledInstanceTest.java Wed Dec 29 07:04:25 2010 @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jini.io; + +import java.rmi.MarshalledObject; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author peter + */ +public class MarshalledInstanceTest { + + public MarshalledInstanceTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + /** + * Test of convertToMarshalledObject method, of class MarshalledInstance. + */ + @Test + public void convertToMarshalledObject() { + System.out.println("convertToMarshalledObject"); + MarshalledInstance instance = null; + MarshalledObject expResult = null; + MarshalledObject result = instance.convertToMarshalledObject(); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } + + /** + * Test of get method, of class MarshalledInstance. + */ + @Test + public void get() throws Exception { + System.out.println("get"); + boolean verifyCodebaseIntegrity = false; + MarshalledInstance instance = null; + Object expResult = null; + Object result = instance.get(verifyCodebaseIntegrity); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } + + /** + * Test of fullyEquals method, of class MarshalledInstance. + */ + @Test + public void fullyEquals() { + System.out.println("fullyEquals"); + Object obj = null; + MarshalledInstance instance = null; + boolean expResult = false; + boolean result = instance.fullyEquals(obj); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } + + /** + * Test of equals method, of class MarshalledInstance. + */ + @Test + public void equals() { + System.out.println("equals"); + Object obj = null; + MarshalledInstance instance = null; + boolean expResult = false; + boolean result = instance.equals(obj); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } + + /** + * Test of hashCode method, of class MarshalledInstance. + */ + @Test + public void hashCodeTest() { + System.out.println("hashCode"); + MarshalledInstance instance = null; + int expResult = 0; + int result = instance.hashCode(); + assertEquals(expResult, result); + // TODO review the generated test code and remove the default call to fail. + fail("The test case is a prototype."); + } + +} \ No newline at end of file Propchange: incubator/river/jtsk/skunk/pepe/test/src/net/jini/io/MarshalledInstanceTest.java ------------------------------------------------------------------------------ svn:eol-style = native
