blob: 9d9a5f582df1da536f26a59dd36945b46bfefb2f [file] [log] [blame]
/**
*
* 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 org.apache.yoko.rmi.impl;
import java.io.Externalizable;
import java.io.IOException;
import java.io.NotActiveException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.yoko.util.cmsf.CmsfThreadLocal;
import org.apache.yoko.util.yasf.Yasf;
import org.apache.yoko.util.yasf.YasfThreadLocal;
abstract class ObjectWriter extends ObjectOutputStream {
protected final Serializable object;
private ValueDescriptor _desc;
private PutFieldImpl _putFields;
private WriteObjectState state = WriteObjectState.NOT_IN_WRITE_OBJECT;
final byte cmsf;
final Set<Yasf> yasfSet;
private enum WriteObjectState {
NOT_IN_WRITE_OBJECT {
void beforeWriteObject(ObjectWriter writer) {
writer.state = IN_WRITE_OBJECT;
}
},
IN_WRITE_OBJECT {
void afterWriteObject(ObjectWriter writer) throws IOException {
writer.state = NOT_IN_WRITE_OBJECT;
// there is no custom (nor default) state written
writer.writeBoolean(false);
// If we're in stream format version 2, we must
// put the "null" marker to say that there isn't
// any optional data
if (writer.cmsf == 2) {
writer._nullValue();
}
}
void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
writer.state = IN_DEFAULT_WRITE_OBJECT;
writer.writeBoolean(true);
}
void beforeWriteData(ObjectWriter writer) throws IOException {
writer.state = WROTE_CUSTOM_DATA;
// writeDefaultObject was not invoked
writer.writeBoolean(false);
if (writer.cmsf == 2) {
writer._startValue(writer._desc.getCustomRepositoryID());
}
}
},
IN_DEFAULT_WRITE_OBJECT {
void afterDefaultWriteObject(ObjectWriter writer) {
writer.state = WROTE_DEFAULT_DATA;
}
},
WROTE_DEFAULT_DATA {
void afterWriteObject(ObjectWriter writer) throws IOException {
// the boolean identifying that default data was written has already
// been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
writer.state = NOT_IN_WRITE_OBJECT;
// write a null-marker to identify that there is no custom
// state being marshalled...
if (writer.cmsf == 2) {
writer._nullValue();
}
}
void beforeWriteData(ObjectWriter writer) throws IOException {
// the boolean identifying that default data was written has already
// been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
writer.state = WROTE_CUSTOM_DATA;
if (writer.cmsf == 2) {
writer._startValue(writer._desc.getCustomRepositoryID());
}
}
},
WROTE_CUSTOM_DATA {
void afterWriteObject(ObjectWriter writer) throws IOException {
if (writer.cmsf == 2) {
writer._endValue();
}
writer.state = NOT_IN_WRITE_OBJECT;
}
}
;
void beforeWriteObject(ObjectWriter writer) {
throw new IllegalStateException();
}
void afterWriteObject(ObjectWriter writer) throws IOException {
throw new IllegalStateException();
}
void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
throw new IllegalStateException();
}
void afterDefaultWriteObject(ObjectWriter writer) {
throw new IllegalStateException();
}
void beforeWriteData(ObjectWriter writer) throws IOException {
}
}
protected void beforeWriteData() throws IOException {
state.beforeWriteData(this);
}
ObjectWriter(Serializable obj) throws IOException {
object = obj;
cmsf = CmsfThreadLocal.get();
yasfSet = YasfThreadLocal.get();
}
abstract ObjectReader getObjectReader(Object newObject);
private void setCurrentValueDescriptor(ValueDescriptor desc) {
_desc = desc;
_putFields = null;
}
public final void defaultWriteObject() throws IOException {
if (_desc == null) {
throw new NotActiveException();
}
state.beforeDefaultWriteObject(this);
try {
_desc.defaultWriteValue(this, object);
} finally {
state.afterDefaultWriteObject(this);
}
}
public ObjectOutputStream.PutField putFields()
throws IOException {
if (_desc == null) {
throw new NotActiveException();
}
_putFields = new PutFieldImpl(_desc);
return _putFields;
}
public void writeFields() throws IOException {
if (_putFields == null) {
throw new NotActiveException("no current PutFields");
}
if (_putFields.slice != _desc) {
throw new NotActiveException(
"PutField cannot survive writeObject invocation");
}
state.beforeDefaultWriteObject(this);
try {
_putFields.write(this);
} finally {
state.afterDefaultWriteObject(this);
}
}
public void close() { /* skip */
}
public void flush() { /* skip */
}
public abstract void writeValueObject(Object obj) throws IOException;
public abstract void writeRemoteObject(Object obj) throws IOException;
public abstract void writeCorbaObject(Object obj) throws IOException;
public abstract void writeAny(Object obj) throws IOException;
static class PutFieldImpl extends PutField {
final ValueDescriptor slice;
final Map<String, Object> valueMap = new HashMap<>();
PutFieldImpl(ValueDescriptor slice) {
this.slice = slice;
}
@Override
public void put(String name, boolean val) {
valueMap.put(name, val);
}
@Override
public void put(String name, byte val) {
valueMap.put(name, val);
}
@Override
public void put(String name, char val) {
valueMap.put(name, val);
}
@Override
public void put(String name, double val) {
valueMap.put(name, val);
}
@Override
public void put(String name, float val) {
valueMap.put(name, val);
}
@Override
public void put(String name, int val) {
valueMap.put(name, val);
}
@Override
public void put(String name, long val) {
valueMap.put(name, val);
}
@Override
public void put(String name, Object val) {
valueMap.put(name, val);
}
@Override
public void put(String name, short val) {
valueMap.put(name, val);
}
@Override
public void write(ObjectOutput out) throws IOException {
slice.writeFields((ObjectWriter) out, valueMap);
}
}
void invokeWriteObject(ValueDescriptor descriptor, Serializable val,
Method _write_object_method) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException, IOException {
final ValueDescriptor desc = _desc;
final WriteObjectState old_state = state;
state = WriteObjectState.NOT_IN_WRITE_OBJECT;
try {
setCurrentValueDescriptor(descriptor);
writeByte(cmsf);
state.beforeWriteObject(this);
_write_object_method.invoke(val, this);
state.afterWriteObject(this);
} finally {
state = old_state;
setCurrentValueDescriptor(desc);
}
}
protected abstract void _startValue(String rep_id) throws IOException;
protected abstract void _endValue() throws IOException;
protected abstract void _nullValue() throws IOException;
void invokeWriteExternal(Externalizable externalizable) throws IOException {
writeByte(cmsf);
externalizable.writeExternal(this);
}
}