001package arcommon.xml;
002
003import java.io.IOException;
004import java.io.InvalidObjectException;
005import java.io.NotActiveException;
006import java.io.ObjectInputStream;
007import java.io.ObjectInputValidation;
008import java.io.ObjectStreamClass;
009import java.util.ArrayList;
010
011import arcommon.xml.XmlDeserializer.SpecialHandlingData;
012import arcommon.xml.XmlDeserializer.Update;
013
014public class XmlObjectInputStream extends ObjectInputStream {
015    private XmlDeserializer xmlDeserializer;
016    private ArrayList<Update> specialHandlingUpdates;
017    private ArrayList<SpecialHandlingData> specialHandlingDatas;
018    private boolean fieldsRead;
019    
020    public XmlObjectInputStream(XmlDeserializer pxmlDeserializer, ArrayList<Update> pspecialHandlingUpdates, ArrayList<SpecialHandlingData> pspecialHandlingDatas) throws IOException {
021        xmlDeserializer = pxmlDeserializer;
022        specialHandlingUpdates = pspecialHandlingUpdates;
023        specialHandlingDatas = pspecialHandlingDatas;
024    }
025    
026    public void checkAllDataRead() {
027        if (specialHandlingDatas.size() > 0) {
028            throw new RuntimeException("Not all datas are read: " + specialHandlingDatas);
029        }
030    }
031    
032    private void checkForData() {
033        if (specialHandlingDatas.size() == 0) {
034            throw new RuntimeException("No more data is available");
035        }
036    }
037    
038    private Object readData(Class<?> clazz) {
039        checkForData();
040        SpecialHandlingData specialHandlingData = specialHandlingDatas.remove(0);
041        if (specialHandlingData.clazz != clazz && clazz != null) {
042            throw new RuntimeException("specialHandlingData.class != class (" + specialHandlingData.clazz + " != " + clazz + ")");
043        }
044        return specialHandlingData.value;
045    }
046
047    @Override
048    public void defaultReadObject() throws IOException, ClassNotFoundException {
049        if (fieldsRead) {
050            throw new RuntimeException("Fields have already been read");
051        }
052        fieldsRead = true;
053        xmlDeserializer.executeUpdates(specialHandlingUpdates);
054    }
055
056    @Override
057    public int readInt() throws IOException {
058        return (Integer)readData(int.class);
059    }
060
061    @Override
062    public char readChar() throws IOException {
063        return (Character)readData(char.class);
064    }
065
066    @Override
067    public int read() throws IOException {
068        return (Byte)readData(byte.class);
069    }
070
071    @Override
072    public int read(byte[] p0) throws IOException {
073        checkForData();
074        SpecialHandlingData specialHandlingData = specialHandlingDatas.get(0);
075        byte[] bytes = (byte[])readData(byte[].class);
076        int length = Math.min(bytes.length - specialHandlingData.index, p0.length);
077        System.arraycopy(bytes, specialHandlingData.index, p0, 0, length);
078        if (p0.length < bytes.length - specialHandlingData.index) {
079            specialHandlingData.index += p0.length;
080            specialHandlingDatas.add(0, specialHandlingData);
081        }
082        return length;
083    }
084
085    @Override
086    public int read(byte[] p0, int p1, int p2) throws IOException {
087        throw new RuntimeException("Not implemented");
088    }
089
090    @Override
091    public byte readByte() throws IOException {
092        return (Byte)readData(byte.class);
093    }
094
095    @Override
096    public long readLong() throws IOException {
097        return (Long)readData(long.class);
098    }
099
100    @Override
101    public short readShort() throws IOException {
102        return (Short)readData(short.class);
103    }
104
105    @Override
106    public String readUTF() throws IOException {
107        return (String)readData(String.class);
108    }
109
110    @Override
111    public float readFloat() throws IOException {
112        return (Float)readData(float.class);
113    }
114
115    @Override
116    public void readFully(byte[] b) throws IOException {
117        int read = read(b);
118        if (read != b.length) {
119            throw new RuntimeException("read != b.length " + read + " != " + b.length);
120        }
121    }
122
123    @Override
124    public void readFully(byte[] p0, int p1, int p2) throws IOException {
125        throw new RuntimeException("Not implemented");
126    }
127
128    @Override
129    public boolean readBoolean() throws IOException {
130        return (Boolean)readData(boolean.class);
131    }
132
133    @Override
134    public double readDouble() throws IOException {
135        return (Double)readData(double.class);
136    }
137
138    @Override
139    public int readUnsignedByte() throws IOException {
140        throw new RuntimeException("Not implemented");
141    }
142
143    @Override
144    public int readUnsignedShort() throws IOException {
145        throw new RuntimeException("Not implemented");
146    }
147    
148    @Override
149    public Object readUnshared() throws IOException, ClassNotFoundException {
150        throw new RuntimeException("Not implemented");
151    }
152
153    @Override
154    public void close() throws IOException {
155        throw new RuntimeException("Not implemented");
156    }
157
158    @Override
159    public int skipBytes(int p0) throws IOException {
160        throw new RuntimeException("Not implemented");
161    }
162
163    @Override
164    public int available() throws IOException {
165        throw new RuntimeException("Not implemented");
166    }
167
168    @Override
169    public void registerValidation(ObjectInputValidation p0, int p1) throws NotActiveException, InvalidObjectException {
170        throw new RuntimeException("Not implemented");
171    }
172
173    @Override
174    public void mark(int p0) {
175        throw new RuntimeException("Not implemented");
176    }
177
178    @Override
179    public void reset() throws IOException {
180        throw new RuntimeException("Not implemented");
181    }
182
183    @Override
184    public String readLine() throws IOException {
185        return (String)readData(String.class);
186    }
187    
188    private Object getSpecialHandlingValue(String fieldName, Object defaultValue) {
189        for (Update update : specialHandlingUpdates) {
190            if (update.field.getName().equals(fieldName)) {
191                return update.value;
192            }
193        }
194        
195        return defaultValue;
196    }
197    
198    @Override
199    public GetField readFields() throws IOException, ClassNotFoundException {
200        return new GetField() {
201            @Override
202            public ObjectStreamClass getObjectStreamClass() {
203                throw new RuntimeException("Not implemented");
204            }
205            
206            @Override
207            public Object get(String name, Object val) throws IOException {
208                return getSpecialHandlingValue(name, val);
209            }
210            
211            @Override
212            public double get(String name, double val) throws IOException {
213                // This doesn't compile on 1.6
214//                return (double)getSpecialHandlingValue(name, val);
215                throw new RuntimeException("Not implemented");
216            }
217            
218            @Override
219            public float get(String name, float val) throws IOException {
220                throw new RuntimeException("Not implemented");
221            }
222            
223            @Override
224            public long get(String name, long val) throws IOException {
225                throw new RuntimeException("Not implemented");
226            }
227            
228            @Override
229            public int get(String name, int val) throws IOException {
230                throw new RuntimeException("Not implemented");
231            }
232            
233            @Override
234            public short get(String name, short val) throws IOException {
235                throw new RuntimeException("Not implemented");
236            }
237            
238            @Override
239            public char get(String name, char val) throws IOException {
240                throw new RuntimeException("Not implemented");
241            }
242            
243            @Override
244            public byte get(String name, byte val) throws IOException {
245                throw new RuntimeException("Not implemented");
246            }
247            
248            @Override
249            public boolean get(String name, boolean val) throws IOException {
250                throw new RuntimeException("Not implemented");
251            }
252            
253            @Override
254            public boolean defaulted(String name) throws IOException {
255                for (Update update : specialHandlingUpdates) {
256                    if (update.field.getName().equals(name)) {
257                        return false;
258                    }
259                }
260                return true;
261            }
262        };
263    }
264
265    @Override
266    public long skip(long p0) throws IOException {
267        throw new RuntimeException("Not implemented");
268    }
269
270    @Override
271    public boolean markSupported() {
272        throw new RuntimeException("Not implemented");
273    }
274
275    @Override
276    public Object readObjectOverride() throws ClassNotFoundException, IOException {
277        return readData(null);
278    }
279}