178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson/** 278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * Copyright 2006-2013 the original author or authors. 378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * 478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * Licensed under the Apache License, Version 2.0 (the "License"); 578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * you may not use this file except in compliance with the License. 678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * You may obtain a copy of the License at 778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * 878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * http://www.apache.org/licenses/LICENSE-2.0 978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * 1078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * Unless required by applicable law or agreed to in writing, software 1178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * distributed under the License is distributed on an "AS IS" BASIS, 1278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * See the License for the specific language governing permissions and 1478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * limitations under the License. 1578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson */ 1678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonpackage org.objenesis.instantiator.basic; 1778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 1878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.ByteArrayOutputStream; 1978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.DataOutputStream; 2078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.IOException; 2178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.InputStream; 2278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.NotSerializableException; 2378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.ObjectInputStream; 2478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.ObjectStreamClass; 2578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.ObjectStreamConstants; 2678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport java.io.Serializable; 2778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 2878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport org.objenesis.ObjenesisException; 2978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonimport org.objenesis.instantiator.ObjectInstantiator; 3078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 3178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson/** 3278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * Instantiates a class by using a dummy input stream that always feeds data for an empty object of 3378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * the same kind. NOTE: This instantiator may not work properly if the class being instantiated 3478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * defines a "readResolve" method, since it may return objects that have been returned previously 3578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * (i.e., there's no guarantee that the returned object is a new one), or even objects from a 3678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * completely different class. 3778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * 3878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * @author Leonardo Mesquita 3978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * @see org.objenesis.instantiator.ObjectInstantiator 4078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson */ 4178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinsonpublic class ObjectInputStreamInstantiator implements ObjectInstantiator { 4278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static class MockStream extends InputStream { 4378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 4478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private int pointer; 4578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private byte[] data; 4678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private int sequence; 4778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static final int[] NEXT = new int[] {1, 2, 2}; 4878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private byte[][] buffers; 4978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 5078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private final byte[] FIRST_DATA; 5178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static byte[] HEADER; 5278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static byte[] REPEATING_DATA; 5378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 5478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson static { 5578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson initialize(); 5678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 5778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 5878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static void initialize() { 5978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 6078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 6178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson DataOutputStream dout = new DataOutputStream(byteOut); 6278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeShort(ObjectStreamConstants.STREAM_MAGIC); 6378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeShort(ObjectStreamConstants.STREAM_VERSION); 6478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson HEADER = byteOut.toByteArray(); 6578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 6678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson byteOut = new ByteArrayOutputStream(); 6778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout = new DataOutputStream(byteOut); 6878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 6978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_OBJECT); 7078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_REFERENCE); 7178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeInt(ObjectStreamConstants.baseWireHandle); 7278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson REPEATING_DATA = byteOut.toByteArray(); 7378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 7478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(IOException e) { 7578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("IOException: " + e.getMessage()); 7678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 7778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 7878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 7978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 8078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public MockStream(Class clazz) { 8178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.pointer = 0; 8278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.sequence = 0; 8378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.data = HEADER; 8478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 8578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte) TC_OBJECT 8678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte) TC_CLASSDESC 8778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (short length) 8878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte * className.length) 8978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (long)serialVersionUID 9078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte) SC_SERIALIZABLE 9178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (short)0 <fields> 9278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // TC_ENDBLOCKDATA 9378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // TC_NULL 9478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 9578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson DataOutputStream dout = new DataOutputStream(byteOut); 9678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 9778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_OBJECT); 9878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_CLASSDESC); 9978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeUTF(clazz.getName()); 10078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeLong(ObjectStreamClass.lookup(clazz).getSerialVersionUID()); 10178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.SC_SERIALIZABLE); 10278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeShort((short) 0); // Zero fields 10378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA); 10478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_NULL); 10578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 10678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(IOException e) { 10778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("IOException: " + e.getMessage()); 10878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 10978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.FIRST_DATA = byteOut.toByteArray(); 11078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson buffers = new byte[][] {HEADER, FIRST_DATA, REPEATING_DATA}; 11178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 11278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 11378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private void advanceBuffer() { 11478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson pointer = 0; 11578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson sequence = NEXT[sequence]; 11678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson data = buffers[sequence]; 11778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 11878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 11978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public int read() throws IOException { 12078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson int result = data[pointer++]; 12178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson if(pointer >= data.length) { 12278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson advanceBuffer(); 12378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 12478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 12578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return result; 12678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 12778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 12878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public int available() throws IOException { 12978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return Integer.MAX_VALUE; 13078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 13178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 13278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public int read(byte[] b, int off, int len) throws IOException { 13378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson int left = len; 13478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson int remaining = data.length - pointer; 13578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 13678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson while(remaining <= left) { 13778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson System.arraycopy(data, pointer, b, off, remaining); 13878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson off += remaining; 13978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson left -= remaining; 14078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson advanceBuffer(); 14178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson remaining = data.length - pointer; 14278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 14378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson if(left > 0) { 14478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson System.arraycopy(data, pointer, b, off, left); 14578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson pointer += left; 14678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 14778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 14878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return len; 14978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 15078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 15178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 15278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private ObjectInputStream inputStream; 15378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 15478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public ObjectInputStreamInstantiator(Class clazz) { 15578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson if(Serializable.class.isAssignableFrom(clazz)) { 15678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 15778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.inputStream = new ObjectInputStream(new MockStream(clazz)); 15878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 15978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(IOException e) { 16078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("IOException: " + e.getMessage()); 16178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson else { 16478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new ObjenesisException(new NotSerializableException(clazz+" not serializable")); 16578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 16878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public Object newInstance() { 16978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 17078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return inputStream.readObject(); 17178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 17278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(ClassNotFoundException e) { 17378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("ClassNotFoundException: " + e.getMessage()); 17478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 17578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(Exception e) { 17678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new ObjenesisException(e); 17778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 17878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 17978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson} 180