/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.jini.jeri;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.Permission;
import java.rmi.Remote;
import java.rmi.server.ExportException;
import java.security.Permission;
import java.util.Collection;
import net.jini.core.constraint.MethodConstraints;
import net.jini.core.constraint.RemoteMethodControl;
import net.jini.security.proxytrust.TrustEquivalence;
/**
* A basic implementation of an {@link InvocationLayerFactory}. This
* factory is used to create a {@link Proxy} instance with a {@link
* BasicInvocationHandler} and to create a {@link
* BasicInvocationDispatcher} for a remote object being exported. This
* factory is used in conjunction with the {@link BasicJeriExporter} class.
*
* @author Sun Microsystems, Inc.
* @since 2.0
**/
public class BasicILFactory extends AbstractILFactory {
/**
* The server constraints, or null;
*/
private final MethodConstraints serverConstraints;
/**
* The permission class, or null.
*/
private final Class permissionClass;
/**
* Creates a <code>BasicILFactory</code> instance with no server
* constraints, no permission class, and a <code>null</code> class
* loader.
**/
public BasicILFactory() {
this.serverConstraints = null;
this.permissionClass = null;
}
/**
* Creates a <code>BasicILFactory</code> with the specified server
* constraints, permission class, and a <code>null</code> class
* loader.
*
* @param serverConstraints the server constraints, or <code>null</code>
* @param permissionClass the permission class, or <code>null</code>
* @throws IllegalArgumentException if the permission class is
* abstract, is not a subclass of {@link Permission}, or does
* not have a public constructor that has either one
* <code>String</code> parameter or one {@link Method}
* parameter and has no declared exceptions
**/
public BasicILFactory(MethodConstraints serverConstraints,
Class permissionClass)
{
this(serverConstraints, permissionClass, null);
}
/**
* Creates a <code>BasicILFactory</code> with the specified server
* constraints, permission class, and class loader. The server
* constraints, if not <code>null</code>, are used to enforce minimum
* constraints for remote calls. The permission class, if not
* <code>null</code>, is used to perform server-side access control on
* incoming remote calls. The class loader, which may be
* <code>null</code>, is passed to the superclass constructor and is
* used by the {@link #createInstances createInstances}
* method.
*
* @param serverConstraints the server constraints, or <code>null</code>
* @param permissionClass the permission class, or <code>null</code>
* @param loader the class loader, or <code>null</code>
* @throws IllegalArgumentException if the permission class is
* abstract, is not a subclass of {@link Permission}, or does
* not have a public constructor that has either one
* <code>String</code> parameter or one {@link Method}
* parameter and has no declared exceptions
**/
public BasicILFactory(MethodConstraints serverConstraints,
Class permissionClass,
ClassLoader loader)
{
super(loader);
BasicInvocationDispatcher.checkPermissionClass(permissionClass);
this.serverConstraints = serverConstraints;
this.permissionClass = permissionClass;
}
/**
* Returns an invocation handler to use with a {@link Proxy} instance
* implementing the specified interfaces, communicating with the
* specified remote object using the specified object endpoint.
*
* <p><code>BasicILFactory</code> implements this method to
* return a {@link BasicInvocationHandler} constructed with the
* specified object endpoint and this factory's server constraints.
*
* @throws NullPointerException {@inheritDoc}
**/
protected InvocationHandler createInvocationHandler(Class[] interfaces,
Remote impl,
ObjectEndpoint oe)
throws ExportException
{
for (int i = interfaces.length; --i >= 0; ) {
if (interfaces[i] == null) {
throw new NullPointerException();
}
}
if (impl == null) {
throw new NullPointerException();
}
return new BasicInvocationHandler(oe, serverConstraints);
}
/**
* Returns a new array containing any additional interfaces that the
* proxy should implement, beyond the interfaces obtained by passing
* <code>impl</code> to the {@link #getRemoteInterfaces
* getRemoteInterfaces} method.
*
* <p><code>BasicILFactory</code> implements this method to return a
* new array containing the {@link RemoteMethodControl} and {@link
* TrustEquivalence} interfaces, in that order.
*
* @throws NullPointerException {@inheritDoc}
**/
protected Class[] getExtraProxyInterfaces(Remote impl) {
if (impl == null) {
throw new NullPointerException();
}
return new Class[]{RemoteMethodControl.class, TrustEquivalence.class};
}
/**
* Returns an invocation dispatcher to receive incoming remote calls
* for the specified methods to the specified remote object, for a
* server and transport with the specified capabilities.
*
* <p><code>BasicILFactory</code> implements this method to return a
* {@link BasicInvocationDispatcher} instance constructed with the
* specified methods, server capabilities, and this factory's
* server constraints, permission class, and class loader specified
* at construction.
*
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
**/
protected InvocationDispatcher
createInvocationDispatcher(Collection methods,
Remote impl,
ServerCapabilities caps)
throws ExportException
{
if (impl == null) {
throw new NullPointerException("impl is null");
}
return new BasicInvocationDispatcher(methods, caps,
serverConstraints,
permissionClass,
getClassLoader());
}
/**
* Returns the server constraints, if any.
*
* @return the server constraints, or <code>null</code>
**/
public final MethodConstraints getServerConstraints() {
return serverConstraints;
}
/**
* Returns the permission class, if any.
*
* @return the permission class, or <code>null</code>
*/
public final Class getPermissionClass() {
return permissionClass;
}
/**
* Returns a hash code value for this factory.
**/
public int hashCode() {
int h = super.hashCode();
if (serverConstraints != null) {
h += serverConstraints.hashCode();
}
if (permissionClass != null) {
h += permissionClass.hashCode();
}
return h;
}
/**
* Compares the specified object with this invocation layer factory for
* equality.
*
* <p><code>BasicILFactory</code> implements this method to return
* <code>true</code> if and only if invoking the superclass's
* <code>equals</code> method passing the specified object returns
* <code>true</code>, the specified object has the same class as this
* object, and the server constraints and permission class are equal to
* the ones in this object.
**/
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
BasicILFactory ilf = (BasicILFactory) obj;
return (permissionClass == ilf.permissionClass &&
(serverConstraints == ilf.serverConstraints ||
(serverConstraints != null &&
serverConstraints.equals(ilf.serverConstraints))));
}
/**
* Returns a string representation of this factory.
**/
public String toString() {
return (super.toString() + "[" + serverConstraints +
(permissionClass != null ?
", " + permissionClass.getName() :
"") + "]");
}
}