1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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 }