/*
* 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 java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.rmi.MarshalledObject;
import net.jini.core.event.RemoteEvent;
/**
* This class provides the methods for reading <tt>RemoteEvent</tt>s from
* a given <tt>LogInputStream</tt>.
*
* @author Sun Microsystems, Inc.
*
* @since 1.1
*/
class EventReader {
/**
* This class extends <tt>ObjectInputStream</tt> in order to obtain
* object reading methods. This class is used in conjunction with
* <tt>SwitchInputStream</tt> in order to provide a re-targetable
* input stream capability.
*/
private static class EventInputStream extends ObjectInputStream {
/**
* Simple constructor that passes its argument to the superclass
*
* @exception IOException if an I/O error occurs
*/
public EventInputStream(InputStream in) throws IOException {
super(in);
}
/**
* Overrides <tt>ObjectInputStream</tt>'s method with no-op
* functionality. This prevents the underlying stream from being
* being accessed during construction. See <tt>SwitchInputStream</tt>.
*
* @exception IOException if an I/O error occurs
*/
protected void readStreamHeader() throws IOException {
// Do nothing
}
}
/**
* This class is intended to be the <tt>InputStream</tt> provided
* to <tt>EventInputStream</tt>'s constructor. This class essentially
* delegates <tt>InputStream</tt> functionality to the provided
* <tt>InputStream</tt>. The <tt>setInputStream</tt> method
* allows the underlying <tt>InputStream</tt> to be re-targeted
* at runtime.
*/
private static class SwitchInputStream extends InputStream {
/** The delegation target for the <tt>InputStream</tt> methods */
private InputStream in;
/**
* Simple constructor that assigns the given argument to the
* appropriate internal field.
*/
public SwitchInputStream(InputStream in) {
this.in = in;
}
// documentation inherited from supertype
public int read() throws IOException {
return in.read();
}
// documentation inherited from supertype
public int read(byte[] b) throws IOException {
return in.read(b);
}
// documentation inherited from supertype
public int read(byte[] b, int off, int len) throws IOException {
return in.read(b, off, len);
}
// documentation inherited from supertype
public long skip(long n) throws IOException {
return in.skip(n);
}
// documentation inherited from supertype
public int available() throws IOException {
return in.available();
}
// documentation inherited from supertype
public void close() throws IOException {
in.close();
}
/** Sets the delegation target */
public void setInputStream(InputStream in) {
this.in = in;
}
}
/** Reference to <tt>EventInputStream</tt> for this class */
private EventInputStream ein;
/** Reference to <tt>SwitchInputStream</tt> for this class */
private SwitchInputStream sin;
/**
* Simple constructor that creates the appropriate internal objects.
*
* @exception IOException if an I/O error occurs
*/
public EventReader() throws IOException {
sin = new SwitchInputStream(null);
ein = new EventInputStream(sin);
}
/**
* Returns the next available <tt>RemoteEvent</tt> from the stream.
*
* @exception IOException
* Thrown if an I/O error occurs
* @exception ClassNotFoundException Thrown if the class of a
* serialized object cannot be found.
*/
public RemoteEvent read(InputStream in)
throws IOException, ClassNotFoundException
{
// Set the target stream
sin.setInputStream(in);
try {
// Retrieve next event which was stored as a
// MarshalledObject and return its contents.
MarshalledObject mo = (MarshalledObject)ein.readObject();
return (RemoteEvent) mo.get();
} finally {
// Reset target stream to null
sin.setInputStream(null);
}
}
}