| /** |
| * |
| * 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); |
| } |
| } |