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  
19  package org.apache.river.phoenix.dl;
20  
21  import java.io.IOException;
22  import java.io.InvalidObjectException;
23  import java.io.Serializable;
24  import java.lang.reflect.Method;
25  import java.rmi.RemoteException;
26  import java.rmi.activation.ActivationID;
27  import java.rmi.server.UID;
28  import net.jini.core.constraint.MethodConstraints;
29  import net.jini.core.constraint.RemoteMethodControl;
30  import net.jini.export.ProxyAccessor;
31  import net.jini.security.TrustVerifier;
32  import net.jini.security.proxytrust.ProxyTrustIterator;
33  import net.jini.security.proxytrust.SingletonProxyTrustIterator;
34  import net.jini.security.proxytrust.TrustEquivalence;
35  import org.apache.river.api.io.AtomicSerial;
36  import org.apache.river.api.io.AtomicSerial.GetArg;
37  import org.apache.river.proxy.ConstrainableProxyUtil;
38  
39  /**
40   * A subclass of <code>AID</code> that implements the {@link
41   * RemoteMethodControl} interface by delegating to the contained activator.
42   * 
43   * <p>This class exists as a convenience for activation system daemon
44   * implementations supporting <code>RemoteMethodControl</code> on proxies,
45   * to avoid requiring all such implementations to make code available for
46   * dynamic download to clients.
47   *
48   * @author Sun Microsystems, Inc.
49   * 
50   * @since 2.0
51   **/
52  public final class ConstrainableAID extends AID
53  	implements RemoteMethodControl, TrustEquivalence
54  {
55      private static final long serialVersionUID = 2625527831091986783L;
56      private static final Method[] methodMapping = new Method[2];
57  
58      static {
59  	try {
60  	    methodMapping[0] =
61  		ActivationID.class.getMethod("activate",
62  					     new Class[]{boolean.class});
63  	    methodMapping[1] =
64  		Activator.class.getMethod("activate",
65  					  new Class[]{ActivationID.class,
66  						      boolean.class});
67  	} catch (NoSuchMethodException e) {
68  	    throw new AssertionError(e);
69  	}
70      }
71  
72      /** the client constraints */
73      private final MethodConstraints constraints;
74  
75      @AtomicSerial
76      static final class State implements Serializable, ProxyAccessor {
77  	private static final long serialVersionUID = 1673734348880788487L;
78  	private final Activator activator;
79  	private final UID uid;
80  	private final MethodConstraints constraints;
81  
82  	State(Activator activator, UID uid, MethodConstraints constraints) {
83  	    this.activator = activator;
84  	    this.uid = uid;
85  	    this.constraints = constraints;
86  	}
87  	
88  	public State(GetArg arg) throws IOException{
89  	    this(validate(arg),
90  		 arg.get("uid", null, UID.class),
91  		 arg.get("constraints", null, MethodConstraints.class));
92  	}
93  	
94  	private static Activator validate(GetArg arg) throws IOException{
95  	    Activator activator = arg.get("activator", null, Activator.class);
96  	    ConstrainableProxyUtil.verifyConsistentConstraints(
97  		    arg.get("constraints", null, MethodConstraints.class),
98  		    activator, 
99  		    methodMapping);
100 	    return activator;
101 	}
102 
103 	private Object readResolve() throws InvalidObjectException {
104 	    return new ConstrainableAID(activator, uid, constraints);
105 	}
106 
107 	public Object getProxy() {
108 	    return activator;
109 	}
110     }
111 
112     /**
113      * A <code>ProxyTrust</code> trust verifier for
114      * <code>ConstrainableAID</code> instances.
115      *
116      * @since 2.0
117      **/
118     @AtomicSerial
119     public static final class Verifier implements TrustVerifier, Serializable {
120 	private static final long serialVersionUID = 570158651966790233L;
121 
122 	/**
123 	 * The expected activator.
124 	 *
125 	 * @serial
126 	 */
127 	private final RemoteMethodControl activator;
128 
129 	/**
130 	 * Creates a verifier for the specified activator.
131 	 *
132 	 * @param activator the activator
133 	 * @throws IllegalArgumentException if the specified activator is
134 	 * not an instance of <code>RemoteMethodControl</code> or
135 	 * <code>TrustEquivalence</code>
136 	 */
137 	public Verifier(Activator activator) {
138 	    if (!(activator instanceof RemoteMethodControl)) {
139 		throw new IllegalArgumentException(
140 		    "activator not a RemoteMethodControl instance");
141 	    } else if (!(activator instanceof TrustEquivalence)) {
142 		throw new IllegalArgumentException(
143 				"activator must implement TrustEquivalence");
144 	    }
145 	    this.activator = (RemoteMethodControl) activator;
146 	}
147 	
148 	private Verifier(RemoteMethodControl activator){
149 	    this.activator = activator;
150 	}
151 	
152 	Verifier(GetArg arg) throws IOException{
153 	    this(validate(arg.get("activator", null, RemoteMethodControl.class)));
154 	}
155 	
156 	private static RemoteMethodControl validate(RemoteMethodControl activator) throws InvalidObjectException{
157 	    if (!(activator instanceof TrustEquivalence)) {
158 		throw new InvalidObjectException(
159 				"activator must implement TrustEquivalence");
160 	    }
161 	    return activator;
162 	}
163 
164 	/**
165 	 * Verifies trust in a proxy. Returns <code>true</code> if the
166 	 * proxy passed as an argument is an instance of
167 	 * <code>ConstrainableAID</code> and that proxy's internal
168 	 * activator instance is trust equivalent to the activator of this
169 	 * verifier; returns <code>false</code> otherwise.
170 	 **/
171 	public boolean isTrustedObject(Object obj, TrustVerifier.Context ctx)
172 	    throws RemoteException
173 	{
174 	    if (obj == null || ctx == null) {
175 		throw new NullPointerException();
176 	    } else if (!(obj instanceof ConstrainableAID)) {
177 		return false;
178 	    }
179 	    RemoteMethodControl act =
180 		(RemoteMethodControl) ((ConstrainableAID) obj).activator;
181 	    MethodConstraints mc = act.getConstraints();
182 	    TrustEquivalence trusted =
183 		(TrustEquivalence) activator.setConstraints(mc);
184 	    return trusted.checkTrustEquivalence(act);
185 	}
186     }
187 
188     /**
189      * Creates an activation identifier containing the specified
190      * remote object activator, a new unique identifier, and
191      * <code>null</code> client constraints.
192      *
193      * @param activator the activator
194      * @param uid the unique identifier
195      * @throws IllegalArgumentException if the specified activator is not
196      * an instance of <code>RemoteMethodControl</code> or
197      * <code>TrustEquivalence</code>
198      */
199     public ConstrainableAID(Activator activator, UID uid) {
200 	this(activator, uid, null);
201     }
202 
203     /**
204      * Creates an activation identifier containing the specified
205      * remote object activator and a new unique identifier.
206      *
207      * @param activator the activator
208      * @param uid the unique identifier
209      * @param constraints the client constraints, or <code>null</code>
210      * @throws IllegalArgumentException if the specified activator is not
211      * an instance of <code>RemoteMethodControl</code> or
212      * <code>TrustEquivalence</code>
213      */
214     private ConstrainableAID(Activator activator,
215 			     UID uid,
216 			     MethodConstraints constraints)
217     {
218 	super(check(activator), uid);
219 	this.constraints = constraints;
220     }
221     
222     private static Activator check(Activator activator)
223     {
224 	if (!(activator instanceof RemoteMethodControl)) {
225 	    throw new IllegalArgumentException(
226 		"activator not RemoteMethodControl instance");
227 	} else if (!(activator instanceof TrustEquivalence)) {
228 	    throw new IllegalArgumentException(
229 		"activator not TrustEquivalence instance");
230 	}
231 	return activator;
232     }
233 
234     /** Returns an iterator that yields the activator. */
235     private ProxyTrustIterator getProxyTrustIterator() {
236 	return new SingletonProxyTrustIterator(activator);
237     }
238 
239     /**
240      * Returns a new copy of this activation identifier containing the same
241      * unique identifier and a copy of the activator with the new specified
242      * constraints.
243      *
244      * @param constraints the client constraints, or <code>null</code>
245      * @return a new copy of this activation identifier containing the same
246      * unique identifier and a copy of the activator with the new specified
247      * client constraints
248      * @see #getConstraints
249      */
250     public RemoteMethodControl setConstraints(MethodConstraints constraints) {
251 	MethodConstraints actConstraints =
252 	    ConstrainableProxyUtil.translateConstraints(constraints,
253 							methodMapping);
254 	RemoteMethodControl act =
255 	    ((RemoteMethodControl) activator).setConstraints(actConstraints);
256 	return new ConstrainableAID((Activator) act, uid, constraints);
257     }
258 
259     /**
260      * Returns the client constraints.
261      *
262      * @return the client constraints, or <code>null</code>
263      * @see #setConstraints
264      */
265     public MethodConstraints getConstraints() {
266 	return constraints;
267     }
268 
269     /**
270      * Returns true if the object is an instance of this class with the same
271      * UID and a trust equivalent activator.
272      */
273     public boolean checkTrustEquivalence(Object obj) {
274 	if (!(obj instanceof ConstrainableAID)) {
275 	    return false;
276 	}
277 	ConstrainableAID aid = (ConstrainableAID) obj;
278 	return (uid.equals(aid.uid) &&
279 		((TrustEquivalence) activator).checkTrustEquivalence(
280 							   aid.activator));
281     }
282 
283     private Object writeReplace() {
284 	return new State(activator, uid, constraints);
285     }
286 
287 }