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 */ 022package org.granite.messaging.jmf; 023 024import java.io.IOException; 025import java.io.OutputStream; 026import java.lang.reflect.InvocationTargetException; 027import java.util.HashMap; 028import java.util.IdentityHashMap; 029import java.util.Map; 030 031import org.granite.messaging.jmf.codec.StandardCodec; 032import org.granite.messaging.reflect.Property; 033import org.granite.messaging.reflect.Reflection; 034 035/** 036 * @author Franck WOLFF 037 */ 038public 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}