/*
* Copyright to the original author or authors.
*
* 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.rioproject.cybernode.proxy;
import com.sun.jini.proxy.ConstrainableProxyUtil;
import net.jini.core.constraint.MethodConstraints;
import net.jini.core.constraint.RemoteMethodControl;
import net.jini.core.event.UnknownEventException;
import net.jini.id.Uuid;
import net.jini.security.TrustVerifier;
import net.jini.security.proxytrust.ProxyTrustIterator;
import net.jini.security.proxytrust.SingletonProxyTrustIterator;
import net.jini.security.proxytrust.TrustEquivalence;
import org.rioproject.cybernode.Cybernode;
import org.rioproject.deploy.*;
import org.rioproject.opstring.OperationalStringManager;
import org.rioproject.opstring.ServiceElement;
import org.rioproject.proxy.service.AbstractProxy;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.InetAddress;
import java.rmi.RemoteException;
/**
* A <code>CybernodeProxy</code> is a proxy for the Cybernode server. This is
* the object passed to clients of the Cybernode.
*
* @author Dennis Reedy
*/
public class CybernodeProxy extends AbstractProxy implements Cybernode, Serializable {
private static final long serialVersionUID = 2L;
private String name;
final Cybernode cybernodeProxy;
/**
* Creates a Cybernode proxy, returning an instance that implements
* RemoteMethodControl if the server does too.
*
* @param cybernode The Cybernode server
* @param id The Uuid of the Cybernode
*
* @return A CybernodeProxy
*/
public static CybernodeProxy getInstance(final Cybernode cybernode, final Uuid id) {
if(cybernode instanceof RemoteMethodControl) {
return new ConstrainableCybernodeProxy(cybernode, id, null);
} else {
return (new CybernodeProxy(cybernode, id));
}
}
/*
* Private constructor
*/
private CybernodeProxy(final Cybernode cybernode, final Uuid id) {
super(cybernode, id);
cybernodeProxy = cybernode;
}
/* -------- Implement Cybernode methods -------- */
/** @see Cybernode#enlist() */
public void enlist() throws RemoteException {
cybernodeProxy.enlist();
}
/** @see Cybernode#release(boolean) */
public void release(final boolean terminateServices) throws RemoteException {
cybernodeProxy.release(terminateServices);
}
public boolean isEnlisted() throws RemoteException {
return cybernodeProxy.isEnlisted();
}
/* -------- Implement ServiceBeanInstantiator methods -------- */
/** @see org.rioproject.deploy.ServiceBeanInstantiator#instantiate */
public DeployedService instantiate(final ServiceProvisionEvent event)
throws ServiceBeanInstantiationException, UnknownEventException, RemoteException {
return (cybernodeProxy.instantiate(event));
}
/** @see org.rioproject.deploy.ServiceBeanInstantiator#getServiceStatements */
public ServiceStatement[] getServiceStatements() throws RemoteException {
return (cybernodeProxy.getServiceStatements());
}
/** @see org.rioproject.deploy.ServiceBeanInstantiator#getServiceRecords */
public ServiceRecord[] getServiceRecords(final int filter) throws RemoteException {
return (cybernodeProxy.getServiceRecords(filter));
}
/** @see org.rioproject.deploy.ServiceBeanInstantiator#getServiceStatement */
public ServiceStatement getServiceStatement(final ServiceElement elem) throws RemoteException {
if(elem == null)
throw new IllegalArgumentException("ServiceElement is null");
return (cybernodeProxy.getServiceStatement(elem));
}
/**
* @see org.rioproject.deploy.ServiceBeanInstantiator#getServiceBeanInstances
*/
public ServiceBeanInstance[] getServiceBeanInstances(final ServiceElement element)
throws RemoteException {
return (cybernodeProxy.getServiceBeanInstances(element));
}
/**
* @see org.rioproject.deploy.ServiceBeanInstantiator#update
*/
public void update(final ServiceElement[] sElements,
final OperationalStringManager opStringMgr) throws RemoteException {
cybernodeProxy.update(sElements, opStringMgr);
}
/**
* @see org.rioproject.deploy.ServiceBeanInstantiator#getName
*/
public String getName() throws RemoteException {
if(name == null) {
name = cybernodeProxy.getName();
}
return(name);
}
/**
* @see org.rioproject.deploy.ServiceBeanInstantiator#getInstantiatorUuid()
*/
public Uuid getInstantiatorUuid() throws RemoteException {
return(getReferentUuid());
}
/**
* @see org.rioproject.deploy.ServiceBeanInstantiator#getInetAddress()
*/
public InetAddress getInetAddress() throws RemoteException {
return cybernodeProxy.getInetAddress();
}
/* Constrainable CybernodeProxy */
/**
* A subclass of CybernodeProxy that implements RemoteMethodControl.
*/
final static class ConstrainableCybernodeProxy extends CybernodeProxy
implements
RemoteMethodControl {
private static final long serialVersionUID = 1L;
/* Creates an instance of this class. */
private ConstrainableCybernodeProxy(final Cybernode cybernode,
final Uuid id,
final MethodConstraints methodConstraints) {
super(constrainServer(cybernode, methodConstraints), id);
}
/*
* Returns a copy of the server proxy with the specified client
* constraints and methods mapping.
*/
private static Cybernode constrainServer(final Cybernode cybernode,
final MethodConstraints methodConstraints) {
java.lang.reflect.Method[] methods = Cybernode.class.getMethods();
java.lang.reflect.Method[] methodMapping =
new java.lang.reflect.Method[methods.length * 2];
for(int i = 0; i < methodMapping.length; i++)
methodMapping[i] = methods[i / 2];
return ((Cybernode)((RemoteMethodControl)cybernode).
setConstraints(
ConstrainableProxyUtil.translateConstraints(
methodConstraints,
methodMapping)));
}
/** @see net.jini.core.constraint.RemoteMethodControl#setConstraints */
public RemoteMethodControl setConstraints(final MethodConstraints constraints) {
return (new ConstrainableCybernodeProxy((Cybernode)server,
uuid,
constraints));
}
/** @see RemoteMethodControl#getConstraints */
public MethodConstraints getConstraints() {
return ((RemoteMethodControl)cybernodeProxy).getConstraints();
}
/* Note that the superclass's hashCode method is OK as is. */
/* Note that the superclass's equals method is OK as is. */
/*
* Returns a proxy trust iterator that is used in
* <code>ProxyTrustVerifier</code> to retrieve this object's trust
* verifier.
*/
private ProxyTrustIterator getProxyTrustIterator() {
return (new SingletonProxyTrustIterator(cybernodeProxy));
}
/*
* Verify that the server implements RemoteMethodControl
*/
private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
/*
* Note that basic validation of the fields of this class was
* already performed in the readObject() method of this class' super
* class.
*/
s.defaultReadObject();
// Verify that the server implements RemoteMethodControl
if(!(server instanceof RemoteMethodControl)) {
throw new InvalidObjectException(
"ConstrainableCybernodeProxy.readObject failure - server "+
"does not implement constrainable functionality");
}
}
}
/**
* A trust verifier for secure smart proxies
*/
public final static class Verifier implements TrustVerifier, Serializable {
private static final long serialVersionUID = 1L;
private final RemoteMethodControl serverProxy;
/**
* Create the verifier, throwing UnsupportedOperationException if the
* server proxy does not implement both RemoteMethodControl and
* TrustEquivalence.
*
* @param serverProxy The proxy to verify
*/
public Verifier(Object serverProxy) {
if (serverProxy instanceof RemoteMethodControl &&
serverProxy instanceof TrustEquivalence) {
this.serverProxy = (RemoteMethodControl) serverProxy;
} else {
throw new UnsupportedOperationException();
}
}
/* Implement TrustVerifier */
public boolean isTrustedObject(Object obj, TrustVerifier.Context ctx) throws RemoteException {
if (obj == null || ctx == null) {
throw new IllegalArgumentException();
} else if (!(obj instanceof ConstrainableCybernodeProxy)) {
return false;
}
RemoteMethodControl otherServerProxy =
(RemoteMethodControl) ((ConstrainableCybernodeProxy)obj).cybernodeProxy;
MethodConstraints mc = otherServerProxy.getConstraints();
TrustEquivalence trusted = (TrustEquivalence) serverProxy.setConstraints(mc);
return(trusted.checkTrustEquivalence(otherServerProxy));
}
}
}