View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.river.reggie.proxy;
19  
20  import org.apache.river.proxy.ConstrainableProxyUtil;
21  import java.io.IOException;
22  import java.io.InvalidObjectException;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectOutputStream;
25  import java.lang.reflect.Method;
26  import java.rmi.RemoteException;
27  import net.jini.core.constraint.MethodConstraints;
28  import net.jini.core.constraint.RemoteMethodControl;
29  import net.jini.core.lease.Lease;
30  import net.jini.core.lease.LeaseDeniedException;
31  import net.jini.core.lease.LeaseMap;
32  import net.jini.core.lease.UnknownLeaseException;
33  import net.jini.core.lookup.ServiceID;
34  import net.jini.id.Uuid;
35  import net.jini.security.proxytrust.ProxyTrustIterator;
36  import net.jini.security.proxytrust.SingletonProxyTrustIterator;
37  import org.apache.river.api.io.AtomicSerial;
38  
39  /**
40   * ServiceLease subclass that supports constraints.
41   *
42   * @author Sun Microsystems, Inc.
43   *
44   */
45  @AtomicSerial
46  final class ConstrainableServiceLease
47      extends ServiceLease implements RemoteMethodControl
48  {
49      private static final long serialVersionUID = 2L;
50  
51      /** Mappings between Lease and Registrar methods */
52      private static final Method[] methodMappings = {
53  	Util.getMethod(Lease.class, "cancel", new Class[0]),
54  	Util.getMethod(Registrar.class, "cancelServiceLease",
55  		       new Class[]{ ServiceID.class, Uuid.class }),
56  
57  	Util.getMethod(Lease.class, "renew", new Class[]{ long.class }),
58  	Util.getMethod(Registrar.class, "renewServiceLease",
59  		       new Class[]{ ServiceID.class, Uuid.class, long.class })
60      };
61  
62       /**
63       * Verifies that the client constraints for this proxy are consistent with
64       * those set on the underlying server ref.
65       */
66      public static void verifyConsistentConstraints(
67  	MethodConstraints constraints, Object proxy) throws InvalidObjectException {
68  	ConstrainableProxyUtil.verifyConsistentConstraints(
69  	    constraints, proxy, methodMappings);
70      }
71  
72      /** Client constraints for this proxy, or null */
73      private final MethodConstraints constraints;
74  
75      private static AtomicSerial.GetArg check(AtomicSerial.GetArg arg) throws IOException{
76  	RegistrarLease rl = new RegistrarLease(arg){
77  	    private UnsupportedOperationException exception(){
78  		return new UnsupportedOperationException("Validator only.");
79  	    }
80  	    Object getRegID() { throw exception();}
81  	    String getLeaseType() { throw exception(); }
82  	    protected long doRenew(long duration) throws UnknownLeaseException,
83  		    LeaseDeniedException, RemoteException {throw exception();}
84  	    public void cancel() throws UnknownLeaseException,
85  		    RemoteException { throw exception();}
86  	};
87  	MethodConstraints constraints = (MethodConstraints) arg.get("constraints", null);
88  	verifyConsistentConstraints(constraints, rl.server);
89  	return arg;
90      }
91      
92      ConstrainableServiceLease(AtomicSerial.GetArg arg) throws IOException{
93  	super(check(arg));
94  	constraints = (MethodConstraints) arg.get("constraints", null);
95      }
96  
97      /**
98       * Creates new ConstrainableServiceLease with given server reference, event
99       * and lease IDs, expiration time and client constraints.
100      */
101     ConstrainableServiceLease(
102 	    Registrar server,
103 			      ServiceID registrarID,
104 			      ServiceID serviceID,
105 			      Uuid leaseID,
106 			      long expiration,
107 	    MethodConstraints constraints,
108 	    boolean setConstraints)
109     {
110 	super(setConstraints ? (Registrar) ((RemoteMethodControl) server).setConstraints(
111 		  ConstrainableProxyUtil.translateConstraints(
112 		      constraints, methodMappings)) : server,
113 	      registrarID,
114 	      serviceID,
115 	      leaseID,
116 	      expiration);
117 	this.constraints = constraints;
118     }
119 
120     /**
121      * Creates a constraint-aware lease map.
122      */
123     public LeaseMap<? extends Lease,Long> createLeaseMap(long duration) {
124 	return new ConstrainableRegistrarLeaseMap(this, duration);
125     }
126 
127     /**
128      * Two leases can be batched if they are both RegistrarLeases, share the
129      * same server, and have compatible constraints.
130      */
131     public boolean canBatch(Lease lease) {
132 	if (!(super.canBatch(lease) && lease instanceof RemoteMethodControl)) {
133 	    return false;
134 	}
135 	return ConstrainableProxyUtil.equivalentConstraints(
136 	    ((RemoteMethodControl) lease).getConstraints(),
137 	    ConstrainableProxyUtil.translateConstraints(
138 		constraints, ConstrainableRegistrarLeaseMap.methodMappings),
139 	    ConstrainableRegistrarLeaseMap.methodMappings);
140     }
141 
142     // javadoc inherited from RemoteMethodControl.setConstraints
143     public RemoteMethodControl setConstraints(MethodConstraints constraints) {
144 	return new ConstrainableServiceLease(
145 	    server, registrarID, serviceID, leaseID, getExpiration(), constraints, true);
146     }
147 
148     // javadoc inherited from RemoteMethodControl.getConstraints
149     public MethodConstraints getConstraints() {
150 	return constraints;
151     }
152 
153     /**
154      * Returns iterator used by ProxyTrustVerifier to retrieve a trust verifier
155      * for this object.
156      */
157     private ProxyTrustIterator getProxyTrustIterator() {
158 	return new SingletonProxyTrustIterator(server);
159     }
160 
161     private void writeObject(ObjectOutputStream out) throws IOException {
162 	out.defaultWriteObject();
163     }
164 
165     /**
166      * Verifies that the client constraints for this proxy are consistent with
167      * those set on the underlying server ref.
168      */
169     private void readObject(ObjectInputStream in)
170 	throws IOException, ClassNotFoundException
171     {
172 	in.defaultReadObject();
173 	verifyConsistentConstraints(constraints, server);
174     }
175 }