river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject svn commit: r724995 [3/6] - in /incubator/river/jtsk/skunk/niclas1/shared: ./ action/ action/src/ action/src/main/ action/src/main/java/ action/src/main/java/com/ action/src/main/java/com/sun/ action/src/main/java/com/sun/jini/ action/src/main/java/com...
Date Wed, 10 Dec 2008 05:25:04 GMT
Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/Levels.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/Levels.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/Levels.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/Levels.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,156 @@
+/*
+ * 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 com.sun.jini.logging;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.logging.Level;
+
+/**
+ * Defines additional {@link Level} values. <p>
+ *
+ * See the {@link LogManager} class for one way to use the <code>FAILED</code>
+ * and <code>HANDLED</code> logging levels in standard logging configuration
+ * files.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class Levels
+{
+
+    /**
+     * <code>FAILED</code> is a message level indicating that a facility has
+     * experienced a failure that it will reflect to its caller. <p>
+     *
+     * <code>FAILED</code> messages are intended to provide users with
+     * information about failures produced by internal components in order to
+     * assist with debugging problems in systems with multiple components. This
+     * level is initialized to <code>600</code>.
+     */
+    public static final Level FAILED = createLevel( "FAILED", 600, null );
+
+    /**
+     * <code>HANDLED</code> is a message level indicating that a facility has
+     * detected a failure that it will take steps to handle without reflecting
+     * the failure to its caller. <p>
+     *
+     * <code>HANDLED</code> messages are intended to provide users with
+     * information about failures detected by internal components in order to
+     * assist with debugging problems in systems with multiple components. This
+     * level is initialized to <code>550</code>.
+     */
+    public static final Level HANDLED = createLevel( "HANDLED", 550, null );
+
+    /**
+     * This class cannot be instantiated.
+     */
+    private Levels()
+    {
+        throw new AssertionError( "This class cannot be instantiated" );
+    }
+
+    /**
+     * Defines a class that has the same data format as the Level class, to
+     * permit creating the serialized form of a Level instance.
+     */
+    private static final class LevelData implements Serializable
+    {
+        private static final long serialVersionUID = -8176160795706313070L;
+        private final String name;
+        private final int value;
+        private final String resourceBundleName;
+
+        LevelData( String name, int value, String resourceBundleName )
+        {
+            this.name = name;
+            this.value = value;
+            this.resourceBundleName = resourceBundleName;
+        }
+    }
+
+    /**
+     * Defines an object output stream that allows the data for one class to be
+     * interpreted as the data for another class.  This class is useful in
+     * creating serialization data for a class when access to an appropriate
+     * constructor is not available.
+     */
+    private static final class ClassReplacingObjectOutputStream
+        extends ObjectOutputStream
+    {
+        private final ObjectStreamClass from;
+        private final ObjectStreamClass to;
+
+        ClassReplacingObjectOutputStream( OutputStream out,
+                                          Class from,
+                                          Class to )
+            throws IOException
+        {
+            super( out );
+            this.from = ObjectStreamClass.lookup( from );
+            this.to = ObjectStreamClass.lookup( to );
+        }
+
+        protected void writeClassDescriptor( ObjectStreamClass desc )
+            throws IOException
+        {
+            if( from.equals( desc ) )
+            {
+                desc = to;
+            }
+            super.writeClassDescriptor( desc );
+        }
+    }
+
+    /**
+     * Creates an instance of the Level class.  This method works around the
+     * fact that there is no public constructor for the Level class by
+     * constructing the serialized form for an instance with the specified
+     * field values and deserializing it.
+     */
+    private static Level createLevel( String name,
+                                      int value,
+                                      String resourceBundleName )
+    {
+        try
+        {
+            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+            ObjectOutputStream out =
+                new ClassReplacingObjectOutputStream(
+                    bytes, LevelData.class, Level.class );
+            out.writeObject( new LevelData( name, value, resourceBundleName ) );
+            out.close();
+            ObjectInputStream in = new ObjectInputStream(
+                new ByteArrayInputStream( bytes.toByteArray() ) );
+            Level result = (Level) in.readObject();
+            in.close();
+            return result;
+        }
+        catch( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception", e );
+        }
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogManager.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogManager.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogManager.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogManager.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,224 @@
+/*
+ * 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 com.sun.jini.logging;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Defines a {@link java.util.logging.LogManager} that insures that the {@link
+ * Levels#FAILED Levels.FAILED} and {@link Levels#HANDLED Levels.HANDLED}
+ * fields, instances of {@link Level}, have been initialized, and that can
+ * periodically check for changes to the logging configuration file and force
+ * it to be reread.  Use this class as the value of the
+ * <code>java.util.logging.manager</code> system property to permit specifying
+ * the symbolic names for the <code>FAILED</code> and <code>HANDLED</code>
+ * logging levels in standard logging configuration files, or to allow changes
+ * to the logging configuration file to be noticed. <p>
+ *
+ * The <code>com.sun.jini.logging.interval</code> logging property (obtained
+ * using {@link java.util.logging.LogManager#getProperty
+ * LogManager.getProperty}) specifies the time interval in milliseconds
+ * between probes to see if the logging configuration file has changed;
+ * periodic checking only takes place if the value is greater than zero. (If a
+ * new logging configuration file is read, this property can be redefined.)
+ * The logging configuration file is specified by the
+ * <code>java.util.logging.config.file</code> system property (which is
+ * sampled at every probe), if defined, otherwise it is the
+ * <code>logging.properties</code> file in the <code>lib</code> subdirectory
+ * of the directory specified by the <code>java.home</code> system property.
+ * The file is read if the name of the file differs from that used in the
+ * previous probe or if the file has a different modification time. <p>
+ *
+ * This implementation uses the {@link java.util.logging.Logger} named
+ * <code>com.sun.jini.logging.LogManager</code> to log information at the
+ * following logging levels: <p>
+ *
+ * <table border="1" cellpadding="5" summary="Describes logging performed
+ * by the LogManager class at different logging levels">
+ * <caption halign="center" valign="top"><b><code>
+ * com.sun.jini.logging.LogManager</code></b></caption>
+ * <tr><th scope="col">Level<th scope="col">Description
+ * <tr><td>{@link Level#WARNING WARNING}<td>if an exception occurs while
+ * rereading the logging configuration file
+ * <tr><td>{@link Level#CONFIG CONFIG}<td>each time the logging configuration
+ * file is successfully reread
+ * <tr><td>{@link Level#CONFIG CONFIG}<td>termination of probes because
+ * interval is less than or equal to zero
+ * </table>
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class LogManager extends java.util.logging.LogManager
+{
+    private Probe probe = null;
+
+    /**
+     * Creates an instance of this class.
+     */
+    public LogManager()
+    {
+        /* Refer to the levels to make sure that they are defined */
+        Levels.FAILED.toString();
+        Levels.HANDLED.toString();
+    }
+
+    /**
+     * Reinitialize the logging properties and reread the logging
+     * configuration, and initiate probes if the probe interval is greater
+     * than zero.
+     */
+    public void readConfiguration( InputStream ins ) throws IOException
+    {
+        super.readConfiguration( ins );
+        synchronized( this )
+        {
+            if( probe == null )
+            {
+                long interval = getInterval();
+                if( interval > 0 )
+                {
+                    probe = new Probe( interval );
+                    probe.start();
+                }
+            }
+        }
+    }
+
+    /**
+     * Return the probe interval.
+     */
+    private long getInterval()
+    {
+        String val = getProperty( "com.sun.jini.logging.interval" );
+        if( val != null )
+        {
+            try
+            {
+                return Long.decode( val ).longValue();
+            }
+            catch( NumberFormatException e )
+            {
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Return the logging configuration file name.
+     */
+    private static File getFile()
+    {
+        String fname = System.getProperty( "java.util.logging.config.file" );
+        if( fname != null )
+        {
+            return new File( fname );
+        }
+        else
+        {
+            return new File( System.getProperty( "java.home" ),
+                             "lib" + File.separator + "logging.properties" );
+        }
+    }
+
+    /**
+     * Thread to probe for config file changes and force reread
+     */
+    private class Probe extends Thread
+    {
+        /**
+         * Time in milliseconds between probes
+         */
+        private long interval;
+        /**
+         * The last file read
+         */
+        private File prevFile;
+        /**
+         * The lastModified time of prevFile
+         */
+        private long prevModified;
+
+        Probe( long interval )
+        {
+            super( "LogManager config file probe" );
+            setDaemon( true );
+            this.interval = interval;
+            prevFile = getFile();
+            prevModified = prevFile.lastModified();
+        }
+
+        public void run()
+        {
+            Logger logger =
+                Logger.getLogger( "com.sun.jini.logging.LogManager" );
+            try
+            {
+                while( interval > 0 )
+                {
+                    Thread.sleep( interval );
+                    File file = getFile();
+                    long lastModified = file.lastModified();
+                    if( lastModified > 0 &&
+                        ( !file.equals( prevFile ) ||
+                          lastModified != prevModified ) )
+                    {
+                        try
+                        {
+                            readConfiguration();
+                            interval = getInterval();
+                            logger.log( Level.CONFIG,
+                                        "logging config file reread complete," +
+                                        " new interval is {0}",
+                                        new Long( interval ) );
+                        }
+                        catch( Throwable t )
+                        {
+                            try
+                            {
+                                logger.log( Level.WARNING,
+                                            "exception reading logging config file", t );
+                            }
+                            catch( Throwable t2 )
+                            {
+                            }
+                        }
+                        prevFile = file;
+                        prevModified = lastModified;
+                    }
+                }
+            }
+            catch( InterruptedException e )
+            {
+            }
+            finally
+            {
+                synchronized( LogManager.this )
+                {
+                    probe = null;
+                }
+                logger.config( "logging config file probe terminating" );
+            }
+	}
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogUtil.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogUtil.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogUtil.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/LogUtil.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,72 @@
+/*
+ * 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 com.sun.jini.logging;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * A set of static convenience methods used for logging.
+ * This class cannot be instantiated.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.1
+ */
+public class LogUtil
+{
+
+    /**
+     * This class cannot be instantiated.
+     */
+    private LogUtil()
+    {
+        throw new AssertionError(
+            "com.sun.jini.logging.LogUtil cannot be instantiated" );
+    }
+
+    /**
+     * Convenience method used to log a throw operation when message parameters
+     * and a Throwable are used.
+     *
+     * @param logger       logger to log to
+     * @param level        the log level
+     * @param sourceClass  class where throw occurred
+     * @param sourceMethod name of the method where throw occurred
+     * @param msg          log message
+     * @param params       log message parameters
+     * @param e            exception thrown
+     */
+    public static void logThrow( Logger logger,
+                                 Level level,
+                                 Class sourceClass,
+                                 String sourceMethod,
+                                 String msg,
+                                 Object[] params,
+                                 Throwable e )
+    {
+        LogRecord r = new LogRecord( level, msg );
+        r.setLoggerName( logger.getName() );
+        r.setSourceClassName( sourceClass.getName() );
+        r.setSourceMethodName( sourceMethod );
+        r.setParameters( params );
+        r.setThrown( e );
+        logger.log( r );
+    }
+
+}
\ No newline at end of file

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/package.html
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/package.html?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/package.html (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/logging/package.html Tue Dec  9 21:25:00 2008
@@ -0,0 +1,32 @@
+<!--
+ ! 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.
+ !-->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body bgcolor="white">
+
+Defines convenience classes for use with the {@link java.util.logging}
+package.
+
+@since 2.0
+
+</body>
+</html>

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogException.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogException.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogException.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogException.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,97 @@
+/*
+ * 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 com.sun.jini.reliableLog;
+
+import java.io.IOException;
+
+/**
+ * This class can be used to represent all exceptional conditions that
+ * occur during any logging process. Whenever an exception is caught
+ * while information is being logged, the exception can be wrapped
+ * in this class so as to indicate an unsuccessful log operation.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+public class LogException extends IOException
+{
+
+    private static final long serialVersionUID = 1870528169848832111L;
+
+    /**
+     * @serial
+     */
+    public Throwable detail;
+
+    /**
+     * Create a wrapper exception for exceptions that occur during a logging
+     * operation.
+     */
+    public LogException()
+    {
+        initCause( null );
+    }
+
+    /**
+     * For exceptions that occur during a logging operation, create a wrapper
+     * exception with the specified description string.
+     */
+    public LogException( String s )
+    {
+        super( s );
+        initCause( null );
+    }
+
+    /**
+     * For exceptions that occur during a logging operation, create a wrapper
+     * exception with the specified description string and the specified
+     * nested exception.
+     */
+    public LogException( String s, Throwable ex )
+    {
+        super( s );
+        initCause( null );
+        detail = ex;
+    }
+
+    /**
+     * Produce the message; including the message from the nested exception
+     * if there is one.
+     */
+    public String getMessage()
+    {
+        if( detail == null )
+        {
+            return super.getMessage();
+        }
+        else
+        {
+            return super.getMessage() +
+                   "; nested exception is: \n\t" +
+                   detail.toString();
+        }
+    }
+
+    /**
+     * Returns the nested exception (the <i>cause</i>).
+     */
+    public Throwable getCause()
+    {
+        return detail;
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogHandler.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogHandler.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogHandler.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogHandler.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,110 @@
+/*
+ * 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 com.sun.jini.reliableLog;
+
+
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+
+/**
+ * A LogHandler represents snapshots and update records as serializable
+ * objects.
+ * <p>
+ * This implementation does not know how to create an initial snaphot or
+ * apply an update to a snapshot.  The client must specify these methods
+ * via a subclass.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see ReliableLog
+ */
+public abstract class LogHandler
+{
+
+    /**
+     * Creates a LogHandler for a ReliableLog.
+     */
+    public LogHandler()
+    {
+    }
+
+    /**
+     * Writes the snapshot to a stream.  This callback is invoked when
+     * the client calls the snaphot method of ReliableLog.
+     *
+     * @param out the output stream
+     * @throws Exception can raise any exception
+     */
+    public abstract void snapshot( OutputStream out ) throws Exception;
+
+    /**
+     * Read the snapshot from a stream.  This callback is invoked when
+     * the client calls the recover method of ReliableLog.
+     *
+     * @param in the input stream
+     * @throws Exception can raise any exception
+     */
+
+    public abstract void recover( InputStream in ) throws Exception;
+
+    /**
+     * Writes the representation (a serializable object) of an update
+     * to a stream.  This callback is invoked when the client calls the
+     * update method of ReliableLog.
+     *
+     * @param out   the output stream
+     * @param value the update object
+     * @throws Exception can raise any exception
+     */
+    public void writeUpdate( OutputStream out, Object value ) throws Exception
+    {
+        ObjectOutputStream s = new ObjectOutputStream( out );
+        s.writeObject( value );
+        s.flush();
+    }
+
+    /**
+     * Reads a stably logged update (a serializable object) from a
+     * stream.  This callback is invoked during recovery, once for
+     * every record in the log.  After reading the update, this method
+     * invokes the applyUpdate (abstract) method in order to execute
+     * the update.
+     *
+     * @param in the input stream
+     * @throws Exception can raise any exception
+     */
+    public void readUpdate( InputStream in ) throws Exception
+    {
+        ObjectInputStream s = new ObjectInputStream( in );
+        applyUpdate( s.readObject() );
+    }
+
+    /**
+     * Reads a stably logged update (a serializable object) from a stream.
+     * This callback is invoked during recovery, once for every record in the
+     * log.  After reading the update, this method is invoked in order to
+     * execute the update.
+     *
+     * @param update the update object
+     * @throws Exception can raise any exception
+     */
+    public abstract void applyUpdate( Object update ) throws Exception;
+
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogInputStream.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogInputStream.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogInputStream.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogInputStream.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,175 @@
+/*
+ * 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 com.sun.jini.reliableLog;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * This class extends the functionality of the java.io.InputStream class
+ * in order to provide an input mechanism that can be used by processes
+ * that perform logging operations; in particular, processes that store
+ * state in order to provide persistence.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see java.io.InputStream
+ */
+public class LogInputStream extends InputStream
+{
+    private InputStream in;
+    private int length;
+
+    /**
+     * Creates a log input file with the specified input stream.
+     *
+     * @param in     the input stream
+     * @param length the total number of bytes allowed to be read
+     * @throws IOException If an I/O error has occurred.
+     */
+    public LogInputStream( InputStream in, int length ) throws IOException
+    {
+        this.in = in;
+        this.length = length;
+    }
+
+    /**
+     * Throw exception for reading past end of log record.
+     *
+     * @param numBytes number of bytes attempted to be read
+     * @throws LogException Attempt to read past end of log.
+     */
+    private void badRead( int numBytes ) throws LogException
+    {
+        throw new LogException( "length=" +
+                                String.valueOf( length ) +
+                                ", numBytes=" +
+                                String.valueOf( numBytes ) );
+    }
+
+    /**
+     * Reads a byte of data. This method will block if no input is
+     * available.
+     *
+     * @return the byte read, or -1 if the end of the stream is reached
+     * @throws LogException Attempt to read past end of log.
+     * @throws IOException  If an I/O error has occurred.
+     */
+    public int read() throws IOException, LogException
+    {
+        if( length < 1 )
+        {
+            badRead( 1 );
+        }
+        length--;
+        return in.read();
+    }
+
+    /**
+     * Reads data into an array of bytes.
+     * This method blocks until some input is available.
+     *
+     * @param b the buffer into which the data is read
+     * @return the actual number of bytes read, -1 is
+     *         returned when the end of the stream is reached
+     * @throws LogException Attempt to read past end of log.
+     * @throws IOException  If an I/O error has occurred.
+     */
+    public int read( byte b[] ) throws IOException, LogException
+    {
+        if( length < b.length )
+        {
+            badRead( b.length );
+        }
+        int len = in.read( b );
+        length -= len;
+        return len;
+    }
+
+    /**
+     * Reads data into an array of bytes.
+     * This method blocks until some input is available.
+     *
+     * @param b   the buffer into which the data is read
+     * @param off the start offset of the data
+     * @param len the maximum number of bytes read
+     * @return the actual number of bytes read, -1 is
+     *         returned when the end of the stream is reached
+     * @throws LogException Attempt to read past end of log.
+     * @throws IOException  If an I/O error has occurred.
+     */
+    public int read( byte b[], int off, int len )
+        throws IOException, LogException
+    {
+        if( length < len )
+        {
+            badRead( len );
+        }
+        len = in.read( b, off, len );
+        length -= len;
+        return len;
+    }
+
+    /**
+     * Skips n bytes of input.
+     *
+     * @param n the number of bytes to be skipped
+     * @return the actual number of bytes skipped
+     * @throws LogException Attempt to read past end of log.
+     * @throws IOException  If an I/O error has occurred.
+     */
+    public long skip( long n ) throws IOException, LogException
+    {
+        if( length < n )
+        {
+            badRead( (int) n );
+        }
+        n = in.skip( n );
+        length -= (int) n;
+        return n;
+    }
+
+    /**
+     * Returns the number of bytes that can be read without blocking.
+     *
+     * @return the number of available bytes, which is initially
+     *         equal to the file size
+     */
+    public int available()
+    {
+        return length;
+    }
+
+    /**
+     * Closes the input stream.  No further input can be read.
+     */
+    public void close()
+    {
+        length = 0;
+    }
+
+    /**
+     * Closes the stream when garbage is collected.
+     */
+    protected void finalize() throws IOException
+    {
+        close();
+    }
+
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogOutputStream.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogOutputStream.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/LogOutputStream.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,97 @@
+/*
+ * 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 com.sun.jini.reliableLog;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+
+
+/**
+ * This class extends the functionality of the java.io.OutputStream class
+ * in order to provide an output mechanism that can be used by processes
+ * that perform logging operations; in particular, processes that store
+ * state in order to provide persistence.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see java.io.OutputStream
+ */
+public class LogOutputStream extends OutputStream
+{
+
+    private RandomAccessFile raf;
+
+    /**
+     * Creates an output file with the specified <code>RandomAccessFile</code>
+     *
+     * @param raf the output file
+     * @throws IOException If an I/O error has occurred.
+     */
+    public LogOutputStream( RandomAccessFile raf ) throws IOException
+    {
+        this.raf = raf;
+    }
+
+    /**
+     * Writes a byte of data. This method will block until the byte is
+     * actually written.
+     *
+     * @param b the byte to be written
+     * @throws IOException If an I/O error has occurred.
+     */
+    public void write( int b ) throws IOException
+    {
+        raf.write( b );
+    }
+
+    /**
+     * Writes an array of bytes. Will block until the bytes
+     * are actually written.
+     *
+     * @param b the data to be written
+     * @throws IOException If an I/O error has occurred.
+     */
+    public void write( byte b[] ) throws IOException
+    {
+        raf.write( b );
+    }
+
+    /**
+     * Writes a sub-array of bytes.
+     *
+     * @param b   the data to be written
+     * @param off the start offset in the data
+     * @param len the number of bytes to write
+     * @throws IOException If an I/O error has occurred.
+     */
+    public void write( byte b[], int off, int len ) throws IOException
+    {
+        raf.write( b, off, len );
+    }
+
+    /**
+     * A LogOutputStream cannot be closed, so this does nothing.
+     *
+     * @throws IOException If an I/O error has occurred.
+     */
+    public final void close() throws IOException
+    {
+    }
+
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/ReliableLog.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/ReliableLog.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/ReliableLog.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/ReliableLog.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,614 @@
+/*
+ * 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 com.sun.jini.reliableLog;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.SyncFailedException;
+
+
+/**
+ * This class is a simple implementation of a reliable Log.  The
+ * client of a ReliableLog must provide a set of callbacks (via a
+ * LogHandler) that enables a ReliableLog to read and write snapshots
+ * (checkpoints) and log records.  This implementation ensures that the
+ * data stored (via a ReliableLog) is recoverable after a system crash.
+ * The implementation is unsynchronized; the client must synchronize
+ * externally. <p>
+ *
+ * The secondary storage strategy is to record values in files using a
+ * representation of the caller's choosing.  Two sorts of files are
+ * kept: snapshots and logs.  At any instant, one snapshot is current.
+ * The log consists of a sequence of updates that have occurred since
+ * the current snapshot was taken.  The current stable state is the
+ * value of the snapshot, as modified by the sequence of updates in
+ * the log.  From time to time, the client of a ReliableLog instructs
+ * the package to make a new snapshot and clear the log.  A ReliableLog
+ * arranges disk writes such that updates are stable (as long as the
+ * changes are force-written to disk) and atomic: no update is lost,
+ * and each update either is recorded completely in the log or not at
+ * all.  Making a new snapshot is also atomic. <p>
+ *
+ * Normal use for maintaining the recoverable store is as follows: The
+ * client maintains the relevant data structure in virtual memory.  As
+ * updates happen to the structure, the client informs the ReliableLog
+ * (call it "log") by calling log.update.  Periodically, the client
+ * calls log.snapshot to provide the current complete contents of the
+ * data.  On restart, the client calls log.recover to obtain the
+ * latest snapshot and the following sequences of updates; the client
+ * applies the updates to the snapshot to obtain the state that
+ * existed before the crash. <p>
+ *
+ * @author Sun Microsystems, Inc.
+ * @see LogHandler
+ */
+
+public class ReliableLog
+{
+
+    private static final String snapshotPrefix = "Snapshot.";
+    private static final String logfilePrefix = "Logfile.";
+    private static final String versionFile = "Version_Number";
+    private static final int MAGIC = 0xf2ecefe7;
+    private static final int FORMAT_UNPADDED = 0;
+    private static final int FORMAT_PADDED = 1;
+    private static final long intBytes = 4;
+
+    private final File dir;        // base directory
+    private int version = 0;        // current snapshot and log version
+    private int format = FORMAT_UNPADDED;
+    private String logName = null;
+    private RandomAccessFile log = null;
+    private FileDescriptor logFD;
+    private long snapshotBytes = 0;
+    private long logBytes = 0;
+    private final LogHandler handler;
+    private final byte[] intBuf = new byte[4];
+    private final byte[] zeroBuf = new byte[4];
+
+    /**
+     * Creates a ReliableLog to handle snapshots and logging in a
+     * stable storage directory, and sets up to recover any existing data
+     * from the stable storage directory. If there is no existing data,
+     * snapshot must be called next, otherwise recover must be called next.
+     *
+     * @param dirPath path to the stable storage directory
+     * @param handler the handler for log callbacks
+     * @throws LogException if the directory cannot be created or
+     *                      the current version in the directory is corrupted
+     * @throws IOException  if any other I/O error occurs
+     */
+    public ReliableLog( String dirPath, LogHandler handler ) throws IOException
+    {
+        dir = new File( dirPath );
+        if( !( dir.exists() ? dir.isDirectory() : dir.mkdir() ) )
+        {
+            throw new LogException( "could not create directory for log: " +
+                                    dirPath );
+        }
+        this.handler = handler;
+        try
+        {
+            DataInputStream in =
+                new DataInputStream( new FileInputStream( fName( versionFile ) ) );
+            try
+            {
+                version = in.readInt();
+            }
+            finally
+            {
+                in.close();
+            }
+        }
+        catch( IOException ex )
+        {
+            writeVersionFile();
+        }
+        if( version < 0 )
+        {
+            throw new LogException( "corrupted version file" );
+        }
+    }
+
+    /**
+     * Retrieves the contents of the snapshot file by calling the client
+     * supplied recover callback and then applies the incremental updates
+     * by calling the readUpdate callback for each logged updated.
+     *
+     * @throws LogException if recovery fails due to serious log corruption,
+     *                      or if an exception is thrown by the recover or readUpdate callbacks
+     * @throws IOException  if an other I/O error occurs
+     */
+    public void recover() throws IOException
+    {
+        if( version == 0 )
+        {
+            return;
+        }
+
+        String fname = versionName( snapshotPrefix );
+        File file = new File( fname );
+        InputStream in = new BufferedInputStream( new FileInputStream( file ) );
+        try
+        {
+            handler.recover( in );
+        }
+        catch( Exception e )
+        {
+            throw new LogException( "recovery failed", e );
+        }
+        finally
+        {
+            in.close();
+        }
+        snapshotBytes = file.length();
+
+        fname = versionName( logfilePrefix );
+        file = new File( fname );
+        DataInputStream din =
+            new DataInputStream( new BufferedInputStream(
+                new FileInputStream( file ) ) );
+        long length = file.length();
+        try
+        {
+            int updateLen = din.readInt();
+            /* have to worry about no MAGIC in original format */
+            if( updateLen == MAGIC )
+            {
+                format = din.readInt();
+                if( format != FORMAT_PADDED )
+                {
+                    throw new LogException( "corrupted log: bad log format" );
+                }
+                logBytes += ( intBytes + intBytes );
+                updateLen = din.readInt();
+            }
+            while( true )
+            {
+                if( updateLen == 0 )
+                { /* expected termination case */
+                    break;
+                }
+                if( updateLen < 0 )
+                { /* serious corruption */
+                    throw new LogException( "corrupted log: bad update length" );
+                }
+                if( length - logBytes - intBytes < updateLen )
+                {
+                    /* partial record at end of log; this should not happen
+                  * if forceToDisk is always true, but might happen if
+                  * buffered updates are used.
+                  */
+                    break;
+                }
+                try
+                {
+                    handler.readUpdate( new LogInputStream( din, updateLen ) );
+                }
+                catch( Exception e )
+                {
+                    throw new LogException( "read update failed", e );
+                }
+                logBytes += ( intBytes + updateLen );
+                if( format == FORMAT_PADDED )
+                {
+                    int offset = (int) logBytes & 3;
+                    if( offset > 0 )
+                    {
+                        offset = 4 - offset;
+                        logBytes += offset;
+                        din.skipBytes( offset );
+                    }
+                }
+                updateLen = din.readInt();
+            } /* while */
+        }
+        catch( EOFException e )
+        {
+        }
+        finally
+        {
+            din.close();
+        }
+        /* reopen log file at end */
+        openLogFile();
+    }
+
+    /**
+     * Records this update in the log file and forces the update to disk.
+     * The update is recorded by calling the client's writeUpdate callback.
+     * This method must not be called until this log's recover method has
+     * been invoked (and completed).
+     *
+     * @param value the object representing the update
+     * @throws LogException if an exception is thrown by the writeUpdate
+     *                      callback, or forcing the update to disk fails
+     * @throws IOException  if any other I/O error occurs
+     */
+    public void update( Object value ) throws IOException
+    {
+        update( value, true );
+    }
+
+    /**
+     * Records this update in the log file and optionally forces the update
+     * to disk.  The update is recorded by calling the client's writeUpdate
+     * callback.  This method must not be called until this log's recover
+     * method has been invoked (and completed).
+     *
+     * @param value       the object representing the update
+     * @param forceToDisk true if the update should be forced to disk, false
+     *                    if the updates should be buffered
+     * @throws LogException if an exception is thrown by the writeUpdate
+     *                      callback, or forcing the update to disk fails
+     * @throws IOException  if any other I/O error occurs
+     */
+    public void update( Object value, boolean forceToDisk ) throws IOException
+    {
+        /* avoid accessing a null log field */
+        if( log == null )
+        {
+            throw new LogException( "log file for persistent state is "
+                                    + "inaccessible, it may have been "
+                                    + "corrupted or closed" );
+        }
+        /* note: zero length header for this update was written as part
+       * of the previous update, or at initial opening of the log file
+       */
+        try
+        {
+            handler.writeUpdate( new LogOutputStream( log ), value );
+        }
+        catch( Exception e )
+        {
+            throw new LogException( "write update failed", e );
+        }
+        if( forceToDisk )
+        {
+            /* must force contents to disk before writing real length header */
+            try
+            {
+                logFD.sync();
+            }
+            catch( SyncFailedException sfe )
+            {
+                throw new LogException( "sync log failed", sfe );
+            }
+        }
+        long entryEnd = log.getFilePointer();
+        long updateLen = entryEnd - logBytes - intBytes;
+        if( updateLen > Integer.MAX_VALUE )
+        {
+            throw new LogException( "maximum record length exceeded" );
+        }
+        /* write real length header */
+        log.seek( logBytes );
+        writeInt( log, (int) updateLen );
+        /* pad out update record so length header does not span disk blocks */
+        if( format == FORMAT_PADDED )
+        {
+            entryEnd = ( entryEnd + 3 ) & ~3L;
+        }
+        /* write zero length header for next update */
+        log.seek( entryEnd );
+        log.write( zeroBuf );
+        logBytes = entryEnd;
+        /* force both length headers to disk */
+        if( forceToDisk )
+        {
+            try
+            {
+                logFD.sync();
+            }
+            catch( SyncFailedException sfe )
+            {
+                throw new LogException( "sync log failed", sfe );
+            }
+        }
+    }
+
+    /**
+     * Write an int value in single write operation.
+     *
+     * @param out output stream
+     * @param val int value
+     * @throws IOException if any other I/O error occurs
+     */
+    private void writeInt( DataOutput out, int val ) throws IOException
+    {
+        intBuf[ 0 ] = (byte) ( val >> 24 );
+        intBuf[ 1 ] = (byte) ( val >> 16 );
+        intBuf[ 2 ] = (byte) ( val >> 8 );
+        intBuf[ 3 ] = (byte) val;
+        out.write( intBuf );
+    }
+
+    /**
+     * Records the client-defined current snapshot by invoking the client
+     * supplied snapshot callback, and then empties the log of incremental
+     * updates.
+     *
+     * @throws LogException if the snapshot callback throws an exception
+     * @throws IOException  if any other I/O error occurs
+     */
+    public void snapshot() throws IOException
+    {
+        int oldVersion = version;
+        version++;
+
+        String fname = versionName( snapshotPrefix );
+        File snapshotFile = new File( fname );
+        FileOutputStream out = new FileOutputStream( snapshotFile );
+        try
+        {
+            try
+            {
+                handler.snapshot( out );
+                /* force contents to disk */
+                out.getFD().sync();
+            }
+            catch( Exception e )
+            {
+                throw new LogException( "snapshot failed", e );
+            }
+            snapshotBytes = snapshotFile.length();
+        }
+        finally
+        {
+            out.close();
+        }
+
+        logBytes = 0;
+        openLogFile();
+        writeVersionFile();
+        deleteSnapshot( oldVersion );
+        deleteLogFile( oldVersion );
+    }
+
+    /**
+     * Closes the stable storage directory in an orderly manner.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    public void close() throws IOException
+    {
+        if( log == null )
+        {
+            return;
+        }
+        try
+        {
+            log.close();
+        }
+        finally
+        {
+            log = null;
+        }
+    }
+
+    /**
+     * Closes the incremental update log file, removes all ReliableLog-related
+     * files from the stable storage directory, and deletes the directory.
+     */
+    public void deletePersistentStore()
+    {
+        try
+        {
+            close();
+        }
+        catch( IOException e )
+        {
+        }
+        try
+        {
+            deleteLogFile( version );
+        }
+        catch( LogException e )
+        {
+        }
+        try
+        {
+            deleteSnapshot( version );
+        }
+        catch( LogException e )
+        {
+        }
+        try
+        {
+            deleteFile( fName( versionFile ) );
+        }
+        catch( LogException e )
+        {
+        }
+        try
+        {
+            /* Delete the directory. The following call to the delete method
+            * will fail only if the directory is not empty or if the Security
+            * Manager's checkDelete() method throws a SecurityException.
+            * (The Security Manager will throw such an exception if it
+            * determines that the current application is not allowed to
+            * delete the directory.) For either case, upon un-successful
+            * deletion of the directory, take no further action.
+            */
+            dir.delete();
+        }
+        catch( SecurityException e )
+        {
+        }
+    }
+
+    /**
+     * Returns the size of the current snapshot file in bytes;
+     */
+    public long snapshotSize()
+    {
+        return snapshotBytes;
+    }
+
+    /**
+     * Returns the current size of the incremental update log file in bytes;
+     */
+    public long logSize()
+    {
+        return logBytes;
+    }
+
+    /**
+     * Generates a filename prepended with the stable storage directory path.
+     *
+     * @param name the name of the file (sans directory path)
+     */
+    private String fName( String name )
+    {
+        return dir.getPath() + File.separator + name;
+    }
+
+    /**
+     * Generates a version filename prepended with the stable storage
+     * directory path with the current version number as a suffix.
+     *
+     * @param name version filename prefix
+     */
+    private String versionName( String name )
+    {
+        return versionName( name, version );
+    }
+
+    /**
+     * Generates a version filename prepended with the stable storage
+     * directory path with the given version number as a suffix.
+     *
+     * @param prefix version filename prefix
+     * @param ver    version number
+     */
+    private String versionName( String prefix, int ver )
+    {
+        return fName( prefix ) + String.valueOf( ver );
+    }
+
+    /**
+     * Deletes a file.
+     *
+     * @param name the name of the file (complete path)
+     * @throws LogException if file cannot be deleted
+     */
+    private void deleteFile( String name ) throws LogException
+    {
+        if( !new File( name ).delete() )
+        {
+            throw new LogException( "couldn't delete file: " + name );
+        }
+    }
+
+    /**
+     * Removes the snapshot file.
+     *
+     * @param ver the version to remove
+     * @throws LogException if file cannot be deleted
+     */
+    private void deleteSnapshot( int ver ) throws LogException
+    {
+        if( ver != 0 )
+        {
+            deleteFile( versionName( snapshotPrefix, ver ) );
+        }
+    }
+
+    /**
+     * Removes the incremental update log file.
+     *
+     * @param ver the version to remove
+     * @throws LogException if file cannot be deleted
+     */
+    private void deleteLogFile( int ver ) throws LogException
+    {
+        if( ver != 0 )
+        {
+            deleteFile( versionName( logfilePrefix, ver ) );
+        }
+    }
+
+    /**
+     * Opens the incremental update log file in read/write mode.  If the
+     * file does not exist, it is created.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    private void openLogFile() throws IOException
+    {
+        try
+        {
+            close();
+        }
+        catch( IOException e )
+        { /* assume this is okay */
+        }
+
+        logName = versionName( logfilePrefix );
+        log = new RandomAccessFile( logName, "rw" );
+        logFD = log.getFD();
+
+        if( logBytes == 0 )
+        {
+            format = FORMAT_PADDED;
+            writeInt( log, MAGIC );
+            writeInt( log, format );
+            logBytes = ( intBytes + intBytes );
+        }
+        else
+        {
+            log.seek( logBytes );
+        }
+        log.setLength( logBytes );
+        /* always start out with zero length header for the next update */
+        log.write( zeroBuf );
+        /* force length header to disk */
+        logFD.sync();
+    }
+
+    /**
+     * Writes the current version number to the version file.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    private void writeVersionFile() throws IOException
+    {
+        RandomAccessFile out = new RandomAccessFile( fName( versionFile ), "rw" );
+        try
+        {
+            /* write should be atomic (four bytes on one disk block) */
+            writeInt( out, version );
+            /* force version to disk */
+            out.getFD().sync();
+        }
+        finally
+        {
+            out.close();
+        }
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/package.html
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/package.html?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/package.html (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/logging/src/main/java/com/sun/jini/reliableLog/package.html Tue Dec  9 21:25:00 2008
@@ -0,0 +1,34 @@
+<!--
+ ! 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.
+ !-->
+
+<HTML>
+<BODY BGCOLOR="white">
+
+Reliable log is used to store state in case of system crash
+or reboot.
+A <CODE>ReliableLog</CODE> class writes serialized objects to a log file,
+where the objects represent change in state that must be recorded.
+After each object is logged, its data is forced to the disk.
+You can create snapshots that record the current state to disk,
+creating a new starting point for logging, and
+making previously logged changes obsolete.
+Such snapshots allow you to compress the log, making recovery more
+efficient in cases where the state is modified, not simply added to.
+
+</BODY>
+</HTML>

Added: incubator/river/jtsk/skunk/niclas1/shared/pom.xml
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/pom.xml?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/pom.xml (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/pom.xml Tue Dec  9 21:25:00 2008
@@ -0,0 +1,29 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.river</groupId>
+        <artifactId>master</artifactId>
+        <version>10.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.river.shared</groupId>
+    <artifactId>master-shared</artifactId>
+    <name>Master - Services</name>
+    <packaging>pom</packaging>
+    <version>10.0-SNAPSHOT</version>
+    <!-- This POM is ONLY to initiate the modules to be built. -->
+
+    <modules>
+        <module>action</module>
+        <module>collection</module>
+        <module>constants</module>
+        <module>landlord</module>
+        <module>logging</module>
+        <module>proxy</module>
+        <module>service</module>
+        <module>system</module>
+        <module>thread</module>
+    </modules>
+
+</project>

Added: incubator/river/jtsk/skunk/niclas1/shared/proxy/pom.xml
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/proxy/pom.xml?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/proxy/pom.xml (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/proxy/pom.xml Tue Dec  9 21:25:00 2008
@@ -0,0 +1,39 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.river.service</groupId>
+        <artifactId>master-services</artifactId>
+        <version>10.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.river.shared</groupId>
+    <artifactId>river-proxy</artifactId>
+    <name>Apache River - Shared - Proxy</name>
+    <packaging>jar</packaging>
+    <version>10.0-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.river.core</groupId>
+      <artifactId>river-core-api</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-constraint</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-export</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.shared</groupId>
+      <artifactId>river-logging</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>

Added: incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/BasicProxyTrustVerifier.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/BasicProxyTrustVerifier.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/BasicProxyTrustVerifier.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/BasicProxyTrustVerifier.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,124 @@
+/*
+ * 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 com.sun.jini.proxy;
+
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import net.jini.core.constraint.MethodConstraints;
+import net.jini.core.constraint.RemoteMethodControl;
+import net.jini.export.proxytrust.ServerProxyTrust;
+import net.jini.export.proxytrust.TrustEquivalence;
+import net.jini.security.TrustVerifier;
+
+/**
+ * A basic trust verifier for proxies.  This trust verifier is used to
+ * verify that object passed to its {@link #isTrustedObject
+ * isTrustedObject} method is equivalent in trust, content, and function to
+ * the known trusted object that the trust verifier is constructed with.
+ * This trust verifier is typically returned by an implementation of the
+ * {@link ServerProxyTrust#getProxyVerifier
+ * ServerProxyTrust.getProxyVerifier} method.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public final class BasicProxyTrustVerifier
+    implements TrustVerifier, Serializable
+{
+    private static final long serialVersionUID = 2L;
+
+    /**
+     * The trusted proxy.
+     *
+     * @serial
+     */
+    private final RemoteMethodControl proxy;
+
+    /**
+     * Creates a trust verifier containing the specified trusted proxy.
+     *
+     * @param proxy the trusted proxy
+     * @throws IllegalArgumentException if the specified proxy is
+     *                                  not an instance of {@link RemoteMethodControl} or
+     *                                  {@link TrustEquivalence}
+     */
+    public BasicProxyTrustVerifier( Object proxy )
+    {
+        if( !( proxy instanceof RemoteMethodControl ) )
+        {
+            throw new IllegalArgumentException(
+                "proxy not a RemoteMethodControl instance" );
+        }
+        else if( !( proxy instanceof TrustEquivalence ) )
+        {
+            throw new IllegalArgumentException(
+                "proxy not a TrustEquivalence instance" );
+        }
+        this.proxy = (RemoteMethodControl) proxy;
+    }
+
+    /**
+     * Verifies trust in a proxy. Returns <code>true</code> if and only if
+     * the specified object is an instance of {@link RemoteMethodControl}
+     * and invoking the {@link TrustEquivalence#checkTrustEquivalence
+     * checkTrustEquivalence} method on a proxy that is this verifier's
+     * proxy with the same method constraints of the specified object,
+     * passing the specified object returns <code>true</code>.
+     */
+    public boolean isTrustedObject( Object obj, TrustVerifier.Context ctx )
+    {
+        if( obj == null || ctx == null )
+        {
+            throw new NullPointerException();
+        }
+        else if( !( obj instanceof RemoteMethodControl ) )
+        {
+            return false;
+        }
+        RemoteMethodControl unverifiedProxy = (RemoteMethodControl) obj;
+        MethodConstraints constraints = unverifiedProxy.getConstraints();
+        TrustEquivalence trustedProxy =
+            (TrustEquivalence) proxy.setConstraints( constraints );
+        return trustedProxy.checkTrustEquivalence( unverifiedProxy );
+    }
+
+    /**
+     * @throws InvalidObjectException if the proxy is not an instance of
+     *                                {@link RemoteMethodControl} and {@link TrustEquivalence}
+     */
+    private void readObject( ObjectInputStream in )
+        throws IOException, ClassNotFoundException
+    {
+        in.defaultReadObject();
+        if( !( proxy instanceof RemoteMethodControl ) )
+        {
+            throw new InvalidObjectException(
+                "proxy not a RemoteMethodControl instance" );
+        }
+        else if( !( proxy instanceof TrustEquivalence ) )
+        {
+            throw new InvalidObjectException(
+                "proxy not a TrustEquivalence instance" );
+        }
+    }
+}
+    

Added: incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/ConstrainableProxyUtil.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/ConstrainableProxyUtil.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/ConstrainableProxyUtil.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/ConstrainableProxyUtil.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,212 @@
+/*
+ * 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 com.sun.jini.proxy;
+
+import java.io.InvalidObjectException;
+import java.lang.reflect.Method;
+import net.jini.constraint.BasicMethodConstraints;
+import net.jini.constraint.BasicMethodConstraints.MethodDesc;
+import net.jini.core.constraint.InvocationConstraints;
+import net.jini.core.constraint.MethodConstraints;
+import net.jini.core.constraint.RemoteMethodControl;
+
+/**
+ * A collection of utility methods for use in implementing constrainable
+ * proxies.  This class cannot be instantiated.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class ConstrainableProxyUtil
+{
+
+    /**
+     * This class cannot be instantiated.
+     */
+    private ConstrainableProxyUtil()
+    {
+        throw new AssertionError();
+    }
+
+    /**
+     * Creates a {@link MethodConstraints} using the constraints in
+     * <code>methodConstraints</code>, but with the methods remapped according
+     * to <code>mappings</code>, where the first element of each pair of
+     * elements is mapped to the second.  For example, if
+     * <code>methodConstraints</code> returns constraints <code>C1</code> for
+     * method <code>M1</code>, and the elements of mappings are methods
+     * <code>M1</code> and <code>M2</code>, then the resulting method
+     * constraints return <code>C1</code> for method <code>M2</code>.
+     *
+     * @param methodConstraints the method constraints whose methods should be
+     *                          translated, or <code>null</code> for empty constraints
+     * @param mappings          the method mappings
+     * @return the translated method constraints
+     * @throws NullPointerException     if <code>mappings</code> is
+     *                                  <code>null</code> or contains <code>null</code> elements
+     * @throws IllegalArgumentException if <code>mappings</code> contains an
+     *                                  odd number of elements
+     */
+    public static MethodConstraints translateConstraints(
+        MethodConstraints methodConstraints,
+        Method[] mappings )
+    {
+        if( mappings.length % 2 != 0 )
+        {
+            throw new IllegalArgumentException( "mappings has odd length" );
+        }
+        else if( methodConstraints == null )
+        {
+            return null;
+        }
+        int count = mappings.length / 2;
+        MethodDesc[] descs = new MethodDesc[count];
+        for( int i = mappings.length - 1; i >= 0; i -= 2 )
+        {
+            Method from = mappings[ i - 1 ];
+            Method to = mappings[ i ];
+            descs[ --count ] = new MethodDesc(
+                to.getName(), to.getParameterTypes(),
+                methodConstraints.getConstraints( from ) );
+        }
+        return new BasicMethodConstraints( descs );
+    }
+
+    /**
+     * Test to see if two {@link MethodConstraints} instances are
+     * equivalent given a method-to-method mapping. Only the
+     * constraints for methods that appear in the mapping are
+     * compared. The mapping is represented by an array, <code>
+     * mappings</code>, of 2n {@link Method} objects.  For all values
+     * p less than n the constraints associated with
+     * <code>mappings[2p]</code> in <code>methodConstraints1</code>
+     * are compared to the constraints associated with
+     * <code>mappings[2p+1]</code> in
+     * <code>methodConstraints2</code>. If null is passed in for both
+     * instances they are considered equivalent.
+     *
+     * @param methodConstraints1 the first <code>MethodConstraints</code>
+     *                           object to compare.
+     * @param methodConstraints2 the second <code>MethodConstraints</code>
+     *                           object to compare.
+     * @param mappings           the method-to-method mapping.
+     * @return <code>true</code> if the <code>MethodConstraints</code>
+     *         instances represent equivalent constraints, returns
+     *         <code>false</code> otherwise.
+     * @throws NullPointerException     if <code>mapping</code> is
+     *                                  <code>null</code> contains <code>null</code> elements.
+     * @throws IllegalArgumentException if <code>mapping</code> contains an
+     *                                  odd number of elements
+     */
+    public static boolean equivalentConstraints(
+        MethodConstraints methodConstraints1,
+        MethodConstraints methodConstraints2,
+        Method[] mappings )
+    {
+        if( mappings.length % 2 != 0 )
+        {
+            throw new IllegalArgumentException( "mappings has odd length" );
+        }
+
+        // both null means they are equivalent.
+        if( methodConstraints1 == null && methodConstraints2 == null )
+        {
+            return true;
+        }
+
+        // If only one is null they are not equivalent
+        if( methodConstraints1 == null || methodConstraints2 == null )
+        {
+            return false;
+        }
+
+        // Both non-null need to run though map check
+        final int count = mappings.length / 2;
+        for( int i = 0; i < mappings.length; i += 2 )
+        {
+            final InvocationConstraints c1 =
+                methodConstraints1.getConstraints( mappings[ i ] );
+            final InvocationConstraints c2 =
+                methodConstraints2.getConstraints( mappings[ i + 1 ] );
+            if( !c1.equals( c2 ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Verify that an object, <code>proxy</code>, is an instance of
+     * {@link RemoteMethodControl} its {@link MethodConstraints} are
+     * equivalent to another <code>MethodConstraints</code> instance,
+     * <code>methodConstraints</code> once a mapping has been applied.
+     * If <code>proxy</code> does not implement
+     * <code>RemoteMethodControl</code> or the associated constraints are
+     * not equivalent throw an {@link InvalidObjectException}. The
+     * mapping is represented by an array, <code>mappings</code>, of
+     * 2n {@link Method} objects. For all values p less than n the
+     * constraints associated with <code>mappings[2p]</code> in
+     * <code>methodConstraints</code> are compared to the constraints
+     * associated with <code>mappings[2p+1]</code> in the
+     * <code>MethodConstraints</code> returned by
+     * <code>proxy.getConstraints</code>. Will also return normally if
+     * both <code>methodConstraints</code> and the value returned by
+     * <code>proxy.getConstraints</code> are <code>null</code>.
+     *
+     * @param methodConstraints the method constraints
+     *                          <code>proxy</code> should have.
+     * @param proxy             the proxy to test, must implement
+     *                          <code>RemoteMethodControl</code>.
+     * @param mappings          the method to method mapping
+     * @throws NullPointerException     if <code>mappings</code> or
+     *                                  <code>proxy</code> is <code>null</code> or if
+     *                                  <code>mapping</code> contains <code>null</code> elements
+     * @throws IllegalArgumentException if <code>mappings</code> contains an
+     *                                  odd number of elements
+     * @throws InvalidObjectException   if <code>proxy</code> does
+     *                                  not implement <code>RemoteMethodControl</code>, or if
+     *                                  the constraints on <code>proxy</code> are not
+     *                                  equivalent to <code>methodConstraints</code>.
+     */
+    public static void verifyConsistentConstraints(
+        MethodConstraints methodConstraints, Object proxy, Method[] mappings )
+        throws InvalidObjectException
+    {
+        if( !( proxy instanceof RemoteMethodControl ) )
+        {
+            throw new InvalidObjectException(
+                "Proxy does not implement RemoteMethodControl" );
+        }
+
+        final MethodConstraints proxyMethodConstraints =
+            ( (RemoteMethodControl) proxy ).getConstraints();
+
+        if( !equivalentConstraints( methodConstraints, proxyMethodConstraints,
+                                    mappings ) )
+        {
+            // Not equivalent, complain.
+            throw new InvalidObjectException(
+                "Inconsistent constraints on proxy" );
+        }
+
+        // else everything is ok, normal return
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/MarshalledWrapper.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/MarshalledWrapper.java?rev=724995&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/MarshalledWrapper.java (added)
+++ incubator/river/jtsk/skunk/niclas1/shared/proxy/src/main/java/com/sun/jini/proxy/MarshalledWrapper.java Tue Dec  9 21:25:00 2008
@@ -0,0 +1,212 @@
+/*
+ * 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 com.sun.jini.proxy;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Iterator;
+import net.jini.io.MarshalledInstance;
+import net.jini.io.ObjectStreamContext;
+import net.jini.io.context.IntegrityEnforcement;
+
+/**
+ * Wrapper around {@link MarshalledInstance} that samples the integrity setting
+ * (if any) of the stream it is unmarshalled from, and uses that setting to
+ * determine whether or not to verify codebase integrity when calling the
+ * {@link MarshalledInstance#get(boolean) get} method of the contained
+ * <code>MarshalledInstance</code>.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class MarshalledWrapper implements Serializable
+{
+
+    private static final long serialVersionUID = 2L;
+
+    /**
+     * The wrapped MarshalledInstance.
+     *
+     * @serial
+     */
+    private final MarshalledInstance instance;
+    /**
+     * Flag set to true if this instance was unmarshalled from an
+     * integrity-protected stream, or false otherwise
+     */
+    private transient boolean integrity = false;
+
+    /**
+     * Returns the integrity protection setting of the given stream, determined
+     * as follows: if the stream implements {@link ObjectStreamContext} and has
+     * in its context collection an object of type
+     * {@link IntegrityEnforcement}, the
+     * {@link IntegrityEnforcement#integrityEnforced integrityEnforced} method
+     * of that object is called and the resulting value returned; otherwise,
+     * <code>false</code> is returned.
+     *
+     * @return integrity protection setting of the given stream
+     */
+    public static boolean integrityEnforced( ObjectInputStream stream )
+    {
+        if( stream instanceof ObjectStreamContext )
+        {
+            Collection ctx =
+                ( (ObjectStreamContext) stream ).getObjectStreamContext();
+            for( Iterator i = ctx.iterator(); i.hasNext(); )
+            {
+                Object obj = i.next();
+                if( obj instanceof IntegrityEnforcement )
+                {
+                    return ( (IntegrityEnforcement) obj ).integrityEnforced();
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates a new <code>MarshalledWrapper</code> wrapping a
+     * <code>MarshalledInstance</code> containing the given object.
+     *
+     * @param obj object to create <code>MarshalledInstance</code> with
+     * @throws IOException if <code>MarshalledInstance</code> creation fails
+     */
+    public MarshalledWrapper( Object obj ) throws IOException
+    {
+        instance = new MarshalledInstance( obj );
+    }
+
+    /**
+     * Creates a new <code>MarshalledWrapper</code> wrapping the given
+     * <code>MarshalledInstance</code>.
+     *
+     * @param instance <code>MarshalledInstance</code> to wrap
+     * @throws NullPointerException if <code>instance</code> is
+     *                              <code>null</code>
+     */
+    public MarshalledWrapper( MarshalledInstance instance )
+    {
+        if( instance == null )
+        {
+            throw new NullPointerException();
+        }
+        this.instance = instance;
+    }
+
+    /**
+     * Returns the result of calling the {@link MarshalledInstance#get(boolean)
+     * get} method of the wrapped <code>MarshalledInstance</code>, passing the
+     * integrity value sampled during deserialization as the
+     * <code>verifyCodebaseIntegrity</code> argument.  If this
+     * <code>MarshalledWrapper</code> instance was not produced by
+     * deserialization or was deserialized from a stream with no integrity
+     * protection setting, then a <code>verifyCodebaseIntegrity</code> value of
+     * <code>false</code> is used.
+     *
+     * @return the object unmarshalled by the wrapped
+     *         <code>MarshalledInstance</code>
+     * @throws IOException            if an <code>IOException</code> occurs during
+     *                                unmarshalling
+     * @throws ClassNotFoundException if any classes necessary for
+     *                                reconstructing the object being unmarshalled cannot be found
+     */
+    public Object get() throws IOException, ClassNotFoundException
+    {
+        return instance.get( integrity );
+    }
+
+    /**
+     * Returns the <code>MarshalledInstance</code> wrapped by this
+     * <code>MarshalledWrapper</code>.
+     *
+     * @return wrapped <code>MarshalledInstance</code>
+     */
+    public MarshalledInstance getMarshalledInstance()
+    {
+        return instance;
+    }
+
+    /**
+     * Returns the integrity value sampled during deserialization of this
+     * <code>MarshalledWrapper</code> instance, or <code>false</code> if this
+     * instance was not produced by deserialization or was deserialized from a
+     * stream with no integrity protection setting.
+     *
+     * @return sampled integrity value
+     */
+    public boolean getIntegrity()
+    {
+        return integrity;
+    }
+
+    /**
+     * Returns the hash code value for this <code>MarshalledWrapper</code>.
+     *
+     * @return the hash code value for this <code>MarshalledWrapper</code>.
+     */
+    public int hashCode()
+    {
+        return MarshalledWrapper.class.hashCode() ^ instance.hashCode();
+    }
+
+    /**
+     * Compares the specified object with this <code>MarshalledWrapper</code>
+     * for equality.  This method returns <code>true</code> if and only if the
+     * specified object is of the same class as this object and its wrapped
+     * <code>MarshalledInstance</code> is equal to the one in this object.
+     *
+     * @param obj object to compare with
+     * @return <code>true</code> if <code>obj</code> is equivalent to
+     *         this object; <code>false</code> otherwise
+     */
+    public boolean equals( Object obj )
+    {
+        return obj == this ||
+               ( obj != null &&
+                 obj.getClass() == getClass() &&
+                 instance.equals( ( (MarshalledWrapper) obj ).instance ) );
+    }
+
+    /**
+     * Samples integrity protection setting (if any) of the stream from which
+     * this instance is being deserialized.
+     */
+    private void readObject( ObjectInputStream in )
+        throws IOException, ClassNotFoundException
+    {
+        in.defaultReadObject();
+        if( instance == null )
+        {
+            throw new InvalidObjectException( "null instance" );
+        }
+        integrity = integrityEnforced( in );
+    }
+
+    /**
+     * Throws InvalidObjectException, since data for this class is required.
+     */
+    private void readObjectNoData() throws ObjectStreamException
+    {
+        throw new InvalidObjectException( "no data" );
+    }
+}



Mime
View raw message