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