Modified: river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerLeaseMap.java URL: http://svn.apache.org/viewvc/river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerLeaseMap.java?rev=1879521&r1=1879520&r2=1879521&view=diff ============================================================================== --- river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerLeaseMap.java (original) +++ river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerLeaseMap.java Sun Jul 5 11:41:39 2020 @@ -1,417 +1,417 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.river.fiddler; - -import org.apache.river.proxy.ConstrainableProxyUtil; -import java.lang.reflect.Method; -import java.rmi.RemoteException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import net.jini.core.constraint.MethodConstraints; -import net.jini.core.constraint.RemoteMethodControl; -import net.jini.core.lease.Lease; -import net.jini.core.lease.LeaseMap; -import net.jini.core.lease.LeaseMapException; -import net.jini.id.Uuid; -import org.apache.river.lease.AbstractIDLeaseMap; - -/** - * When clients request a registration with the Fiddler implementation of - * the lookup discovery service, leases of type FiddlerLease are granted - * on those registrations. Under certain circumstances it may be desirable - * to collect multiple granted leases in a set which implements the - * <code>net.jini.core.lease.LeaseMap</code> interface. - * <p> - * This class is the implementation class of the <code>LeaseMap</code> - * interface that is employed by the Fiddler implementation of the lookup - * discovery service. When a client wishes to "batch" leases granted by - * that service, the are placed in an instance of this class. - * <p> - * Clients only see instances of this class via the <code>LeaseMap</code> - * interface. - * - * @author Sun Microsystems, Inc. - * - */ -class FiddlerLeaseMap extends AbstractIDLeaseMap<FiddlerLease> { - - /** - * The reference to the back-end server of the lookup discovery service - * - * @serial - */ - final Fiddler server; - /** - * The unique ID associated with the server referenced in this class - * (used to compare server references). - * - * @serial - */ - final Uuid serverID; - - /** - * Static factory method that creates and returns an instance of - * <code>FiddlerLeaseMap</code>. If the lease input to this method - * is and instance of <code>ConstrainableFiddlerLease</code>, then - * the object returned by this method will be an instance of - * <code>ConstrainableFiddlerLeaseMap</code>. - * - * Note that because of the way the <code>Lease</code> class for the - * associated service is implemented, together with the way the - * <code>canBatch</code> method of that class is implemented, if the - * <code>lease</code> object input to this method implements - * <code>ConstrainableFiddlerLease</code>, then the <code>server</code> - * object referenced in this class will implement - * <code>RemoteMethodControl</code> as well. - * - * @param lease reference to a lease to add to the map as a key value - * @param duration the duration of the corresponding lease. This value - * is the "mapped" value corresponding to the lease key. - * - * @return an instance of <code>FiddlerLeaseMap</code>, or an instance - * of <code>ConstrainableFiddlerLeaseMap</code> if the given - * <code>lease</code> is an instance of - * <code>ConstrainableFiddlerLease</code>. - */ - static FiddlerLeaseMap createLeaseMap(FiddlerLease lease, long duration) { - if(lease instanceof FiddlerLease.ConstrainableFiddlerLease) { - MethodConstraints leaseConstraints = - ((FiddlerLease.ConstrainableFiddlerLease)lease).getConstraints(); - - return new ConstrainableFiddlerLeaseMap(lease.getServer(), - lease, - duration, - leaseConstraints); - } else { - return new FiddlerLeaseMap(lease.getServer(), lease, duration); - }//endif - }//end createLeaseMap - - /** - * Constructs a new instance of FiddlerLeaseMap. - * - * @param server reference to the server object through which - * communication occurs between the client-side and - * server-side of the associated service. - * @param lease reference to a lease to add to the map as a key value - * @param duration the duration of the corresponding lease. This value - * is the "mapped" value corresponding to the lease key. - */ - private FiddlerLeaseMap(Fiddler server, FiddlerLease lease, long duration){ - super(); - this.server = server; - this.serverID = lease.getServerID(); - put(lease, duration); - }//end constructor - - /** - * Examines the input parameter to determine if that parameter will be - * accepted or rejected by this map as a "legal" key value. - * <p> - * This method will return true if the <code>key</code> parameter is - * the type of lease which can be "batch-wise" renewed and cancelled - * along with all of the other leases in the map. - * <p> - * For the Fiddler implementation of the lookup discovery service, two - * leases can be batched (placed in the same </code>FiddlerLeaseMap</code>) - * if they are both instances of <code>FiddlerLease</code> and they - * were both granted by the same Fiddler implementation of the lookup - * discovery service. That is, they are the same type, and they were - * granted by the same server. - * - * @param key reference to the object that this method examines to - * determine if this map will accept or reject it as a key - * - * @return true if this map will accept the <code>key</code> parameter, - * false otherwise - * - * @see net.jini.core.lease.Lease#canBatch - */ - public boolean canContainKey(Object key) { - return ( (key instanceof FiddlerLease) - && (serverID.equals(((FiddlerLease)key).getServerID())) ); - } - - /** - * Renews all leases in this map. For each lease (key) in the map, the - * duration used to renew the lease is the lease's corresponding map - * value. If all renewal attempts are successful, this method returns - * normally; otherwise, this method removes from this map all leases - * that could not be renewed, and throws a <code>LeaseMapException</code>. - * - * @throws net.jini.core.lease.LeaseMapException this exception is thrown - * when one or more leases in the map could not be renewed. - * - * @throws java.rmi.RemoteException typically, this exception occurs when - * there is a communication failure between the client and the - * server. When this exception does occur, the leases in the map - * may or may not have been renewed successfully. - */ - public void renewAll() throws LeaseMapException, RemoteException { - if (isEmpty()) return; - List<FiddlerLease> keys = new LinkedList<FiddlerLease>(); - List<Uuid> registrationIDs = new LinkedList<Uuid>(); - List<Uuid> leaseIDs = new LinkedList<Uuid>(); - List<Long> durations = new LinkedList<Long>(); - Iterator<Entry<FiddlerLease,Long>> it = entrySet().iterator(); - while (it.hasNext()){ - Entry<FiddlerLease,Long> e = it.next(); - FiddlerLease ls = e.getKey(); - keys.add(ls); - registrationIDs.add(ls.getRegistrationID()); - leaseIDs.add(ls.getLeaseID()); - durations.add(e.getValue()); - } - long [] dur = new long[durations.size()]; - int i = 0; - for (Iterator<Long> durIt = durations.iterator(); durIt.hasNext(); i++){ - dur[i] = durIt.next().intValue(); - } - FiddlerRenewResults results = server.renewLeases( - registrationIDs.toArray(new Uuid[registrationIDs.size()]), - leaseIDs.toArray(new Uuid[leaseIDs.size()]), - dur - ); - long now = System.currentTimeMillis(); - HashMap<Lease,Exception> emap = (results.exceptions != null) ? - new HashMap<Lease,Exception>(2 * results.exceptions.length + 1) : null; - i = 0; - int j = 0; - for (Iterator<FiddlerLease> iter = keys.iterator(); iter.hasNext(); i++) { - FiddlerLease e = iter.next(); - long duration = results.durations[i]; - if (duration >= 0) { - // Mutation of volatile field - e.setExpiration(duration + now); - } else { - emap.put(e, results.exceptions[j++]); - remove(e); - } - } - if (emap != null) { - throw new LeaseMapException("lease renewal failures", emap); - } - } - - /** - * Cancels all leases in this map. If all cancellation attempts are - * successful, this method returns normally; otherwise, this method - * removes from this map all leases that could not be cancelled, and - * throws a <code>LeaseMapException</code>. - * <p> - * Note that a lease is removed from this map only when an attempt to - * cancel it fails; that is, every lease that is successfully cancelled - * is left in the map. - * - * @throws net.jini.core.lease.LeaseMapException this exception is thrown - * when one or more leases in the map could not be cancelled. - * - * @throws java.rmi.RemoteException typically, this exception occurs when - * there is a communication failure between the client and the - * server. When this exception does occur, the leases in the map - * may or may not have been cancelled successfully. - */ - public void cancelAll() throws LeaseMapException, RemoteException { - if( isEmpty()) return; - List<FiddlerLease> leases = new LinkedList<FiddlerLease>(); - List<Uuid> registrationIDs = new LinkedList<Uuid>(); - List<Uuid> leaseIDs = new LinkedList<Uuid>(); - int i = 0; - for (Iterator<FiddlerLease> iter = keySet().iterator(); iter.hasNext(); i++) { - FiddlerLease ls = iter.next(); - leases.add(ls); - registrationIDs.add(ls.getRegistrationID()); - leaseIDs.add(ls.getLeaseID()); - } - Exception[] exceptions = server.cancelLeases( - registrationIDs.toArray(new Uuid[registrationIDs.size()]), - leaseIDs.toArray(new Uuid[leaseIDs.size()]) - ); - if (exceptions == null) { - return; - } - i = 0; - Map<Lease,Exception> emap = new HashMap<Lease,Exception>(13); - for (Iterator<FiddlerLease> iter = leases.iterator(); iter.hasNext(); i++) { - FiddlerLease ls = iter.next(); - Exception ex = exceptions[i]; - if (ex != null) { - emap.put(ls, ex); - remove(ls); - } - } - throw new LeaseMapException("lease cancellation failures", emap); - } - - /** The constrainable version of the class <code>FiddlerLeaseMap</code>. - * - * @since 2.0 - */ - static final class ConstrainableFiddlerLeaseMap extends FiddlerLeaseMap { - - /* Convenience fields containing, respectively, the renew and cancel - * methods defined in the Lease interface. These fields are used in - * the method mapping array, and when retrieving method constraints - * for comparison in canContainKey(). - */ - private static final Method renewMethod = - ProxyUtil.getMethod(Lease.class, - "renew", - new Class[] {long.class} ); - private static final Method cancelMethod = - ProxyUtil.getMethod(Lease.class, - "cancel", - new Class[] {} ); - - /* When a <code>LeaseMap</code> is created, an implicit set of - * constraints is generated and associated with that lease map. - * The constraints that are generated are based on the constraints - * on the first lease placed in that lease map. As such, the array - * defined here contains element pairs in which each pair of elements - * represents a correspondence 'mapping' between two methods having - * the following characteristics: - * - the first element in the pair is one of the public, remote - * method(s) that may be invoked by the client through a lease - * proxy, and which has method constraints that are intended - * to apply to the corresponding method that is invoked on - * server's backend - * - the second element in the pair is the method, implemented - * in the backend server class, that is intended to be - * executed with the same method constraints as its corresponding - * method, specified in the first element of the pair - */ - private static final Method[] methodMapArray = - { - renewMethod, ProxyUtil.getMethod(Fiddler.class, - "renewLeases", - new Class[] {Uuid[].class, - Uuid[].class, - long[].class}), - - cancelMethod, ProxyUtil.getMethod(Fiddler.class, - "cancelLeases", - new Class[] {Uuid[].class, - Uuid[].class}) - };//end methodMapArray - - /** In order to determine if a given lease will be accepted by this - * map as a "legal" key value, the method <code>canContainKey</code> - * must verify that the corresponding methods of the initial - * lease used to create this map and the lease input to - * <code>canContainKey</code> have equivalent constraints. The - * array defined here contains the set of methods whose constraints - * will be compared in <code>canContainKey</code>. - */ - private static final Method[] canContainKeyMethodMapArray = - { renewMethod, renewMethod, - cancelMethod, cancelMethod - };//end canContainKeyMethodMapArray - - /** Client constraints placed on this proxy (may be <code>null</code>). - * - * @serial - */ - private MethodConstraints methodConstraints; - - /** Constructs a new <code>ConstrainableFiddlerLeaseMap</code> - * instance. - * <p> - * For a description of all but the <code>methodConstraints</code> - * argument (provided below), refer to the description for the - * constructor of this class' super class. - * - * @param methodConstraints the client method constraints to place on - * this proxy (may be <code>null</code>). - */ - private ConstrainableFiddlerLeaseMap - (Fiddler server, - FiddlerLease lease, - long duration, - MethodConstraints methodConstraints) - { - super(constrainServer(server, methodConstraints), lease, duration); - this.methodConstraints = methodConstraints; - }//end constructor - - /** - * Examines the input parameter to determine if that parameter will - * be accepted or rejected by this map as a "legal" key value. - * <p> - * This method will return true if the <code>key</code> parameter is - * the type of lease which can be "batch-wise" renewed and cancelled - * along with all of the other leases in the map. - * <p> - * For this implementation of the service, two leases can be - * batched (placed in the same service-specific instance of - * <code>LeaseMap</code>) if those leases satisfy the following - * conditions: - * <p><ul> - * <li> the leases are the same type; that is, the leases are - * both instances of the same, constrainable, service-specific - * <code>Lease</code> implementation - * <li> the leases were granted by the same backend server - * <li> the leases have the same constraints - * - * @param key reference to the object that this method examines to - * determine if this map will accept or reject it as a key - * - * @return <code>true</code> if this map will accept the - * <code>key</code> parameter, <code>false</code> otherwise - * - * @see net.jini.core.lease.Lease#canBatch - * @see net.jini.core.lease.LeaseMap#canContainKey - */ - public boolean canContainKey(Object key) { - if( !(super.canContainKey(key)) ) return false; - /* Non-constrainable criteria satisfied, now handle constrainable - * case. - */ - if( !(key instanceof FiddlerLease.ConstrainableFiddlerLease) ) { - return false; - }//endif - /* Compare constraints */ - MethodConstraints keyConstraints = - ((FiddlerLease.ConstrainableFiddlerLease)key).getConstraints(); - return ConstrainableProxyUtil.equivalentConstraints - ( methodConstraints, - keyConstraints, - canContainKeyMethodMapArray ); - }//end ConstrainableFiddlerLeaseMap.canContainKey - - /** Returns a copy of the given server proxy having the client method - * constraints that result after the specified method mapping is - * applied to the given client method constraints. - */ - private static Fiddler constrainServer( Fiddler server, - MethodConstraints constraints ) - { - MethodConstraints newConstraints - = ConstrainableProxyUtil.translateConstraints(constraints, - methodMapArray); - RemoteMethodControl constrainedServer = - ((RemoteMethodControl)server).setConstraints(newConstraints); - - return ((Fiddler)constrainedServer); - }//end constrainServer - - }//end class ConstrainableFiddlerLeaseMap - -}//end class FiddlerLeaseMap +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.river.fiddler.proxy; + +import org.apache.river.proxy.ConstrainableProxyUtil; +import java.lang.reflect.Method; +import java.rmi.RemoteException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import net.jini.core.constraint.MethodConstraints; +import net.jini.core.constraint.RemoteMethodControl; +import net.jini.core.lease.Lease; +import net.jini.core.lease.LeaseMap; +import net.jini.core.lease.LeaseMapException; +import net.jini.id.Uuid; +import org.apache.river.lease.AbstractIDLeaseMap; + +/** + * When clients request a registration with the Fiddler implementation of + * the lookup discovery service, leases of type FiddlerLease are granted + * on those registrations. Under certain circumstances it may be desirable + * to collect multiple granted leases in a set which implements the + * <code>net.jini.core.lease.LeaseMap</code> interface. + * <p> + * This class is the implementation class of the <code>LeaseMap</code> + * interface that is employed by the Fiddler implementation of the lookup + * discovery service. When a client wishes to "batch" leases granted by + * that service, the are placed in an instance of this class. + * <p> + * Clients only see instances of this class via the <code>LeaseMap</code> + * interface. + * + * @author Sun Microsystems, Inc. + * + */ +class FiddlerLeaseMap extends AbstractIDLeaseMap<FiddlerLease> { + + /** + * The reference to the back-end server of the lookup discovery service + * + * @serial + */ + final Fiddler server; + /** + * The unique ID associated with the server referenced in this class + * (used to compare server references). + * + * @serial + */ + final Uuid serverID; + + /** + * Static factory method that creates and returns an instance of + * <code>FiddlerLeaseMap</code>. If the lease input to this method + * is and instance of <code>ConstrainableFiddlerLease</code>, then + * the object returned by this method will be an instance of + * <code>ConstrainableFiddlerLeaseMap</code>. + * + * Note that because of the way the <code>Lease</code> class for the + * associated service is implemented, together with the way the + * <code>canBatch</code> method of that class is implemented, if the + * <code>lease</code> object input to this method implements + * <code>ConstrainableFiddlerLease</code>, then the <code>server</code> + * object referenced in this class will implement + * <code>RemoteMethodControl</code> as well. + * + * @param lease reference to a lease to add to the map as a key value + * @param duration the duration of the corresponding lease. This value + * is the "mapped" value corresponding to the lease key. + * + * @return an instance of <code>FiddlerLeaseMap</code>, or an instance + * of <code>ConstrainableFiddlerLeaseMap</code> if the given + * <code>lease</code> is an instance of + * <code>ConstrainableFiddlerLease</code>. + */ + static FiddlerLeaseMap createLeaseMap(FiddlerLease lease, long duration) { + if(lease instanceof FiddlerLease.ConstrainableFiddlerLease) { + MethodConstraints leaseConstraints = + ((FiddlerLease.ConstrainableFiddlerLease)lease).getConstraints(); + + return new ConstrainableFiddlerLeaseMap(lease.getServer(), + lease, + duration, + leaseConstraints); + } else { + return new FiddlerLeaseMap(lease.getServer(), lease, duration); + }//endif + }//end createLeaseMap + + /** + * Constructs a new instance of FiddlerLeaseMap. + * + * @param server reference to the server object through which + * communication occurs between the client-side and + * server-side of the associated service. + * @param lease reference to a lease to add to the map as a key value + * @param duration the duration of the corresponding lease. This value + * is the "mapped" value corresponding to the lease key. + */ + private FiddlerLeaseMap(Fiddler server, FiddlerLease lease, long duration){ + super(); + this.server = server; + this.serverID = lease.getServerID(); + put(lease, duration); + }//end constructor + + /** + * Examines the input parameter to determine if that parameter will be + * accepted or rejected by this map as a "legal" key value. + * <p> + * This method will return true if the <code>key</code> parameter is + * the type of lease which can be "batch-wise" renewed and cancelled + * along with all of the other leases in the map. + * <p> + * For the Fiddler implementation of the lookup discovery service, two + * leases can be batched (placed in the same </code>FiddlerLeaseMap</code>) + * if they are both instances of <code>FiddlerLease</code> and they + * were both granted by the same Fiddler implementation of the lookup + * discovery service. That is, they are the same type, and they were + * granted by the same server. + * + * @param key reference to the object that this method examines to + * determine if this map will accept or reject it as a key + * + * @return true if this map will accept the <code>key</code> parameter, + * false otherwise + * + * @see net.jini.core.lease.Lease#canBatch + */ + public boolean canContainKey(Object key) { + return ( (key instanceof FiddlerLease) + && (serverID.equals(((FiddlerLease)key).getServerID())) ); + } + + /** + * Renews all leases in this map. For each lease (key) in the map, the + * duration used to renew the lease is the lease's corresponding map + * value. If all renewal attempts are successful, this method returns + * normally; otherwise, this method removes from this map all leases + * that could not be renewed, and throws a <code>LeaseMapException</code>. + * + * @throws net.jini.core.lease.LeaseMapException this exception is thrown + * when one or more leases in the map could not be renewed. + * + * @throws java.rmi.RemoteException typically, this exception occurs when + * there is a communication failure between the client and the + * server. When this exception does occur, the leases in the map + * may or may not have been renewed successfully. + */ + public void renewAll() throws LeaseMapException, RemoteException { + if (isEmpty()) return; + List<FiddlerLease> keys = new LinkedList<FiddlerLease>(); + List<Uuid> registrationIDs = new LinkedList<Uuid>(); + List<Uuid> leaseIDs = new LinkedList<Uuid>(); + List<Long> durations = new LinkedList<Long>(); + Iterator<Entry<FiddlerLease,Long>> it = entrySet().iterator(); + while (it.hasNext()){ + Entry<FiddlerLease,Long> e = it.next(); + FiddlerLease ls = e.getKey(); + keys.add(ls); + registrationIDs.add(ls.getRegistrationID()); + leaseIDs.add(ls.getLeaseID()); + durations.add(e.getValue()); + } + long [] dur = new long[durations.size()]; + int i = 0; + for (Iterator<Long> durIt = durations.iterator(); durIt.hasNext(); i++){ + dur[i] = durIt.next().intValue(); + } + FiddlerRenewResults results = server.renewLeases( + registrationIDs.toArray(new Uuid[registrationIDs.size()]), + leaseIDs.toArray(new Uuid[leaseIDs.size()]), + dur + ); + long now = System.currentTimeMillis(); + HashMap<Lease,Exception> emap = (results.exceptions != null) ? + new HashMap<Lease,Exception>(2 * results.exceptions.length + 1) : null; + i = 0; + int j = 0; + for (Iterator<FiddlerLease> iter = keys.iterator(); iter.hasNext(); i++) { + FiddlerLease e = iter.next(); + long duration = results.durations[i]; + if (duration >= 0) { + // Mutation of volatile field + e.setExpiration(duration + now); + } else { + emap.put(e, results.exceptions[j++]); + remove(e); + } + } + if (emap != null) { + throw new LeaseMapException("lease renewal failures", emap); + } + } + + /** + * Cancels all leases in this map. If all cancellation attempts are + * successful, this method returns normally; otherwise, this method + * removes from this map all leases that could not be cancelled, and + * throws a <code>LeaseMapException</code>. + * <p> + * Note that a lease is removed from this map only when an attempt to + * cancel it fails; that is, every lease that is successfully cancelled + * is left in the map. + * + * @throws net.jini.core.lease.LeaseMapException this exception is thrown + * when one or more leases in the map could not be cancelled. + * + * @throws java.rmi.RemoteException typically, this exception occurs when + * there is a communication failure between the client and the + * server. When this exception does occur, the leases in the map + * may or may not have been cancelled successfully. + */ + public void cancelAll() throws LeaseMapException, RemoteException { + if( isEmpty()) return; + List<FiddlerLease> leases = new LinkedList<FiddlerLease>(); + List<Uuid> registrationIDs = new LinkedList<Uuid>(); + List<Uuid> leaseIDs = new LinkedList<Uuid>(); + int i = 0; + for (Iterator<FiddlerLease> iter = keySet().iterator(); iter.hasNext(); i++) { + FiddlerLease ls = iter.next(); + leases.add(ls); + registrationIDs.add(ls.getRegistrationID()); + leaseIDs.add(ls.getLeaseID()); + } + Exception[] exceptions = server.cancelLeases( + registrationIDs.toArray(new Uuid[registrationIDs.size()]), + leaseIDs.toArray(new Uuid[leaseIDs.size()]) + ); + if (exceptions == null) { + return; + } + i = 0; + Map<Lease,Exception> emap = new HashMap<Lease,Exception>(13); + for (Iterator<FiddlerLease> iter = leases.iterator(); iter.hasNext(); i++) { + FiddlerLease ls = iter.next(); + Exception ex = exceptions[i]; + if (ex != null) { + emap.put(ls, ex); + remove(ls); + } + } + throw new LeaseMapException("lease cancellation failures", emap); + } + + /** The constrainable version of the class <code>FiddlerLeaseMap</code>. + * + * @since 2.0 + */ + static final class ConstrainableFiddlerLeaseMap extends FiddlerLeaseMap { + + /* Convenience fields containing, respectively, the renew and cancel + * methods defined in the Lease interface. These fields are used in + * the method mapping array, and when retrieving method constraints + * for comparison in canContainKey(). + */ + private static final Method renewMethod = + ProxyUtil.getMethod(Lease.class, + "renew", + new Class[] {long.class} ); + private static final Method cancelMethod = + ProxyUtil.getMethod(Lease.class, + "cancel", + new Class[] {} ); + + /* When a <code>LeaseMap</code> is created, an implicit set of + * constraints is generated and associated with that lease map. + * The constraints that are generated are based on the constraints + * on the first lease placed in that lease map. As such, the array + * defined here contains element pairs in which each pair of elements + * represents a correspondence 'mapping' between two methods having + * the following characteristics: + * - the first element in the pair is one of the public, remote + * method(s) that may be invoked by the client through a lease + * proxy, and which has method constraints that are intended + * to apply to the corresponding method that is invoked on + * server's backend + * - the second element in the pair is the method, implemented + * in the backend server class, that is intended to be + * executed with the same method constraints as its corresponding + * method, specified in the first element of the pair + */ + private static final Method[] methodMapArray = + { + renewMethod, ProxyUtil.getMethod(Fiddler.class, + "renewLeases", + new Class[] {Uuid[].class, + Uuid[].class, + long[].class}), + + cancelMethod, ProxyUtil.getMethod(Fiddler.class, + "cancelLeases", + new Class[] {Uuid[].class, + Uuid[].class}) + };//end methodMapArray + + /** In order to determine if a given lease will be accepted by this + * map as a "legal" key value, the method <code>canContainKey</code> + * must verify that the corresponding methods of the initial + * lease used to create this map and the lease input to + * <code>canContainKey</code> have equivalent constraints. The + * array defined here contains the set of methods whose constraints + * will be compared in <code>canContainKey</code>. + */ + private static final Method[] canContainKeyMethodMapArray = + { renewMethod, renewMethod, + cancelMethod, cancelMethod + };//end canContainKeyMethodMapArray + + /** Client constraints placed on this proxy (may be <code>null</code>). + * + * @serial + */ + private MethodConstraints methodConstraints; + + /** Constructs a new <code>ConstrainableFiddlerLeaseMap</code> + * instance. + * <p> + * For a description of all but the <code>methodConstraints</code> + * argument (provided below), refer to the description for the + * constructor of this class' super class. + * + * @param methodConstraints the client method constraints to place on + * this proxy (may be <code>null</code>). + */ + private ConstrainableFiddlerLeaseMap + (Fiddler server, + FiddlerLease lease, + long duration, + MethodConstraints methodConstraints) + { + super(constrainServer(server, methodConstraints), lease, duration); + this.methodConstraints = methodConstraints; + }//end constructor + + /** + * Examines the input parameter to determine if that parameter will + * be accepted or rejected by this map as a "legal" key value. + * <p> + * This method will return true if the <code>key</code> parameter is + * the type of lease which can be "batch-wise" renewed and cancelled + * along with all of the other leases in the map. + * <p> + * For this implementation of the service, two leases can be + * batched (placed in the same service-specific instance of + * <code>LeaseMap</code>) if those leases satisfy the following + * conditions: + * <p><ul> + * <li> the leases are the same type; that is, the leases are + * both instances of the same, constrainable, service-specific + * <code>Lease</code> implementation + * <li> the leases were granted by the same backend server + * <li> the leases have the same constraints + * + * @param key reference to the object that this method examines to + * determine if this map will accept or reject it as a key + * + * @return <code>true</code> if this map will accept the + * <code>key</code> parameter, <code>false</code> otherwise + * + * @see net.jini.core.lease.Lease#canBatch + * @see net.jini.core.lease.LeaseMap#canContainKey + */ + public boolean canContainKey(Object key) { + if( !(super.canContainKey(key)) ) return false; + /* Non-constrainable criteria satisfied, now handle constrainable + * case. + */ + if( !(key instanceof FiddlerLease.ConstrainableFiddlerLease) ) { + return false; + }//endif + /* Compare constraints */ + MethodConstraints keyConstraints = + ((FiddlerLease.ConstrainableFiddlerLease)key).getConstraints(); + return ConstrainableProxyUtil.equivalentConstraints + ( methodConstraints, + keyConstraints, + canContainKeyMethodMapArray ); + }//end ConstrainableFiddlerLeaseMap.canContainKey + + /** Returns a copy of the given server proxy having the client method + * constraints that result after the specified method mapping is + * applied to the given client method constraints. + */ + private static Fiddler constrainServer( Fiddler server, + MethodConstraints constraints ) + { + MethodConstraints newConstraints + = ConstrainableProxyUtil.translateConstraints(constraints, + methodMapArray); + RemoteMethodControl constrainedServer = + ((RemoteMethodControl)server).setConstraints(newConstraints); + + return ((Fiddler)constrainedServer); + }//end constrainServer + + }//end class ConstrainableFiddlerLeaseMap + +}//end class FiddlerLeaseMap
Modified: river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerProxy.java URL: http://svn.apache.org/viewvc/river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerProxy.java?rev=1879521&r1=1879520&r2=1879521&view=diff ============================================================================== --- river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerProxy.java (original) +++ river/jtsk/modules/modularize/apache-river/river-services/fiddler/fiddler-dl/src/main/java/org/apache/river/fiddler/proxy/FiddlerProxy.java Sun Jul 5 11:41:39 2020 @@ -1,483 +1,483 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.river.fiddler; - -import org.apache.river.proxy.ConstrainableProxyUtil; - -import net.jini.admin.Administrable; -import net.jini.discovery.LookupDiscoveryService; -import net.jini.discovery.LookupDiscoveryRegistration; -import net.jini.id.ReferentUuid; -import net.jini.id.ReferentUuids; -import net.jini.id.Uuid; -import net.jini.security.proxytrust.ProxyTrustIterator; -import net.jini.security.proxytrust.SingletonProxyTrustIterator; - -import net.jini.core.constraint.MethodConstraints; -import net.jini.core.constraint.RemoteMethodControl; -import net.jini.core.discovery.LookupLocator; -import net.jini.core.event.RemoteEventListener; - -import java.lang.reflect.Method; -import java.io.InvalidObjectException; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.rmi.RemoteException; -import java.rmi.MarshalledObject; - -/** - * This class is a proxy for a lookup discovery service. Clients only see - * instances of this class via the LookupDiscoveryService interface (and - * the FiddlerAdmin interface if needed). - * - * @author Sun Microsystems, Inc. - * - */ -class FiddlerProxy implements Administrable, LookupDiscoveryService, - ReferentUuid, Serializable -{ - private static final long serialVersionUID = 2L; - /** - * The reference through which communication occurs between the - * client-side and the server-side of the lookup discovery service - * - * @serial - */ - final Fiddler server; - /** - * The unique identifier assigned to the current instance of this - * proxy class by the lookup discovery service. This ID is used to - * determine equality between proxies. - * - * @serial - */ - final Uuid proxyID; - - /** - * Public static factory method that creates and returns an instance of - * <code>FiddlerProxy</code>. If the server associated with this proxy - * implements <code>RemoteMethodControl</code>, then the object returned by - * this method will also implement <code>RemoteMethodControl</code>. - * - * @param server reference to the server object through which - * communication occurs between the client-side and - * server-side of the associated service. - * @param proxyID the unique identifier assigned by the service to each - * instance of this proxy - * - * @return an instance of <code>FiddlerProxy</code> that implements - * <code>RemoteMethodControl</code> if the given <code>server</code> - * does. - */ - public static FiddlerProxy createServiceProxy(Fiddler server, - Uuid proxyID) - { - if(server instanceof RemoteMethodControl) { - return new ConstrainableFiddlerProxy(server, proxyID, null); - } else { - return new FiddlerProxy(server, proxyID); - }//endif - }//end createServiceProxy - - /** - * Constructs a new instance of FiddlerProxy. - * - * @param server reference to the server object through which - * communication occurs between the client-side and - * server-side of the associated service - * @param proxyID the unique identifier assigned by the service to each - * instance of this proxy - */ - private FiddlerProxy(Fiddler server, Uuid proxyID) { - this.server = server; - this.proxyID = proxyID; - }//end constructor - - /* From net.jini.admin.Administrable */ - /** - * Returns a proxy object through which the lookup discovery service - * for which the object on which this method is invoked serves as - * proxy may be administered - * - * @return a proxy object through which the lookup discovery service - * may be administered. - * - * @throws java.rmi.RemoteException typically, this exception occurs when - * there is a communication failure between the client and the - * server. - * - * @see net.jini.admin.Administrable - */ - public Object getAdmin() throws RemoteException { - return server.getAdmin(); - } - - /* From net.jini.discovery.LookupDiscoveryService */ - /** - * Registers with the lookup discovery service. When a client invokes - * this method, it requests that the lookup discovery service perform - * discovery processing on its behalf. - * - * @param groups String array, none of whose elements may be null, - * consisting of zero or more names of groups to - * which lookup services to discover belong. - * A null value or an empty array - * (net.jini.discovery.LookupDiscovery.ALL_GROUPS - * or net.jini.discovery.LookupDiscovery.NO_GROUPS) - * are both acceptable. - * - * @param locators array of zero or more non-null LookupLocator - * objects, each corresponding to a specific lookup - * service to discover. If either the empty array - * or null is passed to this argument, then no - * locator discovery will be performed for the - * associated registration. - * - * @param listener a non-null instance of RemoteEventListener. This - * argument specifies the entity that will receive - * events notifying the registration that a lookup - * service of interest has been discovered. A - * non-null value must be passed to this argument, - * otherwise a NullPointerException will be thrown - * and the registration. - * - * @param handback null or an instance of MarshalledObject. This - * argument specifies an object that will be - * included in the notification event that the - * lookup discovery service sends to the registered - * listener. - * - * @param leaseDuration long value representing the amount of time (in - * milliseconds) for which the resources of the - * lookup discovery service are being requested. - * - * @return an instance of the LookupDiscoveryRegistration interface. - * - * @throws java.rmi.RemoteException typically, this exception occurs when - * there is a communication failure between the client and the - * server. When this exception does occur, the registration may - * or may not have completed successfully. - * - * @throws java.lang.NullPointerException this exception occurs when - * null is input to the listener parameter. - * - * @see net.jini.discovery.LookupDiscoveryService - */ - public LookupDiscoveryRegistration register(String[] groups, - LookupLocator[] locators, - RemoteEventListener listener, - MarshalledObject handback, - long leaseDuration) - throws RemoteException - { - return server.register(groups, - locators, - listener, - handback, - leaseDuration); - } - - /* From net.jini.id.ReferentUuid */ - /** - * Returns the universally unique identifier that has been assigned to the - * resource this proxy represents. - * - * @return the instance of <code>Uuid</code> that is associated with the - * resource this proxy represents. This method will not return - * <code>null</code>. - * - * @see net.jini.id.ReferentUuid - */ - public Uuid getReferentUuid() { - return proxyID; - } - - /** - * For any instance of this class, returns the hashcode value generated - * by the hashCode method of the proxy ID associated with the current - * instance of this proxy. - * - * @return <code>int</code> value representing the hashcode for an - * instance of this class. - */ - public int hashCode() { - return proxyID.hashCode(); - } - - /** - * For any instance of this class, indicates whether the object input - * to this method is equal to the current instance of this class; where - * equality of proxies to a lookup discovery service is defined by - * reference equality. That is, two proxies are equal if they reference - * (are proxies to) the same backend server. - * - * @param obj reference to the object that is to be compared to the - * object on which this method is invoked. - * - * @return <code>true</code> if the object input is referentially - * equal to the object on which this method is invoked; - * <code>false</code> otherwise. - */ - public boolean equals(Object obj) { - return ReferentUuids.compare(this,obj); - } - - /** When an instance of this class is deserialized, this method is - * automatically invoked. This implementation of this method validates - * the state of the deserialized instance. - * - * @throws <code>InvalidObjectException</code> if the state of the - * deserialized instance of this class is found to be invalid. - */ - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException - { - s.defaultReadObject(); - /* Verify server */ - if(server == null) { - throw new InvalidObjectException("FiddlerProxy.readObject " - +"failure - server " - +"field is null"); - }//endif - /* Verify proxyID */ - if(proxyID == null) { - throw new InvalidObjectException("FiddlerProxy.readObject " - +"failure - proxyID " - +"field is null"); - }//endif - }//end readObject - - /** During deserialization of an instance of this class, if it is found - * that the stream contains no data, this method is automatically - * invoked. Because it is expected that the stream should always - * contain data, this implementation of this method simply declares - * that something must be wrong. - * - * @throws <code>InvalidObjectException</code> to indicate that there - * was no data in the stream during deserialization of an - * instance of this class; declaring that something is wrong. - */ - private void readObjectNoData() throws InvalidObjectException { - throw new InvalidObjectException("no data found when attempting to " - +"deserialize FiddlerProxy instance"); - }//end readObjectNoData - - /** The constrainable version of the class <code>FiddlerProxy</code>. - * <p> - * When a client obtains an instance of this proxy class, the client - * should not attempt to use the proxy until the client is assured - * that the proxy can be trusted. In addition to implementing the - * methods and mechanisms required by <code>RemoteMethodControl</code>, - * this class - in conjunction with the service's - * <code>ProxyVerifier</code> class, helps provide a mechanism - * for verifying trust in the proxy on behalf of a client. - * <p> - * In order to verify that an instance of this class is trusted, - * trust must be verified in all subsidiary objects (contained in that - * instance) through which the client ultimately makes calls (local or - * remote). With respect to this class, the <code>server</code> field - * is a proxy object through which the client makes remote calls to the - * service's backend. Therefore, trust in that object must be - * verified. Additionally, this class also contains a field of type - * <code>Uuid</code> (<code>proxyID</code> which should be - * tested for trust. Consider the following diagram: - * <p> - * <pre> - * FiddlerProxy { - * Fiddler server - * Uuid proxyID - * }//end FiddlerProxy - * </pre> - * <p> - * Thus, in order to verify that an instance of this class is trusted, - * trust must be verified in the following objects from the diagram - * above: - * <ul><li> server - * <li> proxyID - * </ul> - * - * When a client obtains an instance of this proxy class, the - * deserialization process which delivers the proxy to the client - * invokes the <code>readObject</code> method of this class. Part of - * trust verification is performed in the <code>readObject</code> method, - * and part is performed when the client prepares the proxy. Thus, this - * class' participation in the trust verification process can be - * summarized as follows: - * <p> - * <ul> - * <li> server - * <ul> - * <li> readObject - * <ul> - * <li> verify server != null - * <li> verify server implements RemoteMethodControl - * <li> verify server's method constraints are the same - * as those placed on the corresponding public Remote - * methods of its outer proxy class - * </ul> - * <li> proxy preparation - * <ul> - * <li> Security.verifyObjectTrust() which calls - * <li> ProxyVerifier.isTrustedObject() which calls - * <li> canonicalServerObject.checkTrustEquivalence(server) - * (whose implementation is supplied by the particular - * RMI implementation that was used to export the server) - * </ul> - * </ul> - * <li> proxyID - * <ul><li> readObject - * <ul><li> verify proxyID != null</ul> - * </ul> - * </ul> - * - * @since 2.0 - */ - static final class ConstrainableFiddlerProxy extends FiddlerProxy - implements RemoteMethodControl - { - static final long serialVersionUID = 2L; - - /* Array containing element pairs in which each pair of elements - * represents a correspondence 'mapping' between two methods having - * the following characteristics: - * - the first element in the pair is one of the public, remote - * method(s) that may be invoked by the client through the proxy - * class that this class extends - * - the second element in the pair is the method, implemented - * in the backend server class, that is ultimately executed in - * the server's backend when the client invokes the corresponding - * method in this proxy - */ - private static final Method[] methodMapArray = - { - ProxyUtil.getMethod(Administrable.class, - "getAdmin", new Class[] {} ), - ProxyUtil.getMethod(Administrable.class, - "getAdmin", new Class[] {} ), - - ProxyUtil.getMethod(LookupDiscoveryService.class, - "register", - new Class[] {String[].class, - LookupLocator[].class, - RemoteEventListener.class, - MarshalledObject.class, - long.class} ), - ProxyUtil.getMethod(Fiddler.class, - "register", - new Class[] {String[].class, - LookupLocator[].class, - RemoteEventListener.class, - MarshalledObject.class, - long.class} ) - };//end methodMapArray - - /** Client constraints placed on this proxy (may be <code>null</code>). - * - * @serial - */ - private MethodConstraints methodConstraints; - - /** Constructs a new <code>ConstrainableFiddlerProxy</code> instance. - * <p> - * For a description of all but the <code>methodConstraints</code> - * argument (provided below), refer to the description for the - * constructor of this class' super class. - * - * @param methodConstraints the client method constraints to place on - * this proxy (may be <code>null</code>). - */ - private ConstrainableFiddlerProxy(Fiddler server, - Uuid proxyID, - MethodConstraints methodConstraints) - { - super( constrainServer(server, methodConstraints), proxyID); - this.methodConstraints = methodConstraints; - }//end constructor - - /** Returns a copy of the given server proxy having the client method - * constraints that result after the specified method mapping is - * applied to the given client method constraints. - */ - private static Fiddler constrainServer( Fiddler server, - MethodConstraints constraints ) - { - MethodConstraints newConstraints - = ConstrainableProxyUtil.translateConstraints(constraints, - methodMapArray); - RemoteMethodControl constrainedServer = - ((RemoteMethodControl)server).setConstraints(newConstraints); - - return ((Fiddler)constrainedServer); - }//end constrainServer - - /** Returns a new copy of this proxy class - * (<code>ConstrainableFiddlerProxy</code>) with its client - * constraints set to the specified constraints. A <code>null</code> - * value is interpreted as mapping all methods to empty constraints. - */ - public RemoteMethodControl setConstraints - (MethodConstraints constraints) - { - return ( new ConstrainableFiddlerProxy - (server, proxyID, constraints) ); - }//end setConstraints - - /** Returns the client constraints placed on the current instance - * of this proxy class (<code>ConstrainableFiddlerProxy</code>). - * The value returned by this method can be <code>null</code>, - * which is interpreted as mapping all methods to empty constraints. - */ - public MethodConstraints getConstraints() { - return methodConstraints; - }//end getConstraints - - /** Returns a proxy trust iterator that is used in - * <code>ProxyTrustVerifier</code> to retrieve this object's - * trust verifier. - */ - private ProxyTrustIterator getProxyTrustIterator() { - return new SingletonProxyTrustIterator(server); - }//end getProxyTrustIterator - - /** Performs various functions related to the trust verification - * process for the current instance of this proxy class, as - * detailed in the description for this class. - * - * @throws <code>InvalidObjectException</code> if any of the - * requirements for trust verification (as detailed in the - * class description) are not satisfied. - */ - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException - { - /* Note that basic validation of the fields of this class was - * already performed in the readObject() method of this class' - * super class. - */ - s.defaultReadObject(); - /* Verify the server and its constraints */ - ConstrainableProxyUtil.verifyConsistentConstraints - (methodConstraints, - server, - methodMapArray); - }//end readObject - - }//end class ConstrainableFiddlerProxy - -}//end class FiddlerProxy +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.river.fiddler.proxy; + +import org.apache.river.proxy.ConstrainableProxyUtil; + +import net.jini.admin.Administrable; +import net.jini.discovery.LookupDiscoveryService; +import net.jini.discovery.LookupDiscoveryRegistration; +import net.jini.id.ReferentUuid; +import net.jini.id.ReferentUuids; +import net.jini.id.Uuid; +import net.jini.security.proxytrust.ProxyTrustIterator; +import net.jini.security.proxytrust.SingletonProxyTrustIterator; + +import net.jini.core.constraint.MethodConstraints; +import net.jini.core.constraint.RemoteMethodControl; +import net.jini.core.discovery.LookupLocator; +import net.jini.core.event.RemoteEventListener; + +import java.lang.reflect.Method; +import java.io.InvalidObjectException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.rmi.RemoteException; +import java.rmi.MarshalledObject; + +/** + * This class is a proxy for a lookup discovery service. Clients only see + * instances of this class via the LookupDiscoveryService interface (and + * the FiddlerAdmin interface if needed). + * + * @author Sun Microsystems, Inc. + * + */ +public class FiddlerProxy implements Administrable, LookupDiscoveryService, + ReferentUuid, Serializable +{ + private static final long serialVersionUID = 2L; + /** + * The reference through which communication occurs between the + * client-side and the server-side of the lookup discovery service + * + * @serial + */ + final Fiddler server; + /** + * The unique identifier assigned to the current instance of this + * proxy class by the lookup discovery service. This ID is used to + * determine equality between proxies. + * + * @serial + */ + final Uuid proxyID; + + /** + * Public static factory method that creates and returns an instance of + * <code>FiddlerProxy</code>. If the server associated with this proxy + * implements <code>RemoteMethodControl</code>, then the object returned by + * this method will also implement <code>RemoteMethodControl</code>. + * + * @param server reference to the server object through which + * communication occurs between the client-side and + * server-side of the associated service. + * @param proxyID the unique identifier assigned by the service to each + * instance of this proxy + * + * @return an instance of <code>FiddlerProxy</code> that implements + * <code>RemoteMethodControl</code> if the given <code>server</code> + * does. + */ + public static FiddlerProxy createServiceProxy(Fiddler server, + Uuid proxyID) + { + if(server instanceof RemoteMethodControl) { + return new ConstrainableFiddlerProxy(server, proxyID, null); + } else { + return new FiddlerProxy(server, proxyID); + }//endif + }//end createServiceProxy + + /** + * Constructs a new instance of FiddlerProxy. + * + * @param server reference to the server object through which + * communication occurs between the client-side and + * server-side of the associated service + * @param proxyID the unique identifier assigned by the service to each + * instance of this proxy + */ + private FiddlerProxy(Fiddler server, Uuid proxyID) { + this.server = server; + this.proxyID = proxyID; + }//end constructor + + /* From net.jini.admin.Administrable */ + /** + * Returns a proxy object through which the lookup discovery service + * for which the object on which this method is invoked serves as + * proxy may be administered + * + * @return a proxy object through which the lookup discovery service + * may be administered. + * + * @throws java.rmi.RemoteException typically, this exception occurs when + * there is a communication failure between the client and the + * server. + * + * @see net.jini.admin.Administrable + */ + public Object getAdmin() throws RemoteException { + return server.getAdmin(); + } + + /* From net.jini.discovery.LookupDiscoveryService */ + /** + * Registers with the lookup discovery service. When a client invokes + * this method, it requests that the lookup discovery service perform + * discovery processing on its behalf. + * + * @param groups String array, none of whose elements may be null, + * consisting of zero or more names of groups to + * which lookup services to discover belong. + * A null value or an empty array + * (net.jini.discovery.LookupDiscovery.ALL_GROUPS + * or net.jini.discovery.LookupDiscovery.NO_GROUPS) + * are both acceptable. + * + * @param locators array of zero or more non-null LookupLocator + * objects, each corresponding to a specific lookup + * service to discover. If either the empty array + * or null is passed to this argument, then no + * locator discovery will be performed for the + * associated registration. + * + * @param listener a non-null instance of RemoteEventListener. This + * argument specifies the entity that will receive + * events notifying the registration that a lookup + * service of interest has been discovered. A + * non-null value must be passed to this argument, + * otherwise a NullPointerException will be thrown + * and the registration. + * + * @param handback null or an instance of MarshalledObject. This + * argument specifies an object that will be + * included in the notification event that the + * lookup discovery service sends to the registered + * listener. + * + * @param leaseDuration long value representing the amount of time (in + * milliseconds) for which the resources of the + * lookup discovery service are being requested. + * + * @return an instance of the LookupDiscoveryRegistration interface. + * + * @throws java.rmi.RemoteException typically, this exception occurs when + * there is a communication failure between the client and the + * server. When this exception does occur, the registration may + * or may not have completed successfully. + * + * @throws java.lang.NullPointerException this exception occurs when + * null is input to the listener parameter. + * + * @see net.jini.discovery.LookupDiscoveryService + */ + public LookupDiscoveryRegistration register(String[] groups, + LookupLocator[] locators, + RemoteEventListener listener, + MarshalledObject handback, + long leaseDuration) + throws RemoteException + { + return server.register(groups, + locators, + listener, + handback, + leaseDuration); + } + + /* From net.jini.id.ReferentUuid */ + /** + * Returns the universally unique identifier that has been assigned to the + * resource this proxy represents. + * + * @return the instance of <code>Uuid</code> that is associated with the + * resource this proxy represents. This method will not return + * <code>null</code>. + * + * @see net.jini.id.ReferentUuid + */ + public Uuid getReferentUuid() { + return proxyID; + } + + /** + * For any instance of this class, returns the hashcode value generated + * by the hashCode method of the proxy ID associated with the current + * instance of this proxy. + * + * @return <code>int</code> value representing the hashcode for an + * instance of this class. + */ + public int hashCode() { + return proxyID.hashCode(); + } + + /** + * For any instance of this class, indicates whether the object input + * to this method is equal to the current instance of this class; where + * equality of proxies to a lookup discovery service is defined by + * reference equality. That is, two proxies are equal if they reference + * (are proxies to) the same backend server. + * + * @param obj reference to the object that is to be compared to the + * object on which this method is invoked. + * + * @return <code>true</code> if the object input is referentially + * equal to the object on which this method is invoked; + * <code>false</code> otherwise. + */ + public boolean equals(Object obj) { + return ReferentUuids.compare(this,obj); + } + + /** When an instance of this class is deserialized, this method is + * automatically invoked. This implementation of this method validates + * the state of the deserialized instance. + * + * @throws <code>InvalidObjectException</code> if the state of the + * deserialized instance of this class is found to be invalid. + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + /* Verify server */ + if(server == null) { + throw new InvalidObjectException("FiddlerProxy.readObject " + +"failure - server " + +"field is null"); + }//endif + /* Verify proxyID */ + if(proxyID == null) { + throw new InvalidObjectException("FiddlerProxy.readObject " + +"failure - proxyID " + +"field is null"); + }//endif + }//end readObject + + /** During deserialization of an instance of this class, if it is found + * that the stream contains no data, this method is automatically + * invoked. Because it is expected that the stream should always + * contain data, this implementation of this method simply declares + * that something must be wrong. + * + * @throws <code>InvalidObjectException</code> to indicate that there + * was no data in the stream during deserialization of an + * instance of this class; declaring that something is wrong. + */ + private void readObjectNoData() throws InvalidObjectException { + throw new InvalidObjectException("no data found when attempting to " + +"deserialize FiddlerProxy instance"); + }//end readObjectNoData + + /** The constrainable version of the class <code>FiddlerProxy</code>. + * <p> + * When a client obtains an instance of this proxy class, the client + * should not attempt to use the proxy until the client is assured + * that the proxy can be trusted. In addition to implementing the + * methods and mechanisms required by <code>RemoteMethodControl</code>, + * this class - in conjunction with the service's + * <code>ProxyVerifier</code> class, helps provide a mechanism + * for verifying trust in the proxy on behalf of a client. + * <p> + * In order to verify that an instance of this class is trusted, + * trust must be verified in all subsidiary objects (contained in that + * instance) through which the client ultimately makes calls (local or + * remote). With respect to this class, the <code>server</code> field + * is a proxy object through which the client makes remote calls to the + * service's backend. Therefore, trust in that object must be + * verified. Additionally, this class also contains a field of type + * <code>Uuid</code> (<code>proxyID</code> which should be + * tested for trust. Consider the following diagram: + * <p> + * <pre> + * FiddlerProxy { + * Fiddler server + * Uuid proxyID + * }//end FiddlerProxy + * </pre> + * <p> + * Thus, in order to verify that an instance of this class is trusted, + * trust must be verified in the following objects from the diagram + * above: + * <ul><li> server + * <li> proxyID + * </ul> + * + * When a client obtains an instance of this proxy class, the + * deserialization process which delivers the proxy to the client + * invokes the <code>readObject</code> method of this class. Part of + * trust verification is performed in the <code>readObject</code> method, + * and part is performed when the client prepares the proxy. Thus, this + * class' participation in the trust verification process can be + * summarized as follows: + * <p> + * <ul> + * <li> server + * <ul> + * <li> readObject + * <ul> + * <li> verify server != null + * <li> verify server implements RemoteMethodControl + * <li> verify server's method constraints are the same + * as those placed on the corresponding public Remote + * methods of its outer proxy class + * </ul> + * <li> proxy preparation + * <ul> + * <li> Security.verifyObjectTrust() which calls + * <li> ProxyVerifier.isTrustedObject() which calls + * <li> canonicalServerObject.checkTrustEquivalence(server) + * (whose implementation is supplied by the particular + * RMI implementation that was used to export the server) + * </ul> + * </ul> + * <li> proxyID + * <ul><li> readObject + * <ul><li> verify proxyID != null</ul> + * </ul> + * </ul> + * + * @since 2.0 + */ + static final class ConstrainableFiddlerProxy extends FiddlerProxy + implements RemoteMethodControl + { + static final long serialVersionUID = 2L; + + /* Array containing element pairs in which each pair of elements + * represents a correspondence 'mapping' between two methods having + * the following characteristics: + * - the first element in the pair is one of the public, remote + * method(s) that may be invoked by the client through the proxy + * class that this class extends + * - the second element in the pair is the method, implemented + * in the backend server class, that is ultimately executed in + * the server's backend when the client invokes the corresponding + * method in this proxy + */ + private static final Method[] methodMapArray = + { + ProxyUtil.getMethod(Administrable.class, + "getAdmin", new Class[] {} ), + ProxyUtil.getMethod(Administrable.class, + "getAdmin", new Class[] {} ), + + ProxyUtil.getMethod(LookupDiscoveryService.class, + "register", + new Class[] {String[].class, + LookupLocator[].class, + RemoteEventListener.class, + MarshalledObject.class, + long.class} ), + ProxyUtil.getMethod(Fiddler.class, + "register", + new Class[] {String[].class, + LookupLocator[].class, + RemoteEventListener.class, + MarshalledObject.class, + long.class} ) + };//end methodMapArray + + /** Client constraints placed on this proxy (may be <code>null</code>). + * + * @serial + */ + private MethodConstraints methodConstraints; + + /** Constructs a new <code>ConstrainableFiddlerProxy</code> instance. + * <p> + * For a description of all but the <code>methodConstraints</code> + * argument (provided below), refer to the description for the + * constructor of this class' super class. + * + * @param methodConstraints the client method constraints to place on + * this proxy (may be <code>null</code>). + */ + private ConstrainableFiddlerProxy(Fiddler server, + Uuid proxyID, + MethodConstraints methodConstraints) + { + super( constrainServer(server, methodConstraints), proxyID); + this.methodConstraints = methodConstraints; + }//end constructor + + /** Returns a copy of the given server proxy having the client method + * constraints that result after the specified method mapping is + * applied to the given client method constraints. + */ + private static Fiddler constrainServer( Fiddler server, + MethodConstraints constraints ) + { + MethodConstraints newConstraints + = ConstrainableProxyUtil.translateConstraints(constraints, + methodMapArray); + RemoteMethodControl constrainedServer = + ((RemoteMethodControl)server).setConstraints(newConstraints); + + return ((Fiddler)constrainedServer); + }//end constrainServer + + /** Returns a new copy of this proxy class + * (<code>ConstrainableFiddlerProxy</code>) with its client + * constraints set to the specified constraints. A <code>null</code> + * value is interpreted as mapping all methods to empty constraints. + */ + public RemoteMethodControl setConstraints + (MethodConstraints constraints) + { + return ( new ConstrainableFiddlerProxy + (server, proxyID, constraints) ); + }//end setConstraints + + /** Returns the client constraints placed on the current instance + * of this proxy class (<code>ConstrainableFiddlerProxy</code>). + * The value returned by this method can be <code>null</code>, + * which is interpreted as mapping all methods to empty constraints. + */ + public MethodConstraints getConstraints() { + return methodConstraints; + }//end getConstraints + + /** Returns a proxy trust iterator that is used in + * <code>ProxyTrustVerifier</code> to retrieve this object's + * trust verifier. + */ + private ProxyTrustIterator getProxyTrustIterator() { + return new SingletonProxyTrustIterator(server); + }//end getProxyTrustIterator + + /** Performs various functions related to the trust verification + * process for the current instance of this proxy class, as + * detailed in the description for this class. + * + * @throws <code>InvalidObjectException</code> if any of the + * requirements for trust verification (as detailed in the + * class description) are not satisfied. + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + /* Note that basic validation of the fields of this class was + * already performed in the readObject() method of this class' + * super class. + */ + s.defaultReadObject(); + /* Verify the server and its constraints */ + ConstrainableProxyUtil.verifyConsistentConstraints + (methodConstraints, + server, + methodMapArray); + }//end readObject + + }//end class ConstrainableFiddlerProxy + +}//end class FiddlerProxy
