blob: 585b60fc998e9e2f254ae44b75e7db7be42b7780 [file] [log] [blame]
package org.apache.yoko.rmi.impl;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.MARSHAL;
public final class CustomMarshaledObjectReader extends DelegatingObjectReader {
private enum State {
UNINITIALISED, BEFORE_CUSTOM_DATA, IN_CUSTOM_DATA, CLOSED;
private static final Map<State, Set<State>> TRANSITIONS;
static {
EnumMap<State, Set<State>> transition = new EnumMap<>(State.class);
allow(transition, from(UNINITIALISED), to(BEFORE_CUSTOM_DATA));
allow(transition, from(BEFORE_CUSTOM_DATA), to(IN_CUSTOM_DATA, CLOSED));
allow(transition, from(IN_CUSTOM_DATA), to(CLOSED));
allow(transition, from(CLOSED), to(CLOSED));
TRANSITIONS = Collections.unmodifiableMap(transition);
}
private static void allow(Map<State, Set<State>> map, State from, Set<State> to) {
map.put(from, to);
}
private static State from(State state) { return state; }
private static Set<State> to(State state, State...states) {
return Collections.unmodifiableSet(EnumSet.of(state, states));
}
void checkStateTransition(State newState) {
if (TRANSITIONS.get(this).contains(newState))
return;
throw new INTERNAL("Unexpected state transition from " + this + " to " + newState);
}
}
private final ObjectReader objectReader;
private State state = State.UNINITIALISED;
private State setState(final State newState) throws IOException {
state.checkStateTransition(newState);
try {
return state;
} finally {
state = newState;
switch(newState) {
case UNINITIALISED:
throw new IllegalStateException();
case BEFORE_CUSTOM_DATA:
delegateTo(new DefaultWriteObjectReader(objectReader));
break;
case IN_CUSTOM_DATA:
delegateTo(objectReader);
break;
case CLOSED:
delegateTo(ClosedObjectReader.INSTANCE);
break;
}
}
}
private void readCustomRMIValue() throws IOException {
setState(State.IN_CUSTOM_DATA);
objectReader._startValue();
}
public CustomMarshaledObjectReader(ObjectReader delegate) throws IOException {
this.objectReader = delegate;
setState(State.BEFORE_CUSTOM_DATA);
}
public void close() throws IOException {
switch (setState(State.CLOSED)) {
case UNINITIALISED:
throw new IllegalStateException();
case BEFORE_CUSTOM_DATA :
objectReader.readValueObject();
break;
case IN_CUSTOM_DATA :
objectReader._endValue();
break;
case CLOSED :
// nothing to do here
break;
}
}
@Override
protected final Object readObjectOverride() throws ClassNotFoundException, IOException {
return super.readObjectOverride0();
}
/**
* This class handles reading the defaultWriteObject() data,
* and prepares its outer instance when the custom data is
* first read.
*/
private final class DefaultWriteObjectReader extends DelegatingObjectReaderWithBeforeReadHook {
private boolean allowDefaultRead = true;
public DefaultWriteObjectReader(ObjectReader delegate) throws IOException {
super(delegate);
}
@Override
public void defaultReadObject() throws IOException, ClassNotFoundException {
if (allowDefaultRead) {
allowDefaultRead = false;
CustomMarshaledObjectReader.this.objectReader.defaultReadObject();
} else {
throw new IllegalStateException("defaultReadObject() or readFields() must not be called more than once");
}
}
@Override
public GetField readFields() throws IOException ,ClassNotFoundException {
if (allowDefaultRead) {
allowDefaultRead = false;
return CustomMarshaledObjectReader.this.objectReader.readFields();
} else {
throw new IllegalStateException("readFields() or defaultReadObject() must not be called more than once");
}
};
@Override
void beforeRead() {
try {
CustomMarshaledObjectReader.this.readCustomRMIValue();
} catch (IOException e) {
throw (MARSHAL)new MARSHAL(e.toString()).initCause(e);
}
}
}
}