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.group;
20
21 import java.rmi.MarshalledObject;
22 import java.rmi.Remote;
23 import java.rmi.RemoteException;
24 import java.rmi.activation.ActivationDesc;
25 import java.rmi.activation.ActivationException;
26 import java.rmi.activation.ActivationID;
27 import java.rmi.activation.ActivationInstantiator;
28 import java.rmi.server.ExportException;
29 import net.jini.export.Exporter;
30 import net.jini.jrmp.JrmpExporter;
31 import org.apache.river.phoenix.common.LocalAccess;
32
33 /**
34 * Exporter that wraps an <code>ActivationInstantiator</code> instance so that
35 * it only accepts calls from the local host.
36 *
37 * @author Sun Microsystems, Inc.
38 *
39 * @since 2.0
40 */
41 public class InstantiatorAccessExporter implements Exporter {
42 /**
43 * The underlying exporter.
44 */
45 private final Exporter exporter;
46 /**
47 * The wrapped impl.
48 */
49 private Remote wrapped;
50
51 /**
52 * Creates an exporter with an underlying {@link JrmpExporter} that
53 * exports on an anonymous port.
54 */
55 public InstantiatorAccessExporter() {
56 this.exporter = new JrmpExporter();
57 }
58
59 /**
60 * Creates an exporter with the specified underlying exporter.
61 *
62 * @param exporter the underlying exporter
63 */
64 public InstantiatorAccessExporter(Exporter exporter) {
65 this.exporter = exporter;
66 }
67
68 /**
69 * Wraps the specified remote object in an
70 * <code>ActivationInstantiator</code> implementation that only accepts
71 * calls from the local host before delegating to the specified remote
72 * object, exports the wrapper with the underlying exporter, and returns
73 * the resulting proxy. The wrapper is strongly referenced by this
74 * exporter. For the <code>newInstance</code> method, the wrapper throws an
75 * <code>AccessControlException</code> if the client is not calling from
76 * the local host.
77 *
78 * @throws IllegalArgumentException if <code>impl</code> does not
79 * implement <code>ActivationInstantiator</code>
80 * @throws NullPointerException {@inheritDoc}
81 * @throws IllegalStateException {@inheritDoc}
82 */
83 public Remote export(Remote impl) throws ExportException {
84 if (!(impl instanceof ActivationInstantiator)) {
85 throw new IllegalArgumentException(
86 "not an ActivationInstantiator");
87 }
88 Remote wrapped = new InstantiatorImpl((ActivationInstantiator) impl);
89 Remote proxy = exporter.export(wrapped);
90 this.wrapped = wrapped;
91 return proxy;
92 }
93
94 /**
95 * @throws IllegalStateException {@inheritDoc}
96 */
97 public boolean unexport(boolean force) {
98 return exporter.unexport(force);
99 }
100
101 private static class InstantiatorImpl extends AbstractInstantiator {
102 private final ActivationInstantiator impl;
103
104 InstantiatorImpl(ActivationInstantiator impl) {
105 this.impl = impl;
106 }
107
108 public MarshalledObject newInstance(ActivationID id,
109 ActivationDesc desc)
110 throws ActivationException, RemoteException
111 {
112 LocalAccess.check();
113 return impl.newInstance(id, desc);
114 }
115 }
116 }