1   package org.neo.swarm.core.aop.silc.comp;
2   
3   import java.io.ByteArrayOutputStream;
4   import java.io.ObjectOutputStream;
5   import java.io.Serializable;
6   import java.lang.reflect.Method;
7   
8   import junit.framework.TestCase;
9   
10  import org.aopalliance.intercept.MethodInvocation;
11  import org.neo.swarm.core.aop.AspectComponent;
12  
13  public class AspectedComponentTest extends TestCase {
14  	private TestInterceptor a;
15  	private TestInterceptor b;
16  	private TestInterceptor c;
17  
18  	protected void setUp() throws Exception {
19  		a = new TestInterceptor("A");
20  		b = new TestInterceptor("B");
21  		c = new TestInterceptor("C");
22  	}
23  
24  	public void testSomethingAboutTheMixin() throws Throwable {
25  		Comp target = new Comp();
26  		AspectComponent mixin = new AspectComponentImpl("dummyKey", target.getClass().getInterfaces(), target, new JavaDynamicProxyFactory());
27  		addInterceptors(mixin);
28  
29  		A1 proxy = (A1) mixin.getProxy();
30  		proxy.doA1();
31  		assertions();
32  		assertTrue(target.invoked);
33  	}
34  
35  	private void assertions() {
36  		assertTrue(a.invoked);
37  		assertTrue(b.invoked);
38  		assertTrue(c.invoked);
39  	}
40  
41  	public void testCanGetAllInterfaceMethods() {
42  		CompB b = new CompB();
43  		AspectComponent ac = new AspectComponentImpl("dummyKey", b.getClass().getInterfaces(), b, new JavaDynamicProxyFactory());
44  		Method [] m = ac.getInterfaceMethods();
45  		assertEquals(4, m.length);
46  	}
47  
48  	public void testMultipleInterfaces() throws Throwable {
49  		CompB b = new CompB();
50  		AspectComponent mixin = new AspectComponentImpl("dummyKey", b.getClass().getInterfaces(), b, new JavaDynamicProxyFactory());
51  		addInterceptors(mixin);
52  		Object proxy = mixin.getProxy();
53  
54  		// casts are to prove that the proxy does indeed implement multiple interfaces
55  		((A1) proxy).doA1();
56  		assertions();
57  		assertTrue(b.a1);
58  		reset();
59  
60  
61  		((A2) proxy).doA2();
62  		assertions();
63  		assertTrue(b.a2);
64  		reset();
65  
66  		((B1) proxy).doB1();
67  		assertions();
68  		assertTrue(b.b1);
69  		reset();
70  
71  		((B2) proxy).doB2();
72  		assertions();
73  		assertTrue(b.b2);
74  
75  	}
76  
77  	public void testOnlyImplementsSuppliedInterfaces() throws Throwable {
78  		CompB b = new CompB();
79  		AspectComponent mixin = new AspectComponentImpl("dummyKey", new Class[]{A1.class, A2.class, B1.class}, b, new JavaDynamicProxyFactory());
80  		addInterceptors(mixin);
81  		Object proxy = mixin.getProxy();
82  
83  		((A1) proxy).doA1();
84  		assertions();
85  		assertTrue(b.a1);
86  		reset();
87  
88  		((A2) proxy).doA2();
89  		assertions();
90  		assertTrue(b.a2);
91  		reset();
92  
93  		((B1) proxy).doB1();
94  		assertions();
95  		assertTrue(b.b1);
96  		reset();
97  
98  		try {
99  			((B2) proxy).doB2();
100 			fail();
101 		} catch (ClassCastException cce) {
102 
103 		}
104 
105 	}
106 
107 	public void testCanHaveInterceptorsAppliedToDifferentMethods() throws Exception {
108 		CompC comp = new CompC();
109 
110 		AspectComponent mixin = new AspectComponentImpl("dummyKey", new Class[]{C1.class}, comp, new JavaDynamicProxyFactory());
111 		// apply to all
112 		mixin.addInterceptor(Perspective.DEFAULT, a);
113 		// apply to only this method
114 		mixin.addInterceptor(Perspective.DEFAULT, C1.class.getMethod("doC1", null), b);
115 		mixin.addInterceptor(Perspective.DEFAULT, C1.class.getMethod("doC1Again", null), c);
116 
117 		C1 proxy = (C1) mixin.getProxy();
118 
119 		proxy.doC1();
120 		assertTrue(a.invoked);
121 		assertTrue(b.invoked);
122 		assertFalse(c.invoked);
123 		reset();
124 
125 		proxy.doC1Again();
126 		assertTrue(a.invoked);
127 		assertFalse(b.invoked);
128 		assertTrue(c.invoked);
129 	}
130 
131 	/***
132 	 *
133 	 * @throws Exception
134 	 */
135 	public void testComponentsAreSerializable() throws Exception  {
136 		CompC comp = new CompC();
137 		AspectComponent mixin = new AspectComponentImpl("dummyKey", new Class[]{C1.class}, comp, new JavaDynamicProxyFactory());
138 		ByteArrayOutputStream baos = new ByteArrayOutputStream();
139 		ObjectOutputStream os = new ObjectOutputStream(baos);
140 		os.writeObject(mixin);
141 	}
142 
143 	
144 	public void testWeCanAssociateDifferentPerspectivesWithAComponent() throws Exception {
145 		Comp target = new Comp();
146 		TestInterceptor tInterceptor = new TestInterceptor("TestPerspective1");
147 		AspectComponent mixin = new AspectComponentImpl("dummyKey", target.getClass().getInterfaces(), target, new JavaDynamicProxyFactory());
148 		mixin.addInterceptor(Perspective.REMOTE, tInterceptor);
149 		mixin.addInterceptor(Perspective.REMOTE, new TestInterceptor("Test Perspective2"));
150 		mixin.addInterceptor(Perspective.DEFAULT,  new TestInterceptor("Default Perspective1"));
151 		mixin.addInterceptor(Perspective.DEFAULT,  new TestInterceptor("Default Perspective2"));
152 		A1  comp1 = (A1) mixin.getProxy();
153 		A1 comp2 = (A1) mixin.getProxy(Perspective.REMOTE);
154 		comp1.doA1();
155 		comp2.doA1();
156 		assertEquals(1, tInterceptor.count);
157 	}
158 	
159 	private void reset() {
160 		a.invoked = false;
161 		b.invoked = false;
162 		c.invoked = false;
163 	}
164 
165 	private void addInterceptors(AspectComponent mixin) {
166 		mixin.addInterceptor(Perspective.DEFAULT, a);
167 		mixin.addInterceptor(Perspective.DEFAULT, b);
168 		mixin.addInterceptor(Perspective.DEFAULT, c);
169 	}
170 
171 	static class TestInterceptor implements MethodInterceptor {
172 		private String name;
173 
174 		boolean invoked;
175 		int count = 0;
176 
177 		public TestInterceptor(String name) {
178 			this.name = name;
179 		}
180 
181 		public Object invoke(MethodInvocation invocation) throws Throwable {
182 			System.out.println("invoked interceptor: " + name);
183 			invoked = true;
184 			count++;
185 			return invocation.proceed();
186 		}
187 	}
188 	
189 	static interface MyInterceptorClassification {
190 	}
191 	static class TestInterceptor2 implements MethodInterceptor, MyInterceptorClassification {
192 		private String name;
193 
194 		boolean invoked;
195 
196 		public TestInterceptor2(String name) {
197 			this.name = name;
198 		}
199 
200 		public Object invoke(MethodInvocation invocation) throws Throwable {
201 			invoked = true;
202 			return invocation.proceed();
203 		}
204 	}
205 	
206 	interface A1 {
207 		void doA1();
208 	}
209 
210 	interface A2 {
211 		void doA2();
212 	}
213 
214 	interface B1 {
215 		void doB1();
216 	}
217 
218 	interface B2 {
219 		void doB2();
220 	}
221 
222 	static class Comp implements A1 {
223 		boolean invoked;
224 
225 		public void doA1() {
226 			invoked = true;
227 			System.out.println("Comp was invoked");
228 		}
229 	}
230 
231 	static class CompB implements A1, A2, B1, B2 {
232 		boolean a1;
233 		boolean a2;
234 		boolean b1;
235 		boolean b2;
236 		private boolean compB;
237 
238 		public void doA1() {
239 			a1 = true;
240 		}
241 
242 		public void doA2() {
243 			a2 = true;
244 		}
245 
246 		public void doB1() {
247 			b1 = true;
248 		}
249 
250 		public void doB2() {
251 			b2 = true;
252 		}
253 
254 		public void doCompB() {
255 			compB = true;
256 		}
257 
258 	}
259 
260 	interface C1 {
261 		void doC1();
262 
263 		void doC1Again();
264 
265 	}
266 
267 	static class CompC implements C1, Serializable  {
268 		public void doC1() {
269 		}
270 
271 		public void doC1Again() {
272 		}
273 
274 	}
275 }