org.apache.river.phoenix.SystemAccessAtomicILFactory Maven / Gradle / Ivy
/*
* Copyright 2018 peter.
*
* Licensed 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 org.apache.river.phoenix;
import java.lang.reflect.Method;
import java.rmi.Remote;
import java.rmi.activation.ActivationGroupDesc;
import java.rmi.activation.ActivationSystem;
import java.rmi.server.ExportException;
import java.util.Collection;
import net.jini.core.constraint.InvocationConstraints;
import net.jini.core.constraint.MethodConstraints;
import net.jini.jeri.AtomicILFactory;
import net.jini.jeri.AtomicInvocationDispatcher;
import net.jini.jeri.InvocationDispatcher;
import net.jini.jeri.ServerCapabilities;
import org.apache.river.phoenix.common.LocalAccess;
/**
* Invocation layer factory for exporting an {@link ActivationSystem}
* to use Jini extensible remote invocation (Jini ERI), that is similar
* to {@link AtomicILFactory} except the remote object must be an
* ActivationSystem
instance and the returned dispatcher
* optionally accepts calls from the local host and optionally enforces a
* {@link GroupPolicy} on calls to {@link ActivationSystem#registerGroup
* registerGroup} and {@link ActivationSystem#setActivationGroupDesc
* setActivationGroupDesc}.
*
* @author Peter.
*
* @since 3.1
**/
public class SystemAccessAtomicILFactory extends AtomicILFactory{
/**
* The group policy, if any.
*/
private final GroupPolicy policy;
/**
* If true, check that client is calling from the local host.
*/
private final boolean localAccessCheck;
/**
* Creates an invocation layer factory that creates an invocation
* dispatcher with the specified group policy and the specified class
* loader. This invocation dispatcher only accepts calls from the
* local host and enforces the specified group policy (if
* non-null
) on calls to {@link
* ActivationSystem#registerGroup registerGroup} and {@link
* ActivationSystem#setActivationGroupDesc setActivationGroupDesc}.
*
* @param loader the class loader, or null
* @param policy the group policy, or null
**/
public SystemAccessAtomicILFactory(GroupPolicy policy, ClassLoader loader) {
super(null, null, loader);
this.policy = policy;
this.localAccessCheck = true;
}
public SystemAccessAtomicILFactory(GroupPolicy policy, Class proxyOrService) {
super(null, null, proxyOrService.getClassLoader());
this.policy = policy;
this.localAccessCheck = true;
}
/**
* Creates a factory with the specified server constraints, permission
* class, group policy, and class loader. This factory creates an
* invocation dispatcher that enforces the specified group policy (if
* non-null
) on calls to {@link
* ActivationSystem#registerGroup registerGroup} and {@link
* ActivationSystem#setActivationGroupDesc setActivationGroupDesc}.
*
* @param serverConstraints the server constraints, or null
* @param permClass the permission class, or null
* @param policy the group policy, or null
* @param loader the class loader, or null
* @throws IllegalArgumentException if the permission class is abstract, is
* not a subclass of {@link java.security.Permission}, or does not have
* a public constructor that has either one String
parameter
* or one {@link Method} parameter and has no declared exceptions
**/
public SystemAccessAtomicILFactory(MethodConstraints serverConstraints,
Class permClass,
GroupPolicy policy,
ClassLoader loader)
{
super(serverConstraints, permClass, loader);
this.policy = policy;
this.localAccessCheck = false;
}
/**
* Creates a factory with the specified server constraints, permission
* class, group policy, and proxy or service implementation class.
* This factory creates an
* invocation dispatcher that enforces the specified group policy (if
* non-null
) on calls to {@link
* ActivationSystem#registerGroup registerGroup} and {@link
* ActivationSystem#setActivationGroupDesc setActivationGroupDesc}.
*
* @param serverConstraints the server constraints, or null
* @param permClass the permission class, or null
* @param policy the group policy, or null
* @param proxyOrService the proxy or service implementation class.
* @throws IllegalArgumentException if the permission class is abstract, is
* not a subclass of {@link java.security.Permission}, or does not have
* a public constructor that has either one String
parameter
* or one {@link Method} parameter and has no declared exceptions
* @throws NullPointerException if proxyOrService class is null.
**/
public SystemAccessAtomicILFactory(MethodConstraints serverConstraints,
Class permClass,
GroupPolicy policy,
Class proxyOrService)
{
this(serverConstraints, permClass, policy, proxyOrService.getClassLoader());
}
/**
* Returns a {@link SystemAccessILFactory.SystemDispatcher} instance constructed with the
* specified methods, the class loader specified during construction,
* the remote object, server capabilities, and the server constraints,
* permission class, and group policy that this factory was constructed
* with and a flag indicating whether the dispatcher should only accept
* calls from the local host.
*
* @return a {@link SystemDispatcher} instance constructed with the
* specified methods, remote object, and server capabilities, and the
* server constraints, permission class, group policy, local host access
* check condition, and class loader that this factory was constructed
* with
* @throws java.rmi.server.ExportException
* @throws NullPointerException {@inheritDoc}
**/
@Override
protected InvocationDispatcher
createInvocationDispatcher(Collection methods,
Remote impl,
ServerCapabilities caps)
throws ExportException
{
if (impl == null) {
throw new NullPointerException("impl cannot be null");
} else if (!(impl instanceof ActivationSystem)) {
throw new ExportException("cannot create dispatcher",
new IllegalArgumentException(
"impl must be an ActivationSystem"));
}
return new SystemDispatcher(methods, impl, caps,
getServerConstraints(),
getPermissionClass(), policy,
localAccessCheck, getClassLoader());
}
/**
* A subclass of {@link AtomicInvocationDispatcher} for
* ActivationSystem
instances that optionally enforces a
* {@link GroupPolicy} on calls to registerGroup
and
* setActivationGroupDesc
.
*/
public static class SystemDispatcher extends AtomicInvocationDispatcher {
/**
* The group policy, if any.
*/
private final GroupPolicy policy;
/**
* If true, check that client is calling from the local host.
*/
private final boolean localAccessCheck;
/**
* Creates an invocation dispatcher to receive incoming remote calls
* for the specified methods, for a server and transport with the
* specified capabilities, enforcing the specified constraints, and
* performing preinvocation access control using the specified
* permission class and group policy. The specified class loader
* is used by the {@link #createMarshalInputStream
* createMarshalInputStream} method.
*
* For each combination of constraints that might need to be
* enforced (obtained by calling the {@link
* MethodConstraints#possibleConstraints possibleConstraints}
* method on the specified server constraints, or using an empty
* constraints instance of the specified server constraints
* instance is null
), calling the {@link
* ServerCapabilities#checkConstraints checkConstraints}
* method of the specified capabilities object with those
* constraints must return true
, or an
* ExportException
is thrown.
*
* @param methods a collection of {@link Method} instances for the
* remote methods
* @param impl the remote object
* @param serverCaps the transport capabilities of the server
* @param serverConstraints the server constraints, or
* null
* @param permClass the permission class, or null
* @param policy the group policy, or null
* @param localAccessCheck if true
, calls are only
* accepted from the local host
* @param loader the class loader, or null
* @throws IllegalArgumentException if impl
is not an
* instance of {@link ActivationSystem} or if the permission class is
* abstract, is not a subclass of {@link java.security.Permission},
* or does not have a public constructor that has either one
* String
parameter or one {@link Method} parameter and
* has no declared exceptions, or if any element of
* methods
is not a {@link Method} instance
* @throws NullPointerException if impl
,
* methods
or serverCaps
is
* null
, or if methods
contains a
* null
element
* @throws ExportException if any of the possible server constraints
* cannot be satisfied according to the specified server capabilities
**/
public SystemDispatcher(Collection methods,
Remote impl,
ServerCapabilities serverCaps,
MethodConstraints serverConstraints,
Class permClass,
GroupPolicy policy,
boolean localAccessCheck,
ClassLoader loader)
throws ExportException
{
super(methods, serverCaps, serverConstraints, permClass, loader, false);
if (impl == null) {
throw new NullPointerException("impl is null");
}
if (!(impl instanceof ActivationSystem)) {
throw new IllegalArgumentException(
"impl not an ActivationSystem instance");
}
this.policy = policy;
this.localAccessCheck = localAccessCheck;
}
/**
* Checks that the client is calling from the local host.
*
* @throws java.security.AccessControlException if the client is not
* calling from the local host
*/
protected void checkAccess(Remote impl,
Method method,
InvocationConstraints constraints,
Collection context)
{
if (localAccessCheck) {
LocalAccess.check();
} else {
super.checkAccess(impl, method, constraints, context);
}
}
/**
* Checks the group policy as necessary, and then calls the superclass
* invoke
method with the same arguments, and returns
* the result. If the policy is not null
and the
* specified method is ActivationSystem.registerGroup
or
* ActivationSystem.setActivationGroupDesc
, the policy
* is checked by calling its {@link GroupPolicy#checkGroup checkGroup}
* method with the ActivationGroupDesc
argument.
*
* @throws SecurityException if the caller is not permitted to use
* the specified group descriptor
*/
protected Object invoke(Remote impl,
Method method,
Object[] args,
Collection context)
throws Throwable
{
if (policy != null) {
String op = method.getName();
if (op.equals("registerGroup") ||
op.equals("setActivationGroupDesc"))
{
policy.checkGroup(
(ActivationGroupDesc) args[args.length - 1]);
}
}
return super.invoke(impl, method, args, context);
}
}
}