View Javadoc
1   /**
2    *    Copyright 2009-2019 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.executor.loader;
17  
18  import static org.junit.jupiter.api.Assertions.assertEquals;
19  import static org.junit.jupiter.api.Assertions.assertFalse;
20  import static org.junit.jupiter.api.Assertions.fail;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.ByteArrayOutputStream;
24  import java.io.ObjectInputStream;
25  import java.io.ObjectOutputStream;
26  import java.io.ObjectStreamException;
27  import java.io.Serializable;
28  import java.lang.reflect.Method;
29  import java.util.ArrayList;
30  import org.apache.ibatis.domain.blog.Author;
31  import org.apache.ibatis.domain.blog.Section;
32  import org.apache.ibatis.executor.ExecutorException;
33  import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
34  import org.apache.ibatis.session.Configuration;
35  import org.junit.jupiter.api.Assertions;
36  import org.junit.jupiter.api.Test;
37  
38  public abstract class SerializableProxyTest {
39  
40    protected Authorblog/Author.html#Author">Author author = new Author(999, "someone", "!@#@!#!@#", "someone@somewhere.com", "blah", Section.NEWS);
41  
42    static ProxyFactory proxyFactory;
43  
44    @Test
45    void shouldKeepGenericTypes() {
46      for (int i = 0; i < 10000; i++) {
47        Authorain/blog/Author.html#Author">Author pc = new Author();
48        Author"../../../../../org/apache/ibatis/domain/blog/Author.html#Author">Author proxy = (Author) proxyFactory.createProxy(pc, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(),
49            new ArrayList<>(), new ArrayList<>());
50        proxy.getBio();
51      }
52    }
53  
54    @Test
55    void shouldSerializeAProxyForABeanWithDefaultConstructor() throws Exception {
56      Object proxy = proxyFactory.createProxy(author, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
57      Object proxy2 = deserialize(serialize((Serializable) proxy));
58      assertEquals(author, proxy2);
59    }
60  
61    @Test
62    void shouldSerializeAProxyForABeanWithoutDefaultConstructor() throws Exception {
63      AuthorWithoutDefaultConstructor author = new AuthorWithoutDefaultConstructor(999, "someone", "!@#@!#!@#", "someone@somewhere.com", "blah", Section.NEWS);
64      ArrayList<Class<?>> argTypes = new ArrayList<>();
65      argTypes.add(Integer.class);
66      argTypes.add(String.class);
67      argTypes.add(String.class);
68      argTypes.add(String.class);
69      argTypes.add(String.class);
70      argTypes.add(Section.class);
71      ArrayList<Object> argValues = new ArrayList<>();
72      argValues.add(999);
73      argValues.add("someone");
74      argValues.add("!@#@!#!@#");
75      argValues.add("someone@somewhere.com");
76      argValues.add("blah");
77      argValues.add(Section.NEWS);
78      Object proxy = proxyFactory.createProxy(author, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), argTypes, argValues);
79      Object proxy2 = deserialize(serialize((Serializable) proxy));
80      assertEquals(author, proxy2);
81    }
82  
83    @Test
84    void shouldSerializeAProxyForABeanWithoutDefaultConstructorAndUnloadedProperties() throws Exception {
85      AuthorWithoutDefaultConstructor author = new AuthorWithoutDefaultConstructor(999, "someone", "!@#@!#!@#", "someone@somewhere.com", "blah", Section.NEWS);
86      ArrayList<Class<?>> argTypes = new ArrayList<>();
87      argTypes.add(Integer.class);
88      argTypes.add(String.class);
89      argTypes.add(String.class);
90      argTypes.add(String.class);
91      argTypes.add(String.class);
92      argTypes.add(Section.class);
93      ArrayList<Object> argValues = new ArrayList<>();
94      argValues.add(999);
95      argValues.add("someone");
96      argValues.add("!@#@!#!@#");
97      argValues.add("someone@somewhere.com");
98      argValues.add("blah");
99      argValues.add(Section.NEWS);
100     ResultLoaderMap loader = new ResultLoaderMap();
101     loader.addLoader("id", null, null);
102     Object proxy = proxyFactory.createProxy(author, loader, new Configuration(), new DefaultObjectFactory(), argTypes, argValues);
103     Object proxy2 = deserialize(serialize((Serializable) proxy));
104     assertEquals(author, proxy2);
105   }
106 
107   @Test
108   void shouldSerizaliceAFullLoadedObjectToOriginalClass() throws Exception {
109     Object proxy = proxyFactory.createProxy(author, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
110     Object proxy2 = deserialize(serialize((Serializable) proxy));
111     assertEquals(author.getClass(), proxy2.getClass());
112   }
113 
114   @Test
115   void shouldGenerateWriteReplace() throws Exception {
116     try {
117       author.getClass().getDeclaredMethod("writeReplace");
118       fail("Author should not have a writeReplace method");
119     } catch (NoSuchMethodException e) {
120       // ok
121     }
122     Object proxy = proxyFactory.createProxy(author, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
123     Method m = proxy.getClass().getDeclaredMethod("writeReplace");
124   }
125 
126   @Test
127   void shouldNotGenerateWriteReplaceItThereIsAlreadyOne() {
128     AuthorWithWriteReplaceMethod beanWithWriteReplace = new AuthorWithWriteReplaceMethod(999, "someone", "!@#@!#!@#", "someone@somewhere.com", "blah", Section.NEWS);
129     try {
130       beanWithWriteReplace.getClass().getDeclaredMethod("writeReplace");
131     } catch (NoSuchMethodException e) {
132       fail("Bean should declare a writeReplace method");
133     }
134     Object proxy = proxyFactory.createProxy(beanWithWriteReplace, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
135     Class<?>[] interfaces = proxy.getClass().getInterfaces();
136     boolean ownInterfaceFound = false;
137     for (Class<?> i : interfaces) {
138       if (i.equals(WriteReplaceInterface.class)) {
139         ownInterfaceFound = true;
140         break;
141       }
142     }
143     assertFalse(ownInterfaceFound);
144   }
145 
146   @Test
147   void shouldNotCreateAProxyForAFullyLoadedBean() throws Exception {
148     Object proxy = proxyFactory.createProxy(author, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
149     Author./../../../../org/apache/ibatis/domain/blog/Author.html#Author">Author author2 = (Author) deserialize(serialize((Serializable) proxy));
150     assertEquals(author.getClass(), author2.getClass());
151   }
152 
153   @Test
154   void shouldNotLetReadUnloadedPropertyAfterSerialization() throws Exception {
155     ResultLoaderMap loader = new ResultLoaderMap();
156     loader.addLoader("id", null, null);
157     Object proxy = proxyFactory.createProxy(author, loader, new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
158     Author./../../../../org/apache/ibatis/domain/blog/Author.html#Author">Author author2 = (Author) deserialize(serialize((Serializable) proxy));
159     Assertions.assertThrows(ExecutorException.class, author2::getId);
160   }
161 
162   @Test
163   void shouldNotLetReadUnloadedPropertyAfterTwoSerializations() throws Exception {
164     ResultLoaderMap loader = new ResultLoaderMap();
165     loader.addLoader("id", null, null);
166     Object proxy = proxyFactory.createProxy(author, loader, new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
167     Author./../../../../org/apache/ibatis/domain/blog/Author.html#Author">Author author2 = (Author) deserialize(serialize(deserialize(serialize((Serializable) proxy))));
168     Assertions.assertThrows(ExecutorException.class, author2::getId);
169   }
170 
171   @Test
172   void shouldLetReadALoadedPropertyAfterSerialization() throws Exception {
173     Object proxy = proxyFactory.createProxy(author, new ResultLoaderMap(), new Configuration(), new DefaultObjectFactory(), new ArrayList<>(), new ArrayList<>());
174     byte[] ser = serialize((Serializable) proxy);
175     Author./../../../../org/apache/ibatis/domain/blog/Author.html#Author">Author author2 = (Author) deserialize(ser);
176     assertEquals(999, author2.getId());
177   }
178 
179   byte[] serialize(Serializable value) throws Exception {
180     try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
181         ObjectOutputStream oos = new ObjectOutputStream(bos)) {
182       oos.writeObject(value);
183       oos.flush();
184       return bos.toByteArray();
185     }
186   }
187 
188   Serializable deserialize(byte[] value) throws Exception {
189     try(ByteArrayInputStream bis = new ByteArrayInputStream(value);
190     ObjectInputStream ois = new ObjectInputStream(bis)) {
191       return (Serializable) ois.readObject();
192     }
193   }
194 
195   public static class AuthorWithWriteReplaceMethod extends Author {
196 
197     public AuthorWithWriteReplaceMethod() {
198     }
199 
200     AuthorWithWriteReplaceMethod(Integer id, String username, String password, String email, String bio, Section section) {
201         super(id, username, password, email, bio, section);
202     }
203 
204     Object writeReplace() throws ObjectStreamException {
205       return this;
206     }
207   }
208 
209   public static class AuthorWithoutDefaultConstructor extends Author {
210 
211     AuthorWithoutDefaultConstructor(Integer id, String username, String password, String email, String bio, Section section) {
212         super(id, username, password, email, bio, section);
213     }
214 
215     protected Object writeReplace() throws ObjectStreamException {
216       return this;
217     }
218   }
219 
220 }