178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson/** 2eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * Copyright 2006-2017 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; 30eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport org.objenesis.instantiator.annotations.Instantiator; 31eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport org.objenesis.instantiator.annotations.Typology; 3278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 3378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson/** 3478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * Instantiates a class by using a dummy input stream that always feeds data for an empty object of 3578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * the same kind. NOTE: This instantiator may not work properly if the class being instantiated 3678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * defines a "readResolve" method, since it may return objects that have been returned previously 3778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * (i.e., there's no guarantee that the returned object is a new one), or even objects from a 3878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * completely different class. 39eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * 4078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * @author Leonardo Mesquita 4178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson * @see org.objenesis.instantiator.ObjectInstantiator 4278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson */ 43eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin@Instantiator(Typology.SERIALIZATION) 44eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinpublic class ObjectInputStreamInstantiator<T> implements ObjectInstantiator<T> { 4578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static class MockStream extends InputStream { 4678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 4778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private int pointer; 4878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private byte[] data; 4978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private int sequence; 5078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static final int[] NEXT = new int[] {1, 2, 2}; 5178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private byte[][] buffers; 5278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 5378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private final byte[] FIRST_DATA; 5478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static byte[] HEADER; 5578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static byte[] REPEATING_DATA; 5678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 5778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson static { 5878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson initialize(); 5978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 6078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 6178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private static void initialize() { 6278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 6378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 6478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson DataOutputStream dout = new DataOutputStream(byteOut); 6578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeShort(ObjectStreamConstants.STREAM_MAGIC); 6678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeShort(ObjectStreamConstants.STREAM_VERSION); 6778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson HEADER = byteOut.toByteArray(); 6878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 6978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson byteOut = new ByteArrayOutputStream(); 7078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout = new DataOutputStream(byteOut); 7178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 7278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_OBJECT); 7378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_REFERENCE); 7478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeInt(ObjectStreamConstants.baseWireHandle); 7578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson REPEATING_DATA = byteOut.toByteArray(); 7678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 7778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(IOException e) { 7878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("IOException: " + e.getMessage()); 7978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 8078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 8178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 8278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 83eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public MockStream(Class<?> clazz) { 8478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.pointer = 0; 8578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.sequence = 0; 8678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.data = HEADER; 8778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 8878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte) TC_OBJECT 8978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte) TC_CLASSDESC 9078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (short length) 9178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte * className.length) 9278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (long)serialVersionUID 9378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (byte) SC_SERIALIZABLE 9478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // (short)0 <fields> 9578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // TC_ENDBLOCKDATA 9678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson // TC_NULL 9778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 9878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson DataOutputStream dout = new DataOutputStream(byteOut); 9978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 10078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_OBJECT); 10178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_CLASSDESC); 10278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeUTF(clazz.getName()); 10378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeLong(ObjectStreamClass.lookup(clazz).getSerialVersionUID()); 10478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.SC_SERIALIZABLE); 10578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeShort((short) 0); // Zero fields 10678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA); 10778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson dout.writeByte(ObjectStreamConstants.TC_NULL); 10878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 10978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(IOException e) { 11078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("IOException: " + e.getMessage()); 11178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 11278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.FIRST_DATA = byteOut.toByteArray(); 11378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson buffers = new byte[][] {HEADER, FIRST_DATA, REPEATING_DATA}; 11478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 11578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 11678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private void advanceBuffer() { 11778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson pointer = 0; 11878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson sequence = NEXT[sequence]; 11978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson data = buffers[sequence]; 12078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 12178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 122eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 12378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public int read() throws IOException { 12478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson int result = data[pointer++]; 12578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson if(pointer >= data.length) { 12678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson advanceBuffer(); 12778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 12878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 12978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return result; 13078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 13178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 132eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 13378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public int available() throws IOException { 13478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return Integer.MAX_VALUE; 13578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 13678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 137eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 13878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson public int read(byte[] b, int off, int len) throws IOException { 13978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson int left = len; 14078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson int remaining = data.length - pointer; 14178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 14278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson while(remaining <= left) { 14378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson System.arraycopy(data, pointer, b, off, remaining); 14478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson off += remaining; 14578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson left -= remaining; 14678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson advanceBuffer(); 14778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson remaining = data.length - pointer; 14878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 14978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson if(left > 0) { 15078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson System.arraycopy(data, pointer, b, off, left); 15178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson pointer += left; 15278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 15378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 15478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson return len; 15578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 15678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 15778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 15878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson private ObjectInputStream inputStream; 15978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 160eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public ObjectInputStreamInstantiator(Class<T> clazz) { 16178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson if(Serializable.class.isAssignableFrom(clazz)) { 16278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 16378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson this.inputStream = new ObjectInputStream(new MockStream(clazz)); 16478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(IOException e) { 16678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("IOException: " + e.getMessage()); 16778c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16878c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 16978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson else { 170eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin throw new ObjenesisException(new NotSerializableException(clazz + " not serializable")); 17178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 17278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 17378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson 174eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @SuppressWarnings("unchecked") 175eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public T newInstance() { 17678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson try { 177eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return (T) inputStream.readObject(); 178eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 17978c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(ClassNotFoundException e) { 18078c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new Error("ClassNotFoundException: " + e.getMessage()); 18178c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 18278c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson catch(Exception e) { 18378c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson throw new ObjenesisException(e); 18478c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 18578c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson } 18678c496fe0fac4c89993109340aec80d1afa3141fIan Parkinson} 187