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.outrigger.proxy;
19  
20  import org.apache.river.landlord.ConstrainableLandlordLease;
21  import org.apache.river.proxy.ConstrainableProxyUtil;
22  import java.io.IOException;
23  import java.io.ObjectInputStream;
24  import java.lang.reflect.Method;
25  import java.rmi.MarshalledObject;
26  import java.util.Collection;
27  import net.jini.admin.Administrable;
28  import net.jini.core.constraint.MethodConstraints;
29  import net.jini.core.constraint.RemoteMethodControl;
30  import net.jini.core.entry.Entry;
31  import net.jini.core.event.RemoteEventListener;
32  import net.jini.core.lease.Lease;
33  import net.jini.core.transaction.Transaction;
34  import net.jini.id.Uuid;
35  import net.jini.io.MarshalledInstance;
36  import net.jini.security.proxytrust.ProxyTrustIterator;
37  import net.jini.security.proxytrust.SingletonProxyTrustIterator;
38  import net.jini.space.JavaSpace;
39  import net.jini.space.JavaSpace05;
40  import org.apache.river.api.io.AtomicSerial;
41  import org.apache.river.api.io.AtomicSerial.GetArg;
42  
43  /**
44   * Constrainable subclass of <code>SpaceProxy2</code>
45   */
46  @AtomicSerial
47  public final class ConstrainableSpaceProxy2 extends SpaceProxy2
48      implements RemoteMethodControl 
49  {
50      static final long serialVersionUID = 1L;
51  
52      /**
53       * Array containing element pairs in which each pair of elements
54       * represents a mapping between two methods having the following
55       * characteristics:
56       * <ul>
57       * <li> the first element in the pair is one of the public, remote
58       *      method(s) that may be invoked by the client through 
59       *      <code>SpaceProxy2</code>.
60       * <li> the second element in the pair is the method, implemented
61       *      in the backend server class, that is ultimately executed in
62       *      the server's backend when the client invokes the corresponding
63       *      method in this proxy.
64       * </ul>
65       */
66      private static final Method[] methodMapArray =  {
67  	ProxyUtil.getMethod(Administrable.class, "getAdmin", new Class[] {}),
68  	ProxyUtil.getMethod(Administrable.class, "getAdmin", new Class[] {}),
69  
70  	ProxyUtil.getMethod(JavaSpace.class, "write", 
71  			    new Class[] {Entry.class,
72  					 Transaction.class,
73  					 long.class}),
74  	ProxyUtil.getMethod(OutriggerServer.class, "write",
75  			    new Class[] {EntryRep.class,
76  					 Transaction.class,
77  					 long.class}),
78  
79  
80  	ProxyUtil.getMethod(JavaSpace.class, "read", 
81  			    new Class[] {Entry.class,
82  					 Transaction.class,
83  					 long.class}),
84  	ProxyUtil.getMethod(OutriggerServer.class, "read",
85  			    new Class[] {EntryRep.class,
86  					 Transaction.class,
87  					 long.class,
88  					 OutriggerServer.QueryCookie.class}),
89  
90  
91  	ProxyUtil.getMethod(JavaSpace.class, "take", 
92  			    new Class[] {Entry.class,
93  					 Transaction.class,
94  					 long.class}),
95  	ProxyUtil.getMethod(OutriggerServer.class, "take",
96  			    new Class[] {EntryRep.class,
97  					 Transaction.class,
98  					 long.class,
99  					 OutriggerServer.QueryCookie.class}),
100 
101 
102 	ProxyUtil.getMethod(JavaSpace.class, "readIfExists", 
103 			    new Class[] {Entry.class,
104 					 Transaction.class,
105 					 long.class}),
106 	ProxyUtil.getMethod(OutriggerServer.class, "readIfExists",
107 			    new Class[] {EntryRep.class,
108 					 Transaction.class,
109 					 long.class,
110 					 OutriggerServer.QueryCookie.class}),
111 
112 
113 	ProxyUtil.getMethod(JavaSpace.class, "takeIfExists", 
114 			    new Class[] {Entry.class,
115 					 Transaction.class,
116 					 long.class}),
117 	ProxyUtil.getMethod(OutriggerServer.class, "takeIfExists",
118 			    new Class[] {EntryRep.class,
119 					 Transaction.class,
120 					 long.class,
121 					 OutriggerServer.QueryCookie.class}),
122 
123 
124 	ProxyUtil.getMethod(JavaSpace.class, "notify", 
125 			    new Class[] {Entry.class,
126 					 Transaction.class,
127 					 RemoteEventListener.class,
128 					 long.class,
129 					 MarshalledObject.class}),
130 	ProxyUtil.getMethod(OutriggerServer.class, "notify",
131 			    new Class[] {EntryRep.class,
132 					 Transaction.class,
133 					 RemoteEventListener.class,
134 					 long.class,
135 					 MarshalledInstance.class}),
136 
137 	ProxyUtil.getMethod(JavaSpace05.class, "contents", 
138 			    new Class[] {Collection.class,
139 					 Transaction.class,
140 					 long.class,
141 					 long.class}), 
142 	ProxyUtil.getMethod(OutriggerServer.class, "contents",
143 			    new Class[] {EntryRep[].class,
144 					 Transaction.class,
145 					 long.class,
146 					 long.class}), 
147 
148 
149 	// Use the same constants for nextBatch as contents
150 	ProxyUtil.getMethod(JavaSpace05.class, "contents", 
151 			    new Class[] {Collection.class,
152 					 Transaction.class,
153 					 long.class,
154 					 long.class}), 
155 	ProxyUtil.getMethod(OutriggerServer.class, "nextBatch",
156 			    new Class[] {Uuid.class,
157 					 Uuid.class}) 
158     };//end methodMapArray
159 
160     /** 
161      * Client constraints placed on this proxy (may be <code>null</code> 
162      * @serial
163      */
164     private final MethodConstraints methodConstraints;
165     
166     /**
167      * Create a new <code>ConstrainableSpaceProxy2</code>.
168      * @param space The <code>OutriggerServer</code> for the 
169      *              space.
170      * @param spaceUuid The universally unique ID for the
171      *              space
172      * @param serverMaxServerQueryTimeout The value this proxy
173      *              should use for the <code>maxServerQueryTimeout</code>
174      *              if no local value is provided.
175      * @param methodConstraints the client method constraints to place on
176      *                          this proxy (may be <code>null</code>).
177      * @throws NullPointerException if <code>space</code> or
178      *         <code>spaceUuid</code> is <code>null</code>.
179      * @throws IllegalArgumentException if 
180      *         <code>serverMaxServerQueryTimeout</code> is not
181      *         larger than zero.     
182      * @throws ClassCastException if <code>server</code>
183      *         does not implement <code>RemoteMethodControl</code>.
184      */
185     public ConstrainableSpaceProxy2(OutriggerServer space, Uuid spaceUuid, 
186 			    long serverMaxServerQueryTimeout, 
187 			    MethodConstraints methodConstraints)
188     {
189 	super(constrainServer(space, methodConstraints),
190 	      spaceUuid, serverMaxServerQueryTimeout);
191 	this.methodConstraints = methodConstraints;
192     }
193 
194     ConstrainableSpaceProxy2(GetArg arg) throws IOException{
195 	this(arg, check(arg));
196     }
197     
198     ConstrainableSpaceProxy2(GetArg arg, MethodConstraints constraints) throws IOException{
199 	super(arg);
200 	methodConstraints = constraints;
201     }
202     
203     private static MethodConstraints check(GetArg arg) throws IOException {
204 	SpaceProxy2 sp2 = new SpaceProxy2(arg);
205 	MethodConstraints methodConstraints = (MethodConstraints) 
206 		arg.get("methodConstraints", null);
207 	MethodConstraints proxyCon = null;
208 	if (sp2.space instanceof RemoteMethodControl && 
209 	    (proxyCon = ((RemoteMethodControl)sp2.space).getConstraints()) != null) {
210 	    // Constraints set during proxy deserialization.
211 	    return ConstrainableProxyUtil.reverseTranslateConstraints(
212 		    proxyCon, methodMapArray);
213 	}
214 	/* Basic validation of space, spaceUuid, and 
215 	 * serverMaxServerQueryTimeout was performed by
216 	 * SpaceProxy2.readObject(), we just need to verify than
217 	 * space implements RemoteMethodControl and that it has
218 	 * appropriate constraints. 
219 	 */
220 	ConstrainableProxyUtil.verifyConsistentConstraints(
221 	    methodConstraints, sp2.space, methodMapArray);
222 	return methodConstraints;
223     }
224 
225     /**
226      * Returns a copy of the given <code>OutriggerServer</code> proxy
227      * having the client method constraints that result after
228      * mapping defined by methodMapArray is applied.
229      * @param server The proxy to attach constrains too.
230      * @param constraints The source method constraints.
231      * @throws NullPointerException if <code>server</code> is 
232      *         <code>null</code>.
233      * @throws ClassCastException if <code>server</code>
234      *         does not implement <code>RemoteMethodControl</code>.
235      */
236     private static OutriggerServer constrainServer(OutriggerServer server,
237         MethodConstraints constraints)
238     {
239 	final MethodConstraints serverRefConstraints 
240 	    = ConstrainableProxyUtil.translateConstraints(constraints,
241 							  methodMapArray);
242 	final RemoteMethodControl constrainedServer = 
243 	    ((RemoteMethodControl)server).
244 	    setConstraints(serverRefConstraints);
245 
246 	return (OutriggerServer)constrainedServer;
247     }
248 
249     public RemoteMethodControl setConstraints(MethodConstraints constraints)
250     {
251 	return new ConstrainableSpaceProxy2(space, spaceUuid, 
252 					   serverMaxServerQueryTimeout,
253 					   constraints);
254     }
255 
256     public MethodConstraints getConstraints() {
257 	return methodConstraints;
258     }
259 
260     /** 
261      * Returns a proxy trust iterator that is used in 
262      * <code>ProxyTrustVerifier</code> to retrieve this object's
263      * trust verifier.
264      */
265     private ProxyTrustIterator getProxyTrustIterator() {
266 	return new SingletonProxyTrustIterator(space);
267     }
268 
269     private void readObject(ObjectInputStream s)  
270 	throws IOException, ClassNotFoundException
271     {
272 	s.defaultReadObject();
273 
274 	/* Basic validation of space, spaceUuid, and 
275 	 * serverMaxServerQueryTimeout was performed by
276 	 * SpaceProxy2.readObject(), we just need to verify than
277 	 * space implements RemoteMethodControl and that it has
278 	 * appropriate constraints. 
279 	 */
280 	ConstrainableProxyUtil.verifyConsistentConstraints(
281 	    methodConstraints, space, methodMapArray);
282     }
283 
284     protected Lease constructLease(Uuid uuid, long expiration) {
285 	return new ConstrainableLandlordLease(uuid, space, spaceUuid,
286 					      expiration, null);
287     }
288 }
289