001 /**
002 * GRANITE DATA SERVICES
003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 * This file is part of the Granite Data Services Platform.
006 *
007 * Granite Data Services is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * Granite Data Services is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 * General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 * USA, or see <http://www.gnu.org/licenses/>.
021 */
022 package org.granite.messaging.jmf;
023
024 import java.io.IOException;
025 import java.io.OutputStream;
026 import java.lang.reflect.InvocationTargetException;
027 import java.util.HashMap;
028 import java.util.IdentityHashMap;
029 import java.util.Map;
030
031 import org.granite.messaging.jmf.codec.StandardCodec;
032 import org.granite.messaging.reflect.Property;
033 import org.granite.messaging.reflect.Reflection;
034
035 /**
036 * @author Franck WOLFF
037 */
038 public class JMFSerializer implements OutputContext {
039
040 ///////////////////////////////////////////////////////////////////////////
041 // Fields
042
043 protected final Map<String, Integer> storedStrings = new HashMap<String, Integer>(256);
044 protected final Map<Object, Integer> storedObjects = new IdentityHashMap<Object, Integer>(256);
045
046 protected final OutputStream outputStream;
047 protected final SharedContext context;
048
049 protected final CodecRegistry codecRegistry;
050
051 ///////////////////////////////////////////////////////////////////////////
052 // Initialization
053
054 public JMFSerializer(OutputStream outputStream, SharedContext context) {
055 this.outputStream = outputStream;
056 this.codecRegistry = context.getCodecRegistry();
057 this.context = context;
058
059 for (String s : context.getDefaultStoredStrings())
060 addToStoredStrings(s);
061 }
062
063 ///////////////////////////////////////////////////////////////////////////
064 // ObjectOutput implementation
065
066 public void writeBoolean(boolean v) throws IOException {
067 codecRegistry.getBooleanCodec().encodePrimitive(this, v);
068 }
069
070 public void writeByte(int v) throws IOException {
071 codecRegistry.getByteCodec().encodePrimitive(this, v);
072 }
073
074 public void writeShort(int v) throws IOException {
075 codecRegistry.getShortCodec().encodePrimitive(this, v);
076 }
077
078 public void writeChar(int v) throws IOException {
079 codecRegistry.getCharacterCodec().encodePrimitive(this, v);
080 }
081
082 public void writeInt(int v) throws IOException {
083 codecRegistry.getIntegerCodec().encodePrimitive(this, v);
084 }
085
086 public void writeLong(long v) throws IOException {
087 codecRegistry.getLongCodec().encodePrimitive(this, v);
088 }
089
090 public void writeFloat(float v) throws IOException {
091 codecRegistry.getFloatCodec().encodePrimitive(this, v);
092 }
093
094 public void writeDouble(double v) throws IOException {
095 codecRegistry.getDoubleCodec().encodePrimitive(this, v);
096 }
097
098 public void writeUTF(String s) throws IOException {
099 if (s == null)
100 codecRegistry.getNullCodec().encode(this, s);
101 else
102 codecRegistry.getStringCodec().encode(this, s);
103 }
104
105 public void writeObject(Object obj) throws IOException {
106 StandardCodec<Object> codec = codecRegistry.getCodec(obj);
107 if (codec == null)
108 throw new JMFEncodingException("Unsupported Java class: " + obj);
109
110 try {
111 codec.encode(this, obj);
112 }
113 catch (IllegalAccessException e) {
114 throw new IOException(e);
115 }
116 catch (InvocationTargetException e) {
117 throw new IOException(e);
118 }
119 }
120
121 public void flush() throws IOException {
122 outputStream.flush();
123 }
124
125 public void close() throws IOException {
126 outputStream.close();
127 }
128
129 ///////////////////////////////////////////////////////////////////////////
130 // ObjectOutput implementation (unsupported, marked at deprecated)
131
132 @Deprecated
133 public void write(int b) throws IOException {
134 throw new UnsupportedOperationException("Use writeByte(b)");
135 }
136
137 @Deprecated
138 public void write(byte[] b) throws IOException {
139 throw new UnsupportedOperationException("Use writeObject(b)");
140 }
141
142 @Deprecated
143 public void write(byte[] b, int off, int len) throws IOException {
144 throw new UnsupportedOperationException("Use writeObject(Arrays.copyOfRange(b, off, off+len))");
145 }
146
147 @Deprecated
148 public void writeBytes(String s) throws IOException {
149 throw new UnsupportedOperationException("Use writeUTF(s)");
150 }
151
152 @Deprecated
153 public void writeChars(String s) throws IOException {
154 throw new UnsupportedOperationException("Use writeUTF(s)");
155 }
156
157 ///////////////////////////////////////////////////////////////////////////
158 // OutputContext implementation
159
160 public SharedContext getSharedContext() {
161 return context;
162 }
163
164 public OutputStream getOutputStream() {
165 return outputStream;
166 }
167
168 public void addToStoredStrings(String s) {
169 if (s != null && !storedStrings.containsKey(s)) {
170 Integer index = Integer.valueOf(storedStrings.size());
171 storedStrings.put(s, index);
172 }
173 }
174
175 public int indexOfStoredStrings(String s) {
176 if (s != null) {
177 Integer index = storedStrings.get(s);
178 if (index != null)
179 return index.intValue();
180 }
181 return -1;
182 }
183
184 public void addToStoredObjects(Object o) {
185 if (o != null && !storedObjects.containsKey(o)) {
186 Integer index = Integer.valueOf(storedObjects.size());
187 storedObjects.put(o, index);
188 }
189 }
190
191 public int indexOfStoredObjects(Object o) {
192 if (o != null) {
193 Integer index = storedObjects.get(o);
194 if (index != null)
195 return index.intValue();
196 }
197 return -1;
198 }
199
200 ///////////////////////////////////////////////////////////////////////////
201 // ExtendedObjectOutput implementation
202
203 public Reflection getReflection() {
204 return context.getReflection();
205 }
206
207 public String getAlias(String className) {
208 return context.getRemoteAlias(className);
209 }
210
211 public void getAndWriteProperty(Object obj, Property property) throws IOException, IllegalAccessException, InvocationTargetException {
212 if (property.getType().isPrimitive())
213 codecRegistry.getPrimitivePropertyCodec(property.getType()).encodePrimitive(this, obj, property);
214 else
215 writeObject(property.getObject(obj));
216 }
217 }