/*
* 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 com.sun.jini.mercury;
import com.sun.jini.proxy.ThrowThis;
import net.jini.core.constraint.MethodConstraints;
import net.jini.core.constraint.RemoteMethodControl;
import net.jini.id.ReferentUuid;
import net.jini.id.ReferentUuids;
import net.jini.id.Uuid;
import net.jini.security.TrustVerifier;
import net.jini.security.proxytrust.ProxyTrustIterator;
import net.jini.security.proxytrust.SingletonProxyTrustIterator;
import java.lang.reflect.Method;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.security.auth.Subject;
import net.jini.admin.Administrable;
import net.jini.core.lease.Lease;
import net.jini.core.lease.LeaseDeniedException;
import net.jini.event.EventMailbox;
import net.jini.event.MailboxRegistration;
import net.jini.event.MailboxPullRegistration;
import net.jini.event.PullEventMailbox;
/**
* A MailboxProxy is a proxy for the event mailbox service.
* This is the object passed to clients of this service.
* It implements the <code>PullEventMailbox</code> and the
* <code>Administrable</code> interfaces.
*
* @author Sun Microsystems, Inc.
*
* @since 1.1
*/
class MailboxProxy implements PullEventMailbox,
Administrable, Serializable, ReferentUuid
{
private static final long serialVersionUID = 2L;
/**
* The reference to the event mailbox service implementation
*
* @serial
*/
final MailboxBackEnd mailbox;
/**
* The proxy's <code>Uuid</code>
*
* @serial
*/
final Uuid proxyID;
/**
* Creates a mailbox proxy, returning an instance
* that implements RemoteMethodControl if the server does too.
*
* @param mailbox the server proxy
* @param id the ID of the server
*/
static MailboxProxy create(MailboxBackEnd mailbox, Uuid id) {
if (mailbox instanceof RemoteMethodControl) {
return new ConstrainableMailboxProxy(mailbox, id, null);
} else {
return new MailboxProxy(mailbox, id);
}
}
/** Convenience constructor. */
private MailboxProxy(MailboxBackEnd mailbox, Uuid proxyID) {
if (mailbox == null || proxyID == null) {
throw new IllegalArgumentException("Cannot accept null arguments");
}
this.mailbox = mailbox;
this.proxyID = proxyID;
}
// inherit javadoc from parent
public MailboxRegistration register(long duration)
throws RemoteException, LeaseDeniedException {
// Check for a bad argument
// Note that -1 (i.e. Lease.ANY) is a valid request
if (duration < 1 && duration != Lease.ANY)
throw new IllegalArgumentException(
"Duration values must be positive");
return mailbox.register(duration);
}
// inherit javadoc from parent
public MailboxPullRegistration pullRegister(long duration)
throws RemoteException, LeaseDeniedException {
// Check for a bad argument
// Note that -1 (i.e. Lease.ANY) is a valid request
if (duration < 1 && duration != Lease.ANY)
throw new IllegalArgumentException(
"Duration values must be positive");
return mailbox.pullRegister(duration);
}
// inherit javadoc from parent
public Object getAdmin() throws RemoteException {
return mailbox.getAdmin();
}
/* From net.jini.id.ReferentUuid */
/**
* Returns the universally unique identifier that has been assigned to the
* resource this proxy represents.
*
* @return the instance of <code>Uuid</code> that is associated with the
* resource this proxy represents. This method will not return
* <code>null</code>.
*
* @see net.jini.id.ReferentUuid
*/
public Uuid getReferentUuid() {
return proxyID;
}
/** Proxies for servers with the same proxyID have the same hash code. */
public int hashCode() {
return proxyID.hashCode();
}
/**
* Proxies for servers with the same <code>proxyID</code> are
* considered equal.
*/
public boolean equals(Object o) {
return ReferentUuids.compare(this,o);
}
/** When an instance of this class is deserialized, this method is
* automatically invoked. This implementation of this method validates
* the state of the deserialized instance.
*
* @throws <code>InvalidObjectException</code> if the state of the
* deserialized instance of this class is found to be invalid.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
/* Verify server */
if(mailbox == null) {
throw new InvalidObjectException("MailboxProxy.readObject "
+"failure - mailbox "
+"field is null");
}//endif
/* Verify proxyID */
if(proxyID == null) {
throw new InvalidObjectException("MailboxProxy.proxyID "
+"failure - proxyID "
+"field is null");
}//endif
}//end readObject
/** During deserialization of an instance of this class, if it is found
* that the stream contains no data, this method is automatically
* invoked. Because it is expected that the stream should always
* contain data, this implementation of this method simply declares
* that something must be wrong.
*
* @throws <code>InvalidObjectException</code> to indicate that there
* was no data in the stream during deserialization of an
* instance of this class; declaring that something is wrong.
*/
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("no data found when attempting to "
+"deserialize MailboxProxy instance");
}//end readObjectNoData
/** A subclass of MailboxProxy that implements RemoteMethodControl. */
final static class ConstrainableMailboxProxy extends MailboxProxy
implements RemoteMethodControl
{
private static final long serialVersionUID = 1L;
/** Creates an instance of this class. */
private ConstrainableMailboxProxy(MailboxBackEnd mailbox, Uuid uuid,
MethodConstraints methodConstraints)
{
super(constrainServer(mailbox, methodConstraints),
uuid);
}
/**
* Returns a copy of the server proxy with the specified client
* constraints and methods mapping.
*/
private static MailboxBackEnd constrainServer(
MailboxBackEnd mailbox,
MethodConstraints methodConstraints)
{
return (MailboxBackEnd)
((RemoteMethodControl)mailbox).setConstraints(methodConstraints);
}
/** {@inheritDoc} */
public RemoteMethodControl setConstraints(
MethodConstraints constraints)
{
return new ConstrainableMailboxProxy(mailbox, proxyID,
constraints);
}
/** {@inheritDoc} */
public MethodConstraints getConstraints() {
return ((RemoteMethodControl) mailbox).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(mailbox);
}//end getProxyTrustIterator
/** Performs various functions related to the trust verification
* process for the current instance of this proxy class, as
* detailed in the description for this class.
*
* @throws <code>InvalidObjectException</code> if any of the
* requirements for trust verification (as detailed in the
* class description) are not satisfied.
*/
private void readObject(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( !(mailbox instanceof RemoteMethodControl) ) {
throw new InvalidObjectException(
"MailboxAdminProxy.readObject failure - mailbox " +
"does not implement constrainable functionality ");
}//endif
}//end readObject
}
}