/* * 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.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.id.Uuid; import net.jini.io.MarshalledInstance; import net.jini.lease.LeaseRenewalSet; import net.jini.lease.LeaseUnmarshalException; import net.jini.security.proxytrust.ProxyTrustIterator; import net.jini.security.proxytrust.SingletonProxyTrustIterator; import com.sun.jini.landlord.ConstrainableLandlordLease; import com.sun.jini.proxy.ConstrainableProxyUtil; import com.sun.jini.proxy.ThrowThis; /** * 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); } } }