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