You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by ni...@apache.org on 2008/12/10 06:11:41 UTC
svn commit: r724975 [4/7] - in
/incubator/river/jtsk/skunk/niclas1/services/norm: ./ src/ src/main/
src/main/java/ src/main/java/com/ src/main/java/com/sun/
src/main/java/com/sun/jini/ src/main/java/com/sun/jini/norm/
src/main/java/com/sun/jini/norm/ev...
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/PersistentStore.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/PersistentStore.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/PersistentStore.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/PersistentStore.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,346 @@
+/*
+ * 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.norm;
+
+import com.sun.jini.norm.lookup.SubStore;
+import com.sun.jini.reliableLog.LogHandler;
+import com.sun.jini.reliableLog.ReliableLog;
+import com.sun.jini.system.FileSystem;
+import com.sun.jini.thread.ReadersWriter;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.config.ConfigurationException;
+
+/**
+ * Class that actually stores a Norm server's state to disk. Basically
+ * a wrapper around ReliableLog with the addition of lock management.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+class PersistentStore
+{
+ /**
+ * Logger for logging messages for this class
+ */
+ private static final Logger logger = Logger.getLogger( "com.sun.jini.norm" );
+
+ /**
+ * Object we use to reliably and persistently log updates to our
+ * state, or null if not persistent.
+ */
+ private ReliableLog log;
+
+ /**
+ * No mutation of persistent state can occur during a snapshot,
+ * however, we can have multiple mutators, use
+ * <code>ReadersWriter</code> object to manage this invariant. Note
+ * as far as the lock is concerned the mutators are the readers and
+ * snapshot thread the writer since for us mutation is the
+ * non-exclusive operation.
+ */
+ final private ReadersWriter mutatorLock = new ReadersWriter();
+
+ /**
+ * Thread local that tracks if (and how many times) the current thread
+ * has acquired a non-exclusive mutator lock.
+ */
+ final static private ThreadLocal lockState = new ThreadLocal();
+
+ /**
+ * Cache a <code>Long</code> object with a zero value
+ */
+ final static private Long zero = new Long( 0 );
+
+ /**
+ * Location of the persistent store, or null if not persistent
+ */
+ final private File storeLocation;
+
+ /**
+ * Object that handles the recovery of logs, or null if not persistent
+ */
+ final private LogHandler logHandler;
+
+ /**
+ * The NormServer we are part of
+ */
+ final private NormServerBaseImpl server;
+
+ /**
+ * Number of updates since last snapshot
+ */
+ private int updateCount;
+
+ /**
+ * A list of all of the sub-stores
+ */
+ private List subStores = new LinkedList();
+
+ /**
+ * Construct a store that will persist its data to the specified
+ * directory.
+ *
+ * @param logDir directory where the store should persist its data,
+ * which must exist, unless it is <code>null</code>, in which case
+ * there is no persistence
+ * @param logHandler object that will process the log and last
+ * snapshot to recover the server's state
+ * @param server the server is called back after an update so it can
+ * decide whether or not to do a snapshot
+ * @throws StoreException if there is a problem setting up the store
+ */
+ PersistentStore( String logDir, LogHandler logHandler,
+ NormServerBaseImpl server )
+ throws StoreException
+ {
+ this.logHandler = logHandler;
+ this.server = server;
+ if( logDir == null )
+ {
+ storeLocation = null;
+ }
+ else
+ {
+ storeLocation = new File( logDir );
+ try
+ {
+ log = new ReliableLog(
+ storeLocation.getCanonicalPath(), logHandler );
+ }
+ catch( IOException e )
+ {
+ throw new CorruptedStoreException(
+ "Failure creating reliable log", e );
+ }
+
+ try
+ {
+ log.recover();
+ }
+ catch( IOException e )
+ {
+ throw new CorruptedStoreException(
+ "Failure recovering reliable log", e );
+ }
+ }
+ }
+
+ /**
+ * Destroy the store.
+ *
+ * @throws IOException if it has difficulty removing the log files
+ */
+ void destroy() throws IOException
+ {
+ // Prep all the sub-stores to be destroyed
+ for( Iterator i = subStores.iterator(); i.hasNext(); )
+ {
+ SubStore subStore = (SubStore) i.next();
+ subStore.prepareDestroy();
+ }
+ if( log != null )
+ {
+ log.deletePersistentStore();
+ FileSystem.destroy( storeLocation, true );
+ }
+ }
+
+ /**
+ * Inform the store of a sub-store
+ */
+ void addSubStore( SubStore subStore ) throws StoreException
+ {
+ try
+ {
+ if( log == null )
+ {
+ subStore.setDirectory( null );
+ }
+ else
+ {
+ final String subDir = subStore.subDirectory();
+
+ if( subDir == null )
+ {
+ subStore.setDirectory( storeLocation );
+ }
+ else
+ {
+ subStore.setDirectory( new File( storeLocation, subDir ) );
+ }
+ }
+
+ subStores.add( subStore );
+ }
+ catch( IOException e )
+ {
+ throw new StoreException( "Failure adding substore " + subStore,
+ e );
+ }
+ catch( ConfigurationException e )
+ {
+ throw new StoreException( "Failure adding substore " + subStore,
+ e );
+ }
+ }
+
+
+ /////////////////////////////////////////////////////////////////
+ // Methods for obtaining and releasing the locks on the store
+
+ /**
+ * Block until we can acquire a non-exclusive mutator lock on the
+ * server's persistent state. This lock should be acquired in a
+ * <code>try</code> block and a <code>releaseMutatorLock</code> call
+ * should be placed in a <code>finally</code> block.
+ */
+ void acquireMutatorLock()
+ {
+ // Do we already hold a lock?
+
+ Long lockStateVal = (Long) lockState.get();
+ if( lockStateVal == null )
+ {
+ lockStateVal = zero;
+ }
+
+ final long longVal = lockStateVal.longValue();
+
+ if( longVal == 0 )
+ {
+ // No, this thread currently does not hold a lock,
+ // grab non-exclusive lock (which for mutatorLock is a
+ // read lock)
+ mutatorLock.readLock();
+ }
+
+ // Either way, bump the lock count and update our thread state
+ lockState.set( new Long( longVal + 1 ) );
+ }
+
+ /**
+ * Release one level of mutator locks if this thread holds at least one.
+ */
+ void releaseMutatorLock()
+ {
+ Long lockStateVal = (Long) lockState.get();
+ if( lockStateVal == null )
+ {
+ lockStateVal = zero;
+ }
+
+ final long longVal = lockStateVal.longValue();
+
+ if( longVal == 0 )
+ {
+ // No lock to release, return
+ return;
+ }
+
+ if( longVal == 1 )
+ {
+ // Last one on stack release lock
+ // Using read lock because we want a non-exclusive lock
+ mutatorLock.readUnlock();
+ lockStateVal = zero;
+ }
+ else
+ {
+ lockStateVal = new Long( longVal - 1 );
+ }
+
+ lockState.set( lockStateVal );
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // Methods for writing records to the log and taking and
+ // coordinating snapshots
+
+ /**
+ * Log an update. Will flush to disk before returning.
+ *
+ * @throws IllegalStateException if the current thread does not hold
+ * a non-exclusive mutator lock
+ * @throws IOException
+ * @see ReliableLog#update
+ */
+ void update( Object o )
+ {
+ if( log == null )
+ {
+ return;
+ }
+ final Long lockStateVal = (Long) lockState.get();
+ if( lockStateVal == null || lockStateVal.longValue() == 0 )
+ {
+ throw new IllegalStateException( "PersistentStore.update:" +
+ "Must acquire mutator lock before calling update()" );
+ }
+
+ synchronized( this )
+ {
+ try
+ {
+ log.update( o, true );
+ updateCount++;
+ server.updatePerformed( updateCount );
+ }
+ catch( IOException e )
+ {
+ // $$$ should probably be propagating this exception
+ logger.log( Level.WARNING, "IOException while updating log", e );
+ }
+ }
+ }
+
+ /**
+ * Generate a snapshot, will perform the necessary locking to ensure no
+ * threads are mutating the state of the server before creating the
+ * snapshot.
+ *
+ * @throws IOException
+ * @see ReliableLog#snapshot
+ */
+ void snapshot() throws IOException
+ {
+ if( log == null )
+ {
+ return;
+ }
+ try
+ {
+ // Using write lock because we want an exclusive lock
+ mutatorLock.writeLock();
+ updateCount = 0;
+
+ // Don't need to sync on this because
+ // mutatorLock.writeLock() gives us an exclusive lock
+ log.snapshot();
+ }
+ finally
+ {
+ // Using write lock because we want an exclusive lock
+ mutatorLock.writeUnlock();
+ }
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/ProxyVerifier.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/ProxyVerifier.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/ProxyVerifier.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/ProxyVerifier.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,145 @@
+/*
+ * 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.norm;
+
+import com.sun.jini.landlord.ConstrainableLandlordLease;
+import com.sun.jini.landlord.Landlord;
+import com.sun.jini.landlord.LandlordProxyVerifier;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import net.jini.core.constraint.MethodConstraints;
+import net.jini.core.constraint.RemoteMethodControl;
+import net.jini.export.proxytrust.TrustEquivalence;
+import net.jini.id.Uuid;
+import net.jini.security.TrustVerifier;
+
+/**
+ * Defines a trust verifier for the smart proxies of a Norm server.
+ */
+final class ProxyVerifier implements Serializable, TrustVerifier
+{
+ private static final long serialVersionUID = 2;
+
+ /**
+ * The Norm server proxy.
+ *
+ * @serial
+ */
+ private final RemoteMethodControl serverProxy;
+
+ /**
+ * The unique ID for the Norm server.
+ *
+ * @serial
+ */
+ private final Uuid serverUuid;
+
+ /**
+ * Returns a verifier for the smart proxies of a Norm server with the
+ * specified proxy and unique ID.
+ *
+ * @param serverProxy the Norm server proxy
+ * @param serverUuid the unique ID for the Norm server
+ * @throws UnsupportedOperationException if <code>serverProxy</code> does
+ * not implement both {@link RemoteMethodControl} and {@link
+ * TrustEquivalence}
+ */
+ ProxyVerifier( NormServer serverProxy, Uuid serverUuid )
+ {
+ if( !( serverProxy instanceof RemoteMethodControl ) )
+ {
+ throw new UnsupportedOperationException(
+ "Verifier requires service proxy to implement " +
+ "RemoteMethodControl" );
+ }
+ else if( !( serverProxy instanceof TrustEquivalence ) )
+ {
+ throw new UnsupportedOperationException(
+ "Verifier requires service proxy to implement " +
+ "TrustEquivalence" );
+ }
+ this.serverProxy = (RemoteMethodControl) serverProxy;
+ this.serverUuid = serverUuid;
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean isTrustedObject( Object obj, TrustVerifier.Context ctx )
+ throws RemoteException
+ {
+ if( obj == null || ctx == null )
+ {
+ throw new NullPointerException( "Arguments must not be null" );
+ }
+ else if( obj instanceof ConstrainableLandlordLease )
+ {
+ return new LandlordProxyVerifier(
+ (Landlord) serverProxy, serverUuid ).isTrustedObject( obj, ctx );
+ }
+ RemoteMethodControl otherServerProxy;
+ if( obj instanceof SetProxy.ConstrainableSetProxy )
+ {
+ if( !isTrustedObject( ( (SetProxy) obj ).getRenewalSetLease(), ctx ) )
+ {
+ return false;
+ }
+ otherServerProxy =
+ (RemoteMethodControl) ( (AbstractProxy) obj ).server;
+ }
+ else if( obj instanceof AdminProxy.ConstrainableAdminProxy ||
+ obj instanceof NormProxy.ConstrainableNormProxy )
+ {
+ if( !serverUuid.equals( ( (AbstractProxy) obj ).uuid ) )
+ {
+ return false;
+ }
+ otherServerProxy =
+ (RemoteMethodControl) ( (AbstractProxy) obj ).server;
+ }
+ else if( obj instanceof RemoteMethodControl )
+ {
+ otherServerProxy = (RemoteMethodControl) obj;
+ }
+ else
+ {
+ return false;
+ }
+ MethodConstraints mc = otherServerProxy.getConstraints();
+ TrustEquivalence trusted =
+ (TrustEquivalence) serverProxy.setConstraints( mc );
+ return trusted.checkTrustEquivalence( otherServerProxy );
+ }
+
+ /**
+ * Require server proxy to implement TrustEquivalence.
+ */
+ private void readObject( ObjectInputStream in )
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ if( !( serverProxy instanceof TrustEquivalence ) )
+ {
+ throw new InvalidObjectException(
+ "serverProxy must implement TrustEquivalence" );
+ }
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/Queue.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/Queue.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/Queue.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/Queue.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,60 @@
+/*
+ * 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.norm;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Simple thread-safe FIFO sequence.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+class Queue
+{
+ /**
+ * List we actually store stuff in
+ */
+ final private List lst = Collections.synchronizedList( new LinkedList() );
+
+ /**
+ * Enqueue an item.
+ */
+ synchronized void enqueue( Object o )
+ {
+ lst.add( o );
+ notifyAll();
+ }
+
+ /**
+ * Block until the queue is non-empty and return the first item.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * while the queue is waiting for an item to appear
+ */
+ synchronized Object dequeue() throws InterruptedException
+ {
+ while( lst.isEmpty() )
+ {
+ wait();
+ }
+
+ return lst.remove( 0 );
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/SetProxy.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/SetProxy.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/SetProxy.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/SetProxy.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,541 @@
+/*
+ * 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.norm;
+
+import com.sun.jini.landlord.ConstrainableLandlordLease;
+import com.sun.jini.proxy.ConstrainableProxyUtil;
+import com.sun.jini.proxy.ThrowThis;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.rmi.MarshalledObject;
+import java.rmi.RemoteException;
+import java.util.LinkedList;
+import java.util.List;
+import net.jini.core.constraint.MethodConstraints;
+import net.jini.core.constraint.RemoteMethodControl;
+import net.jini.core.event.EventRegistration;
+import net.jini.core.event.RemoteEventListener;
+import net.jini.core.lease.Lease;
+import net.jini.export.proxytrust.ProxyTrustIterator;
+import net.jini.export.proxytrust.SingletonProxyTrustIterator;
+import net.jini.id.Uuid;
+import net.jini.io.MarshalledInstance;
+import net.jini.lease.LeaseRenewalSet;
+import net.jini.lease.LeaseUnmarshalException;
+
+/**
+ * Client side proxy for Norm's lease renewal sets. Uses an object of
+ * type NormServer to communicate back to server.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+class SetProxy extends AbstractProxy implements LeaseRenewalSet
+{
+ private static final long serialVersionUID = 2;
+
+ /**
+ * Lease for this set.
+ *
+ * @serial
+ */
+ final Lease ourLease;
+
+ /**
+ * Creates a lease set proxy, returning an instance that implements
+ * RemoteMethodControl if the server does.
+ *
+ * @param server the server proxy
+ * @param id the ID of the lease set
+ * @param lease the lease set's lease
+ */
+ static SetProxy create( NormServer server, Uuid id, Lease lease )
+ {
+ if( server instanceof RemoteMethodControl )
+ {
+ return new ConstrainableSetProxy( server, id, lease, null );
+ }
+ else
+ {
+ return new SetProxy( server, id, lease );
+ }
+ }
+
+ /**
+ * Simple constructor.
+ */
+ private SetProxy( NormServer server, Uuid id, Lease lease )
+ {
+ super( server, id );
+ if( lease == null )
+ {
+ throw new NullPointerException( "lease cannot be null" );
+ }
+ ourLease = lease;
+ }
+
+ /**
+ * Require fields to be non-null.
+ */
+ private void readObjectNoData() throws InvalidObjectException
+ {
+ throw new InvalidObjectException(
+ "server, uuid, and ourLease must be non-null" );
+ }
+
+ /**
+ * Require lease to be non-null.
+ */
+ private void readObject( ObjectInputStream in )
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ if( ourLease == null )
+ {
+ throw new InvalidObjectException( "ourLease cannot be null" );
+ }
+ }
+
+ /* -- Implement LeaseRenewalSet -- */
+
+ // Inherit java doc from super type
+
+ public void renewFor( Lease leaseToRenew, long membershipDuration )
+ throws RemoteException
+ {
+ try
+ {
+ server2().renewFor( uuid, leaseToRenew, membershipDuration,
+ Lease.FOREVER );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ }
+ }
+
+ // Inherit java doc from super type
+ public void renewFor( Lease leaseToRenew, long membershipDuration,
+ long renewDuration )
+ throws RemoteException
+ {
+ try
+ {
+ server.renewFor( uuid, leaseToRenew, membershipDuration,
+ renewDuration );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ }
+ }
+
+ // Inherit java doc from super type
+ public Lease remove( Lease leaseToRemove ) throws RemoteException
+ {
+ try
+ {
+ return server.remove( uuid, leaseToRemove );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ // Need this because compiler does not know that
+ // throwRemoteException is not going to return
+ return null;
+ }
+ }
+
+ // Inherit java doc from super type
+ public Lease[] getLeases() throws LeaseUnmarshalException, RemoteException
+ {
+ try
+ {
+ GetLeasesResult result = server.getLeases( uuid );
+ MarshalledInstance mls[] = result.marshalledLeases;
+
+ if( mls == null || mls.length == 0 )
+ {
+ return new Lease[0];
+ }
+
+ final List leases = new LinkedList();
+ final List problems = new LinkedList();
+ final List exceptions = new LinkedList();
+ for( int i = 0; i < mls.length; i++ )
+ {
+ Lease l;
+ final MarshalledInstance ml = mls[ i ];
+ try
+ {
+ l = (Lease) ml.get( result.verifyCodebaseIntegrity() );
+ leases.add( l );
+ }
+ catch( Throwable t )
+ {
+ problems.add( ml.convertToMarshalledObject() );
+ exceptions.add( t );
+ }
+ }
+
+ final Lease[] rslt =
+ (Lease[]) leases.toArray( new Lease[leases.size()] );
+
+ if( problems.isEmpty() )
+ {
+ return rslt;
+ }
+
+ final MarshalledObject sml[] =
+ (MarshalledObject[]) problems.toArray(
+ new MarshalledObject[problems.size()] );
+ final Throwable es[] =
+ (Throwable[]) exceptions.toArray(
+ new Throwable[exceptions.size()] );
+
+ throw new LeaseUnmarshalException( "Problem unmarshalling lease(s)",
+ rslt, sml, es );
+
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ // Need this because compiler does not know that
+ // throwRemoteException is not going to return
+ return null;
+ }
+ }
+
+ // Inherit java doc from super type
+ public EventRegistration setExpirationWarningListener(
+ RemoteEventListener listener,
+ long minWarning,
+ MarshalledObject handback )
+ throws RemoteException
+ {
+ // Do some client side error checking
+ if( listener == null )
+ {
+ throw new NullPointerException(
+ "LeaseRenewalSet.setExpirationWarningListener:Must " +
+ "pass a non-null listener" );
+ }
+
+ try
+ {
+ return server.setExpirationWarningListener( uuid,
+ listener, minWarning, handback );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ // Need this because compiler does not know that
+ // throwRemoteException is not going to return
+ return null;
+ }
+ }
+
+ // Inherit java doc from super type
+ public void clearExpirationWarningListener() throws RemoteException
+ {
+ try
+ {
+ server2().setExpirationWarningListener(
+ uuid, null, NormServer.NO_LISTENER, null );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ }
+ }
+
+ // Inherit java doc from super type
+ public EventRegistration setRenewalFailureListener(
+ RemoteEventListener listener,
+ MarshalledObject handback )
+ throws RemoteException
+ {
+ // Do some client side error checking
+ if( listener == null )
+ {
+ throw new NullPointerException(
+ "LeaseRenewalSet.setRenewalFailureListener:Must " +
+ "pass a non-null listener" );
+ }
+
+ try
+ {
+ return server.setRenewalFailureListener( uuid, listener, handback );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ // Need this because compiler does not know that
+ // throwRemoteException is not going to return
+ return null;
+ }
+ }
+
+
+ // Inherit java doc from super type
+ public void clearRenewalFailureListener() throws RemoteException
+ {
+ try
+ {
+ server2().setRenewalFailureListener( uuid, null, null );
+ }
+ catch( ThrowThis e )
+ {
+ // The server wants to throw some remote exception
+ e.throwRemoteException();
+ }
+ }
+
+ /**
+ * Returns a second server proxy for use by methods that represent a second
+ * client-side method for a single server-side method. The distinction
+ * only matters for the constrainable subclass, where the different server
+ * proxies need different client constraints.
+ */
+ NormServer server2()
+ {
+ return server;
+ }
+
+ // Inherit java doc from super type
+ public Lease getRenewalSetLease()
+ {
+ return ourLease;
+ }
+
+ /**
+ * Defines a subclass of SetProxy that implements RemoteMethodControl.
+ */
+ static final class ConstrainableSetProxy extends SetProxy
+ implements RemoteMethodControl
+ {
+ private static final long serialVersionUID = 1;
+
+ /**
+ * Mappings from client to server methods, using the client method with
+ * more arguments for each server method when more than one client
+ * method maps to a single server method.
+ */
+ private static final Method[] methodMap1;
+
+ static
+ {
+ try
+ {
+ methodMap1 = new Method[]{
+ LeaseRenewalSet.class.getMethod(
+ "renewFor",
+ new Class[]{ Lease.class, long.class, long.class } ),
+ NormServer.class.getMethod(
+ "renewFor",
+ new Class[]{ Uuid.class, Lease.class, long.class,
+ long.class } ),
+ LeaseRenewalSet.class.getMethod(
+ "remove", new Class[]{ Lease.class } ),
+ NormServer.class.getMethod(
+ "remove",
+ new Class[]{ Uuid.class, Lease.class } ),
+ LeaseRenewalSet.class.getMethod(
+ "getLeases", new Class[]{ } ),
+ NormServer.class.getMethod(
+ "getLeases", new Class[]{ Uuid.class } ),
+ LeaseRenewalSet.class.getMethod(
+ "setExpirationWarningListener",
+ new Class[]{ RemoteEventListener.class,
+ long.class, MarshalledObject.class } ),
+ NormServer.class.getMethod(
+ "setExpirationWarningListener",
+ new Class[]{ Uuid.class, RemoteEventListener.class,
+ long.class, MarshalledObject.class } ),
+ LeaseRenewalSet.class.getMethod(
+ "setRenewalFailureListener",
+ new Class[]{ RemoteEventListener.class,
+ MarshalledObject.class } ),
+ NormServer.class.getMethod(
+ "setRenewalFailureListener",
+ new Class[]{ Uuid.class, RemoteEventListener.class,
+ MarshalledObject.class } )
+ };
+ }
+ catch( NoSuchMethodException e )
+ {
+ throw new NoSuchMethodError( e.getMessage() );
+ }
+ }
+
+ /**
+ * Second set of mappings from client to server method names, for
+ * server methods with a second associated client method.
+ */
+ private static final Method[] methodMap2;
+
+ static
+ {
+ try
+ {
+ methodMap2 = new Method[]{
+ LeaseRenewalSet.class.getMethod(
+ "renewFor",
+ new Class[]{ Lease.class, long.class } ),
+ NormServer.class.getMethod(
+ "renewFor",
+ new Class[]{ Uuid.class, Lease.class, long.class,
+ long.class } ),
+ LeaseRenewalSet.class.getMethod(
+ "clearExpirationWarningListener", new Class[]{ } ),
+ NormServer.class.getMethod(
+ "setExpirationWarningListener",
+ new Class[]{ Uuid.class, RemoteEventListener.class,
+ long.class, MarshalledObject.class } ),
+ LeaseRenewalSet.class.getMethod(
+ "clearRenewalFailureListener", new Class[]{ } ),
+ NormServer.class.getMethod(
+ "setRenewalFailureListener",
+ new Class[]{ Uuid.class, RemoteEventListener.class,
+ MarshalledObject.class } )
+ };
+ }
+ catch( NoSuchMethodException e )
+ {
+ throw new NoSuchMethodError( e.getMessage() );
+ }
+ }
+
+ /**
+ * The client constraints placed on this proxy or <code>null</code>.
+ *
+ * @serial
+ */
+ private MethodConstraints methodConstraints;
+
+ /**
+ * A second inner proxy to use when the client constraints for
+ * different smart proxy methods implemented by the same inner proxy
+ * methods have different constraints. This proxy is used for the
+ * renewFor(Lease, long), clearExpirationWarningListener, and
+ * clearRenewalFailureListener methods.
+ */
+ private transient NormServer server2;
+
+ /**
+ * Creates an instance of this class.
+ */
+ ConstrainableSetProxy( NormServer server,
+ Uuid id,
+ Lease lease,
+ MethodConstraints methodConstraints )
+ {
+ super( constrainServer( server, methodConstraints, methodMap1 ),
+ id, lease );
+ if( !( lease instanceof ConstrainableLandlordLease ) )
+ {
+ throw new IllegalArgumentException(
+ "lease must be a ConstrainableLandlordLease" );
+ }
+ this.methodConstraints = methodConstraints;
+ server2 = constrainServer( server, methodConstraints, methodMap2 );
+ }
+
+ /**
+ * Verifies that ourLease is a ConstrainableLandlordLease, and that
+ * server implements RemoteMethodControl and has the appropriate method
+ * constraints. Also sets the server2 field.
+ */
+ private void readObject( ObjectInputStream s )
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ if( !( server instanceof RemoteMethodControl ) )
+ {
+ throw new InvalidObjectException(
+ "server does not implement RemoteMethodControl" );
+ }
+ else if( !( ourLease instanceof ConstrainableLandlordLease ) )
+ {
+ throw new InvalidObjectException(
+ "ourLease is not a ConstrainableLandlordLease" );
+ }
+ ConstrainableProxyUtil.verifyConsistentConstraints(
+ methodConstraints, server, methodMap1 );
+ server2 = constrainServer( server, methodConstraints, methodMap2 );
+ }
+
+
+ /**
+ * Returns a copy of the server proxy with the specified client
+ * constraints and methods mapping.
+ */
+ private static NormServer constrainServer(
+ NormServer server,
+ MethodConstraints methodConstraints,
+ Method[] mappings )
+ {
+ return (NormServer) ( (RemoteMethodControl) server ).setConstraints(
+ ConstrainableProxyUtil.translateConstraints(
+ methodConstraints, mappings ) );
+ }
+
+ /**
+ * inherit javadoc
+ */
+ public RemoteMethodControl setConstraints(
+ MethodConstraints constraints )
+ {
+ return new ConstrainableSetProxy(
+ server, uuid, ourLease, constraints );
+ }
+
+ /**
+ * inherit javadoc
+ */
+ public MethodConstraints getConstraints()
+ {
+ return methodConstraints;
+ }
+
+ /**
+ * Returns the second server proxy.
+ */
+ NormServer server2()
+ {
+ return server2;
+ }
+
+ /**
+ * Returns a proxy trust iterator that supplies the server, for use by
+ * ProxyTrustVerifier.
+ */
+ private ProxyTrustIterator getProxyTrustIterator()
+ {
+ return new SingletonProxyTrustIterator(server);
+ }
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/StoreException.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/StoreException.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/StoreException.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/StoreException.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,102 @@
+/*
+ * 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.norm;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Base class for exceptions thrown by PersistantStore.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+class StoreException extends Exception
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The exception (if any) that triggered the store exception. This
+ * may be <code>null</code>.
+ *
+ * @serial
+ */
+ final Throwable nestedException;
+
+ /**
+ * Create a store exception, forwarding a string to the superclass
+ * constructor.
+ *
+ * @param str a detailed message for the exception
+ */
+ StoreException( String str )
+ {
+ super( str );
+ nestedException = null;
+ }
+
+ /**
+ * Create an exception, forwarding a string to the
+ * superclass constructor.
+ *
+ * @param str a detailed message for the exception
+ * @param ex root cause for the exception, may be <code>null</code>
+ */
+ StoreException( String str, Throwable ex )
+ {
+ super( str );
+ nestedException = ex;
+ }
+
+ /**
+ * Print the stack trace of this exception, plus that of the nested
+ * exception, if any.
+ */
+ public void printStackTrace()
+ {
+ printStackTrace( System.err );
+ }
+
+ /**
+ * Print the stack trace of this exception, plus that of the nested
+ * exception, if any.
+ */
+ public void printStackTrace( PrintStream out )
+ {
+ super.printStackTrace( out );
+ if( nestedException != null )
+ {
+ out.println( "nested exception:" );
+ nestedException.printStackTrace( out );
+ }
+ }
+
+ /**
+ * Print the stack trace of this exception, plus that of the nested
+ * exception, if any.
+ */
+ public void printStackTrace( PrintWriter out )
+ {
+ super.printStackTrace( out );
+ if( nestedException != null )
+ {
+ out.println( "nested exception:" );
+ nestedException.printStackTrace( out );
+ }
+ }
+}
+
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/TransientNormServerImpl.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/TransientNormServerImpl.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/TransientNormServerImpl.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/TransientNormServerImpl.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,48 @@
+/*
+ * 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.norm;
+
+import com.sun.jini.start.LifeCycle;
+import com.sun.jini.start.ServiceStarter;
+
+/**
+ * Provides a transient implementation of NormServer.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+class TransientNormServerImpl extends NormServerBaseImpl
+{
+
+ /**
+ * Provides a constructor for a transient implementation of NormServer
+ * suitable for use with {@link ServiceStarter}.
+ *
+ * @param configOptions the arguments to use when creating the
+ * configuration for the server
+ * @param lifeCycle object to notify when this service is destroyed, or
+ * <code>null</code>
+ * @throws Exception if there is a problem creating the server
+ */
+ TransientNormServerImpl( String[] configOptions, LifeCycle lifeCycle )
+ throws Exception
+ {
+ super( false /* persistent */ );
+ init( configOptions, lifeCycle );
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/UIDGenerator.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/UIDGenerator.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/UIDGenerator.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/UIDGenerator.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,54 @@
+/*
+ * 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.norm;
+
+/**
+ * Utility class for generating locally unique IDs.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+class UIDGenerator
+{
+ /**
+ * Value of the next ID
+ */
+ private long nextID = 0;
+
+ /**
+ * Generate ID, this method performs appropriate locking to
+ * ensure the returned ID is unique.
+ */
+ synchronized long newID()
+ {
+ return nextID++;
+ }
+
+ /**
+ * Used during log recovery to update the generator that a given ID
+ * is in use. This method performs no locking.
+ *
+ * @param ID ID that is in use
+ */
+ void inUse( long ID )
+ {
+ if( ID >= nextID )
+ {
+ nextID = ID + 1;
+ }
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/build.xml
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/build.xml?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/build.xml (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/build.xml Tue Dec 9 21:11:39 2008
@@ -0,0 +1,258 @@
+<!--
+ ! 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.
+ !-->
+
+<project name="norm" basedir="." default="all">
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## ENVIRONMENT SETTINGS -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <property name="top" location="../../../../.."/>
+
+ <property name="pkg-path" value="com/sun/jini/${ant.project.name}"/>
+
+ <!-- ## -->
+ <!-- ## Set java-source for use with the javac task: -->
+ <!-- ## -->
+
+ <property name="java-source" value="${pkg-path}/**/*.java"/>
+
+ <import file="${top}/build_common.xml"/>
+
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## TARGET: all -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <target name="all"
+ description=""
+ depends="compile,
+ this.stubs">
+
+ </target>
+
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## TARGET: clean -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <target name="clean"
+ description="Removes all files and dirs created by the build."
+ depends="clean.jre.ext">
+
+ <delete dir="${build.classes}/${pkg-path}" quiet="true"/>
+
+ </target>
+
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## TARGET: this.jars -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <target name="this.jars"
+ description=""
+ depends="norm.jar,
+ norm-dl.jar">
+
+ </target>
+
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## TARGET: norm.jar -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <target name="norm.jar"
+ depends="tools">
+
+ <property name="norm.deps" location="${build.deps}/norm.deps"/>
+
+ <!-- ## -->
+ <!-- ## Run ClassDep. -->
+ <!-- ## -->
+
+ <java classname="com.sun.jini.tool.ClassDep"
+ failonerror="true"
+ output="${norm.deps}">
+
+ <classpath refid="path.classdep"/>
+ <arg value="-cp"/>
+ <arg path="${build.classes}"/>
+ <arg value="-files"/>
+ <arg line="${jskprivate.include}"/>
+
+ <arg line="-in com.sun.jini.norm"/>
+
+ <arg value="com.sun.jini.norm.ActivatableNormServerImpl"/>
+ <arg value="com.sun.jini.norm.NormPermission"/>
+ <arg value="com.sun.jini.norm.NormServerBaseImpl_Stub"/>
+ <arg value="com.sun.jini.norm.PersistentNormServerImpl"/>
+ <arg value="com.sun.jini.norm.TransientNormServerImpl"/>
+ <arg value="com.sun.jini.reliableLog.LogException"/>
+
+ </java>
+
+ <!-- ## -->
+ <!-- ## Generate the jar file. -->
+ <!-- ## -->
+
+ <delete file="${build.lib}/norm.jar" quiet="true"/>
+
+ <jar destfile="${build.lib}/norm.jar"
+ index="false"
+ manifest="${src.jini.manifest}/norm.mf">
+
+ <fileset dir="${build.classes}" includesfile="${norm.deps}"/>
+
+ </jar>
+
+ <!-- ## -->
+ <!-- ## Generate the Preferred List -->
+ <!-- ## -->
+
+ <preferredlistgen>
+
+ <plg-elements>
+
+ <arg line="-cp"/>
+ <arg path="${build.classes}"/>
+
+ <arg line="-jar"/>
+ <arg path="${build.lib}/norm.jar"/>
+
+ <arg line="-default true"/>
+
+ </plg-elements>
+
+ </preferredlistgen>
+
+ </target>
+
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## TARGET: norm-dl.jar -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <target name="norm-dl.jar"
+ depends="tools">
+
+
+ <property name="norm-dl.deps" location="${build.deps}/norm-dl.deps"/>
+
+ <!-- ## -->
+ <!-- ## Run ClassDep. -->
+ <!-- ## -->
+
+ <java classname="com.sun.jini.tool.ClassDep"
+ failonerror="true"
+ output="${norm-dl.deps}">
+
+ <classpath refid="path.classdep"/>
+ <arg value="-cp"/>
+ <arg path="${build.classes}"/>
+ <arg value="-files"/>
+ <arg line="${jskprivate.include}"/>
+
+ <arg line="-in com.sun.jini.norm"/>
+
+ <arg value="com.sun.jini.lease.BasicRenewalFailureEvent"/>
+ <arg value="com.sun.jini.lookup.entry.BasicServiceType"/>
+ <arg value="com.sun.jini.norm.CorruptedStoreException"/>
+ <arg value="com.sun.jini.norm.InternalNormException"/>
+ <arg value="com.sun.jini.norm.NormPermission"/>
+ <arg value="com.sun.jini.norm.NormServerBaseImpl_Stub"/>
+ <arg value="com.sun.jini.norm.ProxyVerifier"/>
+ <arg value="com.sun.jini.reliableLog.LogException"/>
+ <arg value="com.sun.jini.start.ServiceProxyAccessor"/>
+ <arg value="net.jini.lookup.entry.ServiceInfo"/>
+
+ </java>
+
+ <!-- ## -->
+ <!-- ## Generate the jar file. -->
+ <!-- ## -->
+
+ <delete file="${build.lib-dl}/norm-dl.jar" quiet="true"/>
+
+ <jar destfile="${build.lib-dl}/norm-dl.jar" index="false">
+
+ <fileset dir="${build.classes}" includesfile="${norm-dl.deps}"/>
+
+ </jar>
+
+ <!-- ## -->
+ <!-- ## Generate the Preferred List -->
+ <!-- ## -->
+
+ <preferredlistgen>
+
+ <plg-elements>
+
+ <arg line="-cp"/>
+ <arg path="${build.lib}/jsk-platform.jar"/>
+
+ <arg line="-jar"/>
+ <arg path="${build.lib-dl}/norm-dl.jar"/>
+
+ <arg line="-jar"/>
+ <arg path="${build.lib-dl}/jsk-dl.jar"/>
+
+ <arg line="-proxy com.sun.jini.norm.AbstractProxy"/>
+ <arg line="-proxy com.sun.jini.norm.AdminProxy"/>
+ <arg line="-proxy com.sun.jini.norm.NormProxy"/>
+ <arg line="-proxy com.sun.jini.norm.SetProxy"/>
+
+ </plg-elements>
+
+ </preferredlistgen>
+
+ </target>
+
+
+ <!-- ################################################################ -->
+ <!-- ## -->
+ <!-- ## TARGET: this.stubs -->
+ <!-- ## -->
+ <!-- ################################################################ -->
+
+ <target name="this.stubs"
+ description="Builds the RMI stubs for ${ant.project.name}."
+ depends="compile">
+
+ <rmic base="${build.classes}" stubversion="1.2">
+
+ <classpath refid="path.jini"/>
+ <include name="com/sun/jini/norm/NormServerBaseImpl.class"/>
+
+ </rmic>
+
+ </target>
+
+</project>
+
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventFactory.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventFactory.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventFactory.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventFactory.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,57 @@
+/*
+ * 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.norm.event;
+
+import java.rmi.MarshalledObject;
+import net.jini.core.event.RemoteEvent;
+
+/**
+ * Factory interface for creating
+ * <code>net.jini.core.event.RemoteEvent</code>. An object of this
+ * type is passed to each call of <code>EventType.sendEvent</code> and
+ * is used by the <code>EventType</code> object to generate the
+ * concrete <code>RemoteEvent</code> associated with a given event
+ * occurrence on demand. Providing a factory to <code>sendEvent</code>
+ * instead of an actual <code>RemoteEvent</code> object allows
+ * <code>eventType</code> object to send an event originally
+ * intended for one listener to another.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see EventType
+ * @see EventType#sendEvent
+ */
+public interface EventFactory
+{
+ /**
+ * Create the concrete <code>RemoteEvent</code> for the associated
+ * event occurrence. Implementations should allow for the
+ * possibility of being called with the same argument more that
+ * once, especially the same eventID and seqNum. The factory
+ * should not mutate the event after it returns it.
+ * <p>
+ * The caller will own no locks when calling this method.
+ *
+ * @param eventID the event ID the new event should have
+ * @param seqNum the sequence number the new event object should have
+ * @param handback the handback the new event object should have
+ * @return the new event object
+ */
+ public RemoteEvent createEvent( long eventID,
+ long seqNum,
+ MarshalledObject handback );
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventType.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventType.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventType.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventType.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,575 @@
+/*
+ * 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.norm.event;
+
+import com.sun.jini.constants.ThrowableConstants;
+import com.sun.jini.logging.Levels;
+import com.sun.jini.thread.RetryTask;
+import com.sun.jini.thread.TaskManager;
+import com.sun.jini.thread.WakeupManager;
+import java.io.IOException;
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+import java.rmi.RemoteException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.core.event.RemoteEvent;
+import net.jini.core.event.RemoteEventListener;
+import net.jini.security.ProxyPreparer;
+
+/**
+ * Representation of an event type the supports a single registrant.
+ * The registrant, event ID, and event sequence number information
+ * portions of this object are preserved when serialized. The send
+ * monitor, and currently scheduled event sends are not.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+// $$$ I am not sure if this class does too much locking, or too little.
+// It does too little in that it does not do any locking during serialization
+// It does too much in that Norm's current locking discipline means that for
+// the most part this class does not have to worry about multiple threads
+// of control entering at one time.
+// Before we make this a general utility we have to re-think the locking
+// strategy.
+public class EventType implements Serializable
+{
+ private static final long serialVersionUID = 2;
+
+ /**
+ * Logger for logging messages for this class
+ */
+ private static final Logger logger = Logger.getLogger( "com.sun.jini.norm" );
+
+ /**
+ * Listener registered for events of this type. Stored in
+ * marshalled form so object the <code>EventType</code> object can
+ * be recovered even if the listener's codebase is not available.
+ * If this field is <code>null</code>, <code>listener</code> and
+ * <code>handback</code> will be also.
+ *
+ * @serial
+ */
+ private MarshalledObject marshalledListener;
+
+ /**
+ * Transient cache of listener in unmarshalled form
+ */
+ private transient RemoteEventListener listener;
+
+ /**
+ * The proxy preparer to use to prepare a newly unmarshalled listener, or
+ * null if this instance was created using an already prepared listener,
+ * which is how instances are created initially.
+ */
+ private transient ProxyPreparer recoveredListenerPreparer;
+
+ /**
+ * Handback object associated with current listener.
+ *
+ * @serial
+ */
+ private MarshalledObject handback;
+
+ /**
+ * Sequence number of the current listener/handback pair, incremented
+ * every time a new listener is set (even if the objects
+ * are equivalent)
+ *
+ * @serial
+ */
+ private long registrationNumber;
+
+ /**
+ * Last event sequence number we used
+ *
+ * @serial
+ */
+ private long lastSeqNum;
+
+ /**
+ * Our event ID
+ *
+ * @serial
+ */
+ private long evID;
+
+ /**
+ * Object we check with to ensure leases have not expired and notify
+ * when we get a definite exception during an event send attempt.
+ * If this field is <code>null</code> generator will be also.
+ */
+ private transient SendMonitor monitor;
+
+ /**
+ * Event type generator that created us. If this field is
+ * <code>null</code> monitor will be also.
+ */
+ private transient EventTypeGenerator generator;
+
+ /**
+ * Simple constructor. Initially the last sequence number is set to 0.
+ *
+ * @param generator EventTypeGenerator that is creating this event type
+ * @param monitor Object which is to monitor the sending of events
+ * of this type
+ * @param evID event ID of this event type
+ * @param listener the listener events of this type should go to
+ * @param handback the object that should be passed to listener
+ * as part of the event
+ * @throws IOException if the listener cannot be serialized
+ */
+ EventType( EventTypeGenerator generator, SendMonitor monitor, long evID,
+ RemoteEventListener listener, MarshalledObject handback )
+ throws IOException
+ {
+ if( generator == null )
+ {
+ throw new NullPointerException( "EventType(): Must create event " +
+ "type objects with a non-null generator" );
+ }
+
+ if( monitor == null )
+ {
+ throw new NullPointerException( "EventType(): Must create event " +
+ "type objects with a non-null monitor" );
+ }
+
+ this.generator = generator;
+ this.monitor = monitor;
+ this.evID = evID;
+ setLastSequenceNumber( 0 );
+ setListener( listener, handback );
+ }
+
+ /**
+ * Utility method to null out listener
+ */
+ private void clearListener()
+ {
+ listener = null;
+ handback = null;
+ marshalledListener = null;
+ }
+
+ /**
+ * (Re)set the listener for this type of event. Any pending
+ * events that have not yet been sent will be sent to the new
+ * listener, passing the new handback. Setting the listener to
+ * <code>null</code> will cancel the sending of all pending
+ * events.
+ *
+ * @param listener the listener events of this type should go to
+ * @param handback the object that should be passed to listener
+ * as part of the event
+ * @throws IOException if listener cannot be serialized
+ */
+ public synchronized void setListener( RemoteEventListener listener,
+ MarshalledObject handback )
+ throws IOException
+ {
+ registrationNumber++;
+
+ if( listener == null )
+ {
+ clearListener();
+ }
+ else
+ {
+ marshalledListener = new MarshalledObject( listener );
+ this.listener = listener;
+ this.handback = handback;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if there is a listener registered for this
+ * event type.
+ */
+ public boolean haveListener()
+ {
+ return marshalledListener != null;
+ }
+
+ /**
+ * Convince method to get the listener.
+ *
+ * @return the listener, or <code>null</code> if the listener can't be
+ * unpacked or prepared, or there is no listener
+ */
+ private RemoteEventListener getListener()
+ {
+ if( !haveListener() )
+ {
+ return null;
+ }
+
+ if( listener != null )
+ {
+ return listener;
+ }
+
+ // There is a listener, but it is not unpacked yet, try to unpack
+ RemoteEventListener unpreparedListener = null;
+ try
+ {
+ unpreparedListener =
+ (RemoteEventListener) marshalledListener.get();
+ }
+ catch( IOException e )
+ {
+ logger.log( Levels.HANDLED,
+ "Problem unmarshalling listener -- will retry later",
+ e );
+ // $$$ is this really the right thing to do?
+ // we probably really have a corrupted marshalledListener here
+ }
+ catch( ClassNotFoundException e )
+ {
+ logger.log( Levels.HANDLED,
+ "Problem unmarshalling listener -- will retry later",
+ e );
+ }
+
+ if( unpreparedListener != null )
+ {
+ // Prepare the listener
+ try
+ {
+ listener = (RemoteEventListener)
+ recoveredListenerPreparer.prepareProxy( unpreparedListener );
+ }
+ catch( RemoteException e )
+ {
+ logger.log( Levels.HANDLED,
+ "Problem preparing listener -- will retry later",
+ e );
+ }
+ catch( SecurityException e )
+ {
+ logger.log( Levels.HANDLED,
+ "Problem preparing listener -- will retry later",
+ e );
+ }
+ }
+
+ return listener;
+ }
+
+ /**
+ * Atomically clear the current registration if its sequence
+ * number matches the passed in sequence number. If the
+ * replacement occurs it will have the same effect as calling
+ * <code>setListener(null, null)</code>.
+ * <p>
+ * Can be used by code that needs to remove event registrations in
+ * response to exceptions thrown during event delivery without
+ * risking clobbering new registrations.
+ *
+ * @param oldSequenceNumber sequence number of the
+ * registration that had a problem
+ * @return <code>true</code> if the state of the object was
+ * changed and <code>false</code> otherwise
+ * @see EventType#setListener
+ */
+ public synchronized boolean clearListenerIfSequenceMatch(
+ long oldSequenceNumber )
+ {
+ if( oldSequenceNumber == registrationNumber )
+ {
+ clearListener();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Set the object's notion of the last sequence number. The next event
+ * scheduled to be sent will have a sequence number one greater than
+ * the value past to this call.
+ * <p>
+ * Note: this method is not synchronized.
+ *
+ * @param seqNum value for the last sequence number
+ */
+ public void setLastSequenceNumber( long seqNum )
+ {
+ lastSeqNum = seqNum;
+ }
+
+ /**
+ * Return the sequence number of the last event that was scheduled
+ * to be sent. Intended primarily for creating
+ * <code>EventRegistration</code> objects and the like.
+ */
+ public synchronized long getLastSequenceNumber()
+ {
+ return lastSeqNum;
+ }
+
+ /**
+ * Return the <code>long</code> that was uniquely associated with this
+ * object when it was created.
+ */
+ public long getEventID()
+ {
+ return evID;
+ }
+
+ /**
+ * Schedule the sending of an event. This event will be sent to
+ * the currently registered listener. If the listener changes
+ * before the the event is successfully sent the event will be sent
+ * to the new listener. If the current listener is
+ * <code>null</code> this call will have no affect aside from
+ * incrementing the sequence number.
+ *
+ * @param factory an object that will be used to create the
+ * <code>Event</code> object when necessary
+ * @return the sequence number assigned to the event
+ * @throws IllegalStateException if this method is called
+ * after the object has be deserialized and before
+ * <code>restoreTransientState</code> has been called
+ * @see EventType#restoreTransientState
+ */
+ public synchronized long sendEvent( EventFactory factory )
+ {
+ if( generator == null )
+ {
+ // Have not had our state restored, complain
+ throw new IllegalStateException( "EventType.sendEvent:" +
+ "called before state was fully restored" );
+ }
+
+ // Even if there is no listener, an event has occurred, so
+ // increment the sequence number (note this a stronger
+ // guarantee that the Jini Distributed Event Specification,
+ // but one that is required by the LRS spec).
+ lastSeqNum++;
+
+ // If we don't have a listener we don't need do anything else
+ if( !haveListener() )
+ {
+ return lastSeqNum;
+ }
+
+ final TaskManager mgr = generator.getTaskManager();
+ final WakeupManager wMgr = generator.getWakeupManager();
+ mgr.add( new SendTask( mgr, wMgr, factory, lastSeqNum ) );
+
+ return lastSeqNum;
+ }
+
+ /**
+ * Increment the sequence number and return the result. This
+ * method is useful if an event occurs that needs to be noted
+ * but from some reason it is impossible to deliver the event.
+ *
+ * @return the new value for the sequence number
+ */
+ public synchronized long bumpSequenceNumber()
+ {
+ return ++lastSeqNum;
+ }
+
+ /**
+ * Restore the transient state of this object after recovering it
+ * from a serialization stream. None of the arguments can be
+ * <code>null</code>.
+ * <p>
+ * Note: this method is not synchronized.
+ *
+ * @param generator the <code>EventTypeGenerator</code> that was used
+ * to create this EventType object originally
+ * @param monitor the object that monitors the progress of events
+ * set by this object
+ * @param recoveredListenerPreparer the proxy preparer to use to prepare
+ * listeners recovered from persistent storage
+ */
+ public void restoreTransientState( EventTypeGenerator generator,
+ SendMonitor monitor,
+ ProxyPreparer recoveredListenerPreparer )
+ {
+ if( generator == null )
+ {
+ throw new NullPointerException( "EventType.restoreTransientState:" +
+ "Must call with a non-null generator" );
+ }
+ if( monitor == null )
+ {
+ throw new NullPointerException( "EventType.restoreTransientState:" +
+ "Must call with a non-null monitor" );
+ }
+ if( recoveredListenerPreparer == null )
+ {
+ throw new NullPointerException( "EventType.restoreTransientState:" +
+ "Must call with a non-null recoveredListenerPreparer" );
+ }
+ this.generator = generator;
+ this.monitor = monitor;
+ this.recoveredListenerPreparer = recoveredListenerPreparer;
+ generator.recoverEventID( evID );
+ }
+
+ /**
+ * Subclass of <code>RetryTask</code> used by <code>EventType</code>
+ * to send events.
+ */
+ private class SendTask extends RetryTask
+ {
+ /**
+ * Max time we are willing to let a send attempt to go on for
+ */
+ final static private long MAX_TIME = 1000 * 60 * 60 * 24; //~ 1 Day
+
+ /**
+ * Factory used to create the <code>RemoteEvent</code> to be sent
+ */
+ final private EventFactory eventFactory;
+
+ /**
+ * Sequence number the event should have
+ */
+ final private long seqNum;
+
+ /**
+ * Cached event
+ */
+ private RemoteEvent event;
+
+ /**
+ * Registration sequence number of the listener/handback pair
+ * event was built for
+ */
+ private long eventForRegistrationNumber = -1;
+
+ /**
+ * Simple constructor.
+ *
+ * @param taskManager <code>TaskManager</code> this task is to be
+ * put into
+ * @param eventFactory <code>EventFactory</code> that will be used
+ * to create the event to be sent
+ * @param seqNum the sequence number of the event
+ */
+ private SendTask( TaskManager taskManager, WakeupManager wakeupManager,
+ EventFactory eventFactory, long seqNum )
+ {
+ super( taskManager, wakeupManager );
+ this.eventFactory = eventFactory;
+ this.seqNum = seqNum;
+ }
+
+ // Inherit java doc from super type
+ public boolean tryOnce()
+ {
+ final long now = System.currentTimeMillis();
+ if( now - startTime() > MAX_TIME )
+ {
+ return true; // we have been trying too long, stop here
+ }
+
+ if( !EventType.this.monitor.isCurrent() )
+ {
+ return true; // lease gone, stop here
+ }
+
+ // Local copies of listener and handback so they won't
+ // be clobbered by setListener calls
+ RemoteEventListener listener;
+ MarshalledObject handback;
+ long registrationNumber;
+
+ synchronized( EventType.this )
+ {
+ if( !EventType.this.haveListener() )
+ {
+ return true; // No currently registered listener, stop here
+ }
+
+ listener = EventType.this.getListener();
+ if( listener == null )
+ {
+ return false; // There is a listener, but we can't unpack
+ // it -- schedule a retry later
+ }
+ handback = EventType.this.handback;
+ registrationNumber = EventType.this.registrationNumber;
+ }
+
+ // If the handback has changed we need to create a new
+ // event object (we approximate this test by checking the
+ // registrationNumber
+
+ if( event == null ||
+ eventForRegistrationNumber != registrationNumber )
+ {
+ event = eventFactory.createEvent( EventType.this.evID, seqNum,
+ handback );
+ eventForRegistrationNumber = registrationNumber;
+ }
+
+ // Try sending
+ try
+ {
+ listener.notify( event );
+ return true;
+ }
+ catch( Throwable t )
+ {
+ // Classify the exception using ThrowableConstants, if
+ // it is a bad object or uncategorized (which must be
+ // a UnknownEventException) drop the event
+ // registration, if it is a bad invocation mark the
+ // try is done (since re-sending this event won't work),
+ // but don't drop the registration. If indefinite return
+ // false so a retry will be scheduled.
+ final int cat = ThrowableConstants.retryable( t );
+ if( cat == ThrowableConstants.INDEFINITE )
+ {
+ logger.log( Levels.HANDLED,
+ "Problem sending event -- will retry later",
+ t );
+ return false;
+ }
+ else if( cat == ThrowableConstants.BAD_INVOCATION )
+ {
+ logger.log( Level.INFO, "Problem sending event", t );
+ return true;
+ }
+ else
+ {
+ EventType.this.monitor.definiteException( EventType.this,
+ event, registrationNumber, t );
+ logger.log( Level.INFO, "Problem sending event", t );
+ return true;
+ }
+ }
+
+ }
+
+ // Inherit java doc from super type
+ public boolean runAfter( List tasks, int size )
+ {
+ // We don't need to run these tasks in any particular order
+ return false;
+ }
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventTypeGenerator.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventTypeGenerator.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventTypeGenerator.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/EventTypeGenerator.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,161 @@
+/*
+ * 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.norm.event;
+
+import com.sun.jini.thread.TaskManager;
+import com.sun.jini.thread.WakeupManager;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * Factory class for <code>EventType</code> objects. All
+ * <code>EventType</code> objects created by the same generator (or
+ * associated with the same generator by a
+ * <code>EventType.restoreTransientState<code> call) will use the same
+ * thread pool to manage their event send threads.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see EventType
+ * @see EventType#restoreTransientState
+ */
+public class EventTypeGenerator implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Next event ID.
+ *
+ * @serial
+ */
+ private long nextEvID = 1;
+
+ /**
+ * Task manager used to send events
+ */
+ private transient TaskManager taskManager = new TaskManager();
+
+ /**
+ * Wakeup manager used by the event sending tasks to schedule
+ * retries.
+ */
+ private transient WakeupManager wakeupManager =
+ new WakeupManager( new WakeupManager.ThreadDesc( null, true ) );
+
+ /**
+ * Create a new <code>EventType</code> object. The event ID for
+ * this type will be generated by this call.
+ *
+ * @param monitor Object to callback when an event sending
+ * attempt fails with a definite exception and to
+ * ensure that the lease on the event is still current.
+ * May not be <code>null</code>.
+ * @return the new <code>EventType</code> object
+ * @throws IOException if listener cannot be serialized
+ */
+ public synchronized EventType newEventType( SendMonitor monitor )
+ throws IOException
+ {
+ EventType rslt = new EventType(
+ this, monitor, nextEvID, null, null );
+ // Do this afterward so we don't use up an ID if
+ // we can't create the new object
+ nextEvID++;
+ return rslt;
+ }
+
+ /**
+ * Create a new <code>EventType</code> object specify the
+ * event id it should have.
+ *
+ * @param eventID the event ID of this type
+ * @param monitor Object to callback when an event sending
+ * attempt fails with a definite exception and to
+ * ensure that the lease on the event is still current.
+ * May not be <code>null</code>.
+ * @return the new <code>EventType</code> object
+ * @throws IOException if listener cannot be serialized
+ */
+ public EventType newEventType( SendMonitor monitor, long eventID )
+ throws IOException
+ {
+ return new EventType( this, monitor, eventID, null, null );
+ }
+
+ /**
+ * Called by event types during transient state recovery to ensure
+ * the generator knows about there event ID.
+ * <p>
+ * Note: this method is not synchronized.
+ *
+ * @param evID event ID of recovered <code>EventType</code> object
+ */
+ void recoverEventID( long evID )
+ {
+ if( evID >= nextEvID )
+ {
+ nextEvID = evID + 1;
+ }
+ }
+
+ /**
+ * Return the task manager that <code>EventType</code> objects created
+ * by this generator should use to send their events.
+ */
+ TaskManager getTaskManager()
+ {
+ return taskManager;
+ }
+
+ /**
+ * Return the wakeup manager that <code>EventType</code> objects created
+ * by this generator should use to send their events.
+ */
+ WakeupManager getWakeupManager()
+ {
+ return wakeupManager;
+ }
+
+ /**
+ * Terminate any independent treads started by event types
+ * associated with this generator.
+ */
+ public void terminate()
+ {
+ taskManager.terminate();
+ wakeupManager.stop();
+ wakeupManager.cancelAll();
+ }
+
+ /**
+ * Override <code>readObject</code> to create a <code>TaskManager</code>
+ * and a <code>WakeupManager</code>.
+ *
+ * @see ObjectInputStream#defaultReadObject
+ */
+ private void readObject( ObjectInputStream in )
+ throws IOException, ClassNotFoundException
+ {
+ // fill in the object from the stream
+ in.defaultReadObject();
+
+ taskManager = new TaskManager();
+ wakeupManager =
+ new WakeupManager( new WakeupManager.ThreadDesc( null, true ) );
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/SendMonitor.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/SendMonitor.java?rev=724975&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/SendMonitor.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/norm/src/main/java/com/sun/jini/norm/event/SendMonitor.java Tue Dec 9 21:11:39 2008
@@ -0,0 +1,65 @@
+/*
+ * 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.norm.event;
+
+import net.jini.core.event.RemoteEvent;
+
+/**
+ * Object associated with an <code>EventType</code> so it can ensure
+ * that the lease on an event notification is still valid and notify
+ * the client when a exception occurs in the course of attempting to
+ * send an event.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see EventType
+ * @see EventTypeGenerator
+ */
+public interface SendMonitor
+{
+ /**
+ * Method called when an attempt to send the event associated with
+ * this object results in a definite exception
+ * (e.g. <code>java.rmi.NoSuchObjectException</code> or any other
+ * <code>Throwable</code> that is not a subclass of
+ * <code>java.rmi.RemoteException</code>.
+ * <p>
+ * The caller will own no locks when calling this method.
+ *
+ * @param type the object that generated the event
+ * @param ev the remote event that could not be sent
+ * @param registrationNumber of the event registration that
+ * generated the exception. This can be used
+ * to call <code>EventType.clearListenerIfSequenceMatch</code>
+ * ensure only the registration that cause the problem
+ * gets cleared.
+ * @param t the definite exception that caused us to give up
+ * sending the event
+ */
+ public void definiteException( EventType type,
+ RemoteEvent ev,
+ long registrationNumber,
+ Throwable t );
+
+ /**
+ * Should return <code>true</code> if the lease associated with this
+ * event is still valid and <code>false</code> otherwise.
+ * <p>
+ * The caller will own no locks when calling this method.
+ */
+ public boolean isCurrent();
+}