View Javadoc
1   /*
2    * Copyright 2002-2014 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  
17  package org.springframework.core;
18  
19  import java.io.Serializable;
20  import java.lang.reflect.Method;
21  import java.lang.reflect.ParameterizedType;
22  import java.lang.reflect.Type;
23  import java.lang.reflect.TypeVariable;
24  import java.util.Collection;
25  import java.util.Date;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.ListIterator;
30  import java.util.Map;
31  import java.util.concurrent.DelayQueue;
32  import java.util.concurrent.Delayed;
33  
34  import org.junit.Test;
35  
36  import org.springframework.util.ReflectionUtils;
37  
38  import static org.junit.Assert.*;
39  
40  /**
41   * @author Rob Harrop
42   * @author Juergen Hoeller
43   * @author Chris Beams
44   */
45  public class BridgeMethodResolverTests {
46  
47  	private static TypeVariable<?> findTypeVariable(Class<?> clazz, String name) {
48  		TypeVariable<?>[] variables = clazz.getTypeParameters();
49  		for (TypeVariable<?> variable : variables) {
50  			if (variable.getName().equals(name)) {
51  				return variable;
52  			}
53  		}
54  		return null;
55  	}
56  
57  	private static Method findMethodWithReturnType(String name, Class<?> returnType, Class<SettingsDaoImpl> targetType) {
58  		Method[] methods = targetType.getMethods();
59  		for (Method m : methods) {
60  			if (m.getName().equals(name) && m.getReturnType().equals(returnType)) {
61  				return m;
62  			}
63  		}
64  		return null;
65  	}
66  
67  
68  	@Test
69  	public void testFindBridgedMethod() throws Exception {
70  		Method unbridged = MyFoo.class.getDeclaredMethod("someMethod", String.class, Object.class);
71  		Method bridged = MyFoo.class.getDeclaredMethod("someMethod", Serializable.class, Object.class);
72  		assertFalse(unbridged.isBridge());
73  		assertTrue(bridged.isBridge());
74  
75  		assertEquals("Unbridged method not returned directly", unbridged, BridgeMethodResolver.findBridgedMethod(unbridged));
76  		assertEquals("Incorrect bridged method returned", unbridged, BridgeMethodResolver.findBridgedMethod(bridged));
77  	}
78  
79  	@Test
80  	public void testFindBridgedVarargMethod() throws Exception {
81  		Method unbridged = MyFoo.class.getDeclaredMethod("someVarargMethod", String.class, Object[].class);
82  		Method bridged = MyFoo.class.getDeclaredMethod("someVarargMethod", Serializable.class, Object[].class);
83  		assertFalse(unbridged.isBridge());
84  		assertTrue(bridged.isBridge());
85  
86  		assertEquals("Unbridged method not returned directly", unbridged, BridgeMethodResolver.findBridgedMethod(unbridged));
87  		assertEquals("Incorrect bridged method returned", unbridged, BridgeMethodResolver.findBridgedMethod(bridged));
88  	}
89  
90  	@Test
91  	public void testFindBridgedMethodInHierarchy() throws Exception {
92  		Method bridgeMethod = DateAdder.class.getMethod("add", Object.class);
93  		assertTrue(bridgeMethod.isBridge());
94  		Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(bridgeMethod);
95  		assertFalse(bridgedMethod.isBridge());
96  		assertEquals("add", bridgedMethod.getName());
97  		assertEquals(1, bridgedMethod.getParameterTypes().length);
98  		assertEquals(Date.class, bridgedMethod.getParameterTypes()[0]);
99  	}
100 
101 	@Test
102 	public void testIsBridgeMethodFor() throws Exception {
103 		Method bridged = MyBar.class.getDeclaredMethod("someMethod", String.class, Object.class);
104 		Method other = MyBar.class.getDeclaredMethod("someMethod", Integer.class, Object.class);
105 		Method bridge = MyBar.class.getDeclaredMethod("someMethod", Object.class, Object.class);
106 
107 		assertTrue("Should be bridge method", BridgeMethodResolver.isBridgeMethodFor(bridge, bridged, MyBar.class));
108 		assertFalse("Should not be bridge method", BridgeMethodResolver.isBridgeMethodFor(bridge, other, MyBar.class));
109 	}
110 
111 	@Test
112 	@Deprecated
113 	public void testCreateTypeVariableMap() throws Exception {
114 		Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(MyBar.class);
115 		TypeVariable<?> barT = findTypeVariable(InterBar.class, "T");
116 		assertEquals(String.class, typeVariableMap.get(barT));
117 
118 		typeVariableMap = GenericTypeResolver.getTypeVariableMap(MyFoo.class);
119 		TypeVariable<?> fooT = findTypeVariable(Foo.class, "T");
120 		assertEquals(String.class, typeVariableMap.get(fooT));
121 
122 		typeVariableMap = GenericTypeResolver.getTypeVariableMap(ExtendsEnclosing.ExtendsEnclosed.ExtendsReallyDeepNow.class);
123 		TypeVariable<?> r = findTypeVariable(Enclosing.Enclosed.ReallyDeepNow.class, "R");
124 		TypeVariable<?> s = findTypeVariable(Enclosing.Enclosed.class, "S");
125 		TypeVariable<?> t = findTypeVariable(Enclosing.class, "T");
126 		assertEquals(Long.class, typeVariableMap.get(r));
127 		assertEquals(Integer.class, typeVariableMap.get(s));
128 		assertEquals(String.class, typeVariableMap.get(t));
129 	}
130 
131 	@Test
132 	public void testDoubleParameterization() throws Exception {
133 		Method objectBridge = MyBoo.class.getDeclaredMethod("foo", Object.class);
134 		Method serializableBridge = MyBoo.class.getDeclaredMethod("foo", Serializable.class);
135 
136 		Method stringFoo = MyBoo.class.getDeclaredMethod("foo", String.class);
137 		Method integerFoo = MyBoo.class.getDeclaredMethod("foo", Integer.class);
138 
139 		assertEquals("foo(String) not resolved.", stringFoo, BridgeMethodResolver.findBridgedMethod(objectBridge));
140 		assertEquals("foo(Integer) not resolved.", integerFoo, BridgeMethodResolver.findBridgedMethod(serializableBridge));
141 	}
142 
143 	@Test
144 	public void testFindBridgedMethodFromMultipleBridges() throws Exception {
145 		Method loadWithObjectReturn = findMethodWithReturnType("load", Object.class, SettingsDaoImpl.class);
146 		assertNotNull(loadWithObjectReturn);
147 
148 		Method loadWithSettingsReturn = findMethodWithReturnType("load", Settings.class, SettingsDaoImpl.class);
149 		assertNotNull(loadWithSettingsReturn);
150 		assertNotSame(loadWithObjectReturn, loadWithSettingsReturn);
151 
152 		Method method = SettingsDaoImpl.class.getMethod("load");
153 		assertEquals(method, BridgeMethodResolver.findBridgedMethod(loadWithObjectReturn));
154 		assertEquals(method, BridgeMethodResolver.findBridgedMethod(loadWithSettingsReturn));
155 	}
156 
157 	@Test
158 	public void testFindBridgedMethodFromParent() throws Exception {
159 		Method loadFromParentBridge = SettingsDaoImpl.class.getMethod("loadFromParent");
160 		assertTrue(loadFromParentBridge.isBridge());
161 
162 		Method loadFromParent = AbstractDaoImpl.class.getMethod("loadFromParent");
163 		assertFalse(loadFromParent.isBridge());
164 
165 		assertEquals(loadFromParent, BridgeMethodResolver.findBridgedMethod(loadFromParentBridge));
166 	}
167 
168 	@Test
169 	public void testWithSingleBoundParameterizedOnInstantiate() throws Exception {
170 		Method bridgeMethod = DelayQueue.class.getMethod("add", Object.class);
171 		assertTrue(bridgeMethod.isBridge());
172 		Method actualMethod = DelayQueue.class.getMethod("add", Delayed.class);
173 		assertFalse(actualMethod.isBridge());
174 		assertEquals(actualMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
175 	}
176 
177 	@Test
178 	public void testWithDoubleBoundParameterizedOnInstantiate() throws Exception {
179 		Method bridgeMethod = SerializableBounded.class.getMethod("boundedOperation", Object.class);
180 		assertTrue(bridgeMethod.isBridge());
181 		Method actualMethod = SerializableBounded.class.getMethod("boundedOperation", HashMap.class);
182 		assertFalse(actualMethod.isBridge());
183 		assertEquals(actualMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
184 	}
185 
186 	@Test
187 	public void testWithGenericParameter() throws Exception {
188 		Method[] methods = StringGenericParameter.class.getMethods();
189 		Method bridgeMethod = null;
190 		Method bridgedMethod = null;
191 		for (Method method : methods) {
192 			if ("getFor".equals(method.getName()) && !method.getParameterTypes()[0].equals(Integer.class)) {
193 				if (method.getReturnType().equals(Object.class)) {
194 					bridgeMethod = method;
195 				}
196 				else {
197 					bridgedMethod = method;
198 				}
199 			}
200 		}
201 		assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
202 		assertTrue(bridgedMethod != null && !bridgedMethod.isBridge());
203 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
204 	}
205 
206 	@Test
207 	public void testOnAllMethods() throws Exception {
208 		Method[] methods = StringList.class.getMethods();
209 		for (Method method : methods) {
210 			assertNotNull(BridgeMethodResolver.findBridgedMethod(method));
211 		}
212 	}
213 
214 	@Test
215 	public void testSPR2583() throws Exception {
216 		Method bridgedMethod = MessageBroadcasterImpl.class.getMethod("receive", MessageEvent.class);
217 		assertFalse(bridgedMethod.isBridge());
218 		Method bridgeMethod = MessageBroadcasterImpl.class.getMethod("receive", Event.class);
219 		assertTrue(bridgeMethod.isBridge());
220 
221 		Method otherMethod = MessageBroadcasterImpl.class.getMethod("receive", NewMessageEvent.class);
222 		assertFalse(otherMethod.isBridge());
223 
224 		assertFalse("Match identified incorrectly", BridgeMethodResolver.isBridgeMethodFor(bridgeMethod, otherMethod, MessageBroadcasterImpl.class));
225 		assertTrue("Match not found correctly", BridgeMethodResolver.isBridgeMethodFor(bridgeMethod, bridgedMethod, MessageBroadcasterImpl.class));
226 
227 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
228 	}
229 
230 	@Test
231 	@Deprecated
232 	public void testSPR2454() throws Exception {
233 		Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(YourHomer.class);
234 		TypeVariable<?> variable = findTypeVariable(MyHomer.class, "L");
235 		assertEquals(AbstractBounded.class, ((ParameterizedType) typeVariableMap.get(variable)).getRawType());
236 	}
237 
238 	@Test
239 	public void testSPR2603() throws Exception {
240 		Method objectBridge = YourHomer.class.getDeclaredMethod("foo", Bounded.class);
241 		Method abstractBoundedFoo = YourHomer.class.getDeclaredMethod("foo", AbstractBounded.class);
242 
243 		Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(objectBridge);
244 		assertEquals("foo(AbstractBounded) not resolved.", abstractBoundedFoo, bridgedMethod);
245 	}
246 
247 	@Test
248 	public void testSPR2648() throws Exception {
249 		Method bridgeMethod = ReflectionUtils.findMethod(GenericSqlMapIntegerDao.class, "saveOrUpdate", Object.class);
250 		assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
251 		Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(bridgeMethod);
252 		assertFalse(bridgedMethod.isBridge());
253 		assertEquals("saveOrUpdate", bridgedMethod.getName());
254 	}
255 
256 	@Test
257 	public void testSPR2763() throws Exception {
258 		Method bridgedMethod = AbstractDao.class.getDeclaredMethod("save", Object.class);
259 		assertFalse(bridgedMethod.isBridge());
260 
261 		Method bridgeMethod = UserDaoImpl.class.getDeclaredMethod("save", User.class);
262 		assertTrue(bridgeMethod.isBridge());
263 
264 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
265 	}
266 
267 	@Test
268 	public void testSPR3041() throws Exception {
269 		Method bridgedMethod = BusinessDao.class.getDeclaredMethod("save", Business.class);
270 		assertFalse(bridgedMethod.isBridge());
271 
272 		Method bridgeMethod = BusinessDao.class.getDeclaredMethod("save", Object.class);
273 		assertTrue(bridgeMethod.isBridge());
274 
275 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
276 	}
277 
278 	@Test
279 	public void testSPR3173() throws Exception {
280 		Method bridgedMethod = UserDaoImpl.class.getDeclaredMethod("saveVararg", User.class, Object[].class);
281 		assertFalse(bridgedMethod.isBridge());
282 
283 		Method bridgeMethod = UserDaoImpl.class.getDeclaredMethod("saveVararg", Object.class, Object[].class);
284 		assertTrue(bridgeMethod.isBridge());
285 
286 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
287 	}
288 
289 	@Test
290 	public void testSPR3304() throws Exception {
291 		Method bridgedMethod = MegaMessageProducerImpl.class.getDeclaredMethod("receive", MegaMessageEvent.class);
292 		assertFalse(bridgedMethod.isBridge());
293 
294 		Method bridgeMethod  = MegaMessageProducerImpl.class.getDeclaredMethod("receive", MegaEvent.class);
295 		assertTrue(bridgeMethod.isBridge());
296 
297 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
298 	}
299 
300 	@Test
301 	public void testSPR3324() throws Exception {
302 		Method bridgedMethod = BusinessDao.class.getDeclaredMethod("get", Long.class);
303 		assertFalse(bridgedMethod.isBridge());
304 
305 		Method bridgeMethod = BusinessDao.class.getDeclaredMethod("get", Object.class);
306 		assertTrue(bridgeMethod.isBridge());
307 
308 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
309 	}
310 
311 	@Test
312 	public void testSPR3357() throws Exception {
313 		Method bridgedMethod = ExtendsAbstractImplementsInterface.class.getDeclaredMethod(
314 				"doSomething", DomainObjectExtendsSuper.class, Object.class);
315 		assertFalse(bridgedMethod.isBridge());
316 
317 		Method bridgeMethod = ExtendsAbstractImplementsInterface.class.getDeclaredMethod(
318 				"doSomething", DomainObjectSuper.class, Object.class);
319 		assertTrue(bridgeMethod.isBridge());
320 
321 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
322 	}
323 
324 	@Test
325 	public void testSPR3485() throws Exception {
326 		Method bridgedMethod = DomainObject.class.getDeclaredMethod(
327 				"method2", ParameterType.class, byte[].class);
328 		assertFalse(bridgedMethod.isBridge());
329 
330 		Method bridgeMethod = DomainObject.class.getDeclaredMethod(
331 				"method2", Serializable.class, Object.class);
332 		assertTrue(bridgeMethod.isBridge());
333 
334 		assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
335 	}
336 
337 	@Test
338 	public void testSPR3534() throws Exception {
339 		Method bridgeMethod = ReflectionUtils.findMethod(TestEmailProvider.class, "findBy", Object.class);
340 		assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
341 		Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(bridgeMethod);
342 		assertFalse(bridgedMethod.isBridge());
343 		assertEquals("findBy", bridgedMethod.getName());
344 	}
345 
346 
347 	public static interface Foo<T extends Serializable> {
348 
349 		void someMethod(T theArg, Object otherArg);
350 
351 		void someVarargMethod(T theArg, Object... otherArg);
352 	}
353 
354 
355 	public static class MyFoo implements Foo<String> {
356 
357 		public void someMethod(Integer theArg, Object otherArg) {
358 		}
359 
360 		@Override
361 		public void someMethod(String theArg, Object otherArg) {
362 		}
363 
364 		@Override
365 		public void someVarargMethod(String theArg, Object... otherArgs) {
366 		}
367 	}
368 
369 
370 	public static abstract class Bar<T> {
371 
372 		void someMethod(Map<?, ?> m, Object otherArg) {
373 		}
374 
375 		void someMethod(T theArg, Map<?, ?> m) {
376 		}
377 
378 		abstract void someMethod(T theArg, Object otherArg);
379 	}
380 
381 
382 	public static abstract class InterBar<T> extends Bar<T> {
383 
384 	}
385 
386 
387 	public static class MyBar extends InterBar<String> {
388 
389 		@Override
390 		public void someMethod(String theArg, Object otherArg) {
391 		}
392 
393 		public void someMethod(Integer theArg, Object otherArg) {
394 		}
395 	}
396 
397 
398 	public static interface Adder<T> {
399 
400 		void add(T item);
401 	}
402 
403 
404 	public static abstract class AbstractDateAdder implements Adder<Date> {
405 
406 		@Override
407 		public abstract void add(Date date);
408 	}
409 
410 
411 	public static class DateAdder extends AbstractDateAdder {
412 
413 		@Override
414 		public void add(Date date) {
415 		}
416 	}
417 
418 
419 	public static class Enclosing<T> {
420 
421 		public class Enclosed<S> {
422 
423 			public class ReallyDeepNow<R> {
424 
425 				void someMethod(S s, T t, R r) {
426 				}
427 			}
428 		}
429 	}
430 
431 
432 	public static class ExtendsEnclosing extends Enclosing<String> {
433 
434 		public class ExtendsEnclosed extends Enclosed<Integer> {
435 
436 			public class ExtendsReallyDeepNow extends ReallyDeepNow<Long> {
437 
438 				@Override
439 				void someMethod(Integer s, String t, Long r) {
440 					throw new UnsupportedOperationException();
441 				}
442 			}
443 		}
444 	}
445 
446 
447 	public static interface Boo<E, T extends Serializable> {
448 
449 		void foo(E e);
450 
451 		void foo(T t);
452 	}
453 
454 
455 	public static class MyBoo implements Boo<String, Integer> {
456 
457 		@Override
458 		public void foo(String e) {
459 			throw new UnsupportedOperationException();
460 		}
461 
462 		@Override
463 		public void foo(Integer t) {
464 			throw new UnsupportedOperationException();
465 		}
466 	}
467 
468 
469 	public static interface Settings {
470 
471 	}
472 
473 
474 	public static interface ConcreteSettings extends Settings {
475 
476 	}
477 
478 
479 	public static interface Dao<T, S> {
480 
481 		T load();
482 
483 		S loadFromParent();
484 	}
485 
486 
487 	public static interface SettingsDao<T extends Settings, S> extends Dao<T, S> {
488 
489 		@Override
490 		T load();
491 	}
492 
493 
494 	public static interface ConcreteSettingsDao extends
495 			SettingsDao<ConcreteSettings, String> {
496 
497 		@Override
498 		String loadFromParent();
499 	}
500 
501 
502 	static abstract class AbstractDaoImpl<T, S> implements Dao<T, S> {
503 
504 		protected T object;
505 
506 		protected S otherObject;
507 
508 		protected AbstractDaoImpl(T object, S otherObject) {
509 			this.object = object;
510 			this.otherObject = otherObject;
511 		}
512 
513 		//@Transactional(readOnly = true)
514 		@Override
515 		public S loadFromParent() {
516 			return otherObject;
517 		}
518 	}
519 
520 
521 	static class SettingsDaoImpl extends AbstractDaoImpl<ConcreteSettings, String>
522 			implements ConcreteSettingsDao {
523 
524 		protected SettingsDaoImpl(ConcreteSettings object) {
525 			super(object, "From Parent");
526 		}
527 
528 		//@Transactional(readOnly = true)
529 		@Override
530 		public ConcreteSettings load() {
531 			return super.object;
532 		}
533 	}
534 
535 
536 	public static interface Bounded<E> {
537 
538 		boolean boundedOperation(E e);
539 	}
540 
541 
542 	private static class AbstractBounded<E> implements Bounded<E> {
543 
544 		@Override
545 		public boolean boundedOperation(E myE) {
546 			return true;
547 		}
548 	}
549 
550 
551 	private static class SerializableBounded<E extends HashMap & Delayed> extends AbstractBounded<E> {
552 
553 		@Override
554 		public boolean boundedOperation(E myE) {
555 			return false;
556 		}
557 	}
558 
559 
560 	public static interface GenericParameter<T> {
561 
562 		T getFor(Class<T> cls);
563 	}
564 
565 
566 	@SuppressWarnings("unused")
567 	private static class StringGenericParameter implements GenericParameter<String> {
568 
569 		@Override
570 		public String getFor(Class<String> cls) {
571 			return "foo";
572 		}
573 
574 		public String getFor(Integer integer) {
575 			return "foo";
576 		}
577 	}
578 
579 
580 	private static class StringList implements List<String> {
581 
582 		@Override
583 		public int size() {
584 			throw new UnsupportedOperationException();
585 		}
586 
587 		@Override
588 		public boolean isEmpty() {
589 			throw new UnsupportedOperationException();
590 		}
591 
592 		@Override
593 		public boolean contains(Object o) {
594 			throw new UnsupportedOperationException();
595 		}
596 
597 		@Override
598 		public Iterator<String> iterator() {
599 			throw new UnsupportedOperationException();
600 		}
601 
602 		@Override
603 		public Object[] toArray() {
604 			throw new UnsupportedOperationException();
605 		}
606 
607 		@Override
608 		public <T> T[] toArray(T[] a) {
609 			throw new UnsupportedOperationException();
610 		}
611 
612 		@Override
613 		public boolean add(String o) {
614 			throw new UnsupportedOperationException();
615 		}
616 
617 		@Override
618 		public boolean remove(Object o) {
619 			throw new UnsupportedOperationException();
620 		}
621 
622 		@Override
623 		public boolean containsAll(Collection<?> c) {
624 			throw new UnsupportedOperationException();
625 		}
626 
627 		@Override
628 		public boolean addAll(Collection<? extends String> c) {
629 			throw new UnsupportedOperationException();
630 		}
631 
632 		@Override
633 		public boolean addAll(int index, Collection<? extends String> c) {
634 			throw new UnsupportedOperationException();
635 		}
636 
637 		@Override
638 		public boolean removeAll(Collection<?> c) {
639 			throw new UnsupportedOperationException();
640 		}
641 
642 		@Override
643 		public boolean retainAll(Collection<?> c) {
644 			throw new UnsupportedOperationException();
645 		}
646 
647 		@Override
648 		public void clear() {
649 			throw new UnsupportedOperationException();
650 		}
651 
652 		@Override
653 		public String get(int index) {
654 			throw new UnsupportedOperationException();
655 		}
656 
657 		@Override
658 		public String set(int index, String element) {
659 			throw new UnsupportedOperationException();
660 		}
661 
662 		@Override
663 		public void add(int index, String element) {
664 			throw new UnsupportedOperationException();
665 		}
666 
667 		@Override
668 		public String remove(int index) {
669 			throw new UnsupportedOperationException();
670 		}
671 
672 		@Override
673 		public int indexOf(Object o) {
674 			throw new UnsupportedOperationException();
675 		}
676 
677 		@Override
678 		public int lastIndexOf(Object o) {
679 			throw new UnsupportedOperationException();
680 		}
681 
682 		@Override
683 		public ListIterator<String> listIterator() {
684 			throw new UnsupportedOperationException();
685 		}
686 
687 		@Override
688 		public ListIterator<String> listIterator(int index) {
689 			throw new UnsupportedOperationException();
690 		}
691 
692 		@Override
693 		public List<String> subList(int fromIndex, int toIndex) {
694 			throw new UnsupportedOperationException();
695 		}
696 	}
697 
698 
699 	public static interface Event {
700 
701 		int getPriority();
702 	}
703 
704 
705 	public static class GenericEvent implements Event {
706 
707 		private int priority;
708 
709 		@Override
710 		public int getPriority() {
711 			return priority;
712 		}
713 
714 		/**
715 		 * Constructor that takes an event priority
716 		 */
717 		public GenericEvent(int priority) {
718 			this.priority = priority;
719 		}
720 
721 		/**
722 		 * Default Constructor
723 		 */
724 		public GenericEvent() {
725 		}
726 	}
727 
728 
729 	public static interface UserInitiatedEvent {
730 
731 		//public Session getInitiatorSession();
732 	}
733 
734 
735 	public static abstract class BaseUserInitiatedEvent extends GenericEvent implements
736 			UserInitiatedEvent {
737 
738 	}
739 
740 
741 	public static class MessageEvent extends BaseUserInitiatedEvent {
742 
743 	}
744 
745 
746 	public static interface Channel<E extends Event> {
747 
748 		void send(E event);
749 
750 		void subscribe(final Receiver<E> receiver, Class<E> event);
751 
752 		void unsubscribe(final Receiver<E> receiver, Class<E> event);
753 	}
754 
755 
756 	public static interface Broadcaster {
757 	}
758 
759 
760 	public static interface EventBroadcaster extends Broadcaster {
761 
762 		public void subscribe();
763 
764 		public void unsubscribe();
765 
766 		public void setChannel(Channel<?> channel);
767 	}
768 
769 
770 	public static class GenericBroadcasterImpl implements Broadcaster {
771 
772 	}
773 
774 
775 	@SuppressWarnings({ "unused", "unchecked" })
776 	public static abstract class GenericEventBroadcasterImpl<T extends Event> extends
777 			GenericBroadcasterImpl
778 					implements EventBroadcaster {
779 
780 		private Class<T>[] subscribingEvents;
781 
782 		private Channel<T> channel;
783 
784 		/**
785 		 * Abstract method to retrieve instance of subclass
786 		 *
787 		 * @return receiver instance
788 		 */
789 		public abstract Receiver<T> getInstance();
790 
791 		@Override
792 		public void setChannel(Channel channel) {
793 			this.channel = channel;
794 		}
795 
796 		private String beanName;
797 
798 		public void setBeanName(String name) {
799 			this.beanName = name;
800 		}
801 
802 		@Override
803 		public void subscribe() {
804 
805 		}
806 
807 		@Override
808 		public void unsubscribe() {
809 
810 		}
811 
812 		public GenericEventBroadcasterImpl(Class<? extends T>... events) {
813 
814 		}
815 	}
816 
817 
818 	public static interface Receiver<E extends Event> {
819 
820 		void receive(E event);
821 	}
822 
823 
824 	public static interface MessageBroadcaster extends Receiver<MessageEvent> {
825 
826 	}
827 
828 
829 	public static class RemovedMessageEvent extends MessageEvent {
830 
831 	}
832 
833 
834 	public static class NewMessageEvent extends MessageEvent {
835 
836 	}
837 
838 
839 	public static class ModifiedMessageEvent extends MessageEvent {
840 
841 	}
842 
843 
844 	@SuppressWarnings("unchecked")
845 	public static class MessageBroadcasterImpl extends
846 			GenericEventBroadcasterImpl<MessageEvent>
847 					implements MessageBroadcaster {
848 
849 		public MessageBroadcasterImpl() {
850 			super(NewMessageEvent.class);
851 		}
852 
853 		@Override
854 		public void receive(MessageEvent event) {
855 			throw new UnsupportedOperationException("should not be called, use subclassed events");
856 		}
857 
858 		public void receive(NewMessageEvent event) {
859 		}
860 
861 		@Override
862 		public Receiver<MessageEvent> getInstance() {
863 			return null;
864 		}
865 
866 		public void receive(RemovedMessageEvent event) {
867 		}
868 
869 		public void receive(ModifiedMessageEvent event) {
870 		}
871 	}
872 
873 
874 	//-----------------------------
875 	// SPR-2454 Test Classes
876 	//-----------------------------
877 
878 	public static interface SimpleGenericRepository<T> {
879 
880 		public Class<T> getPersistentClass();
881 
882 		List<T> findByQuery();
883 
884 		List<T> findAll();
885 
886 		T refresh(T entity);
887 
888 		T saveOrUpdate(T entity);
889 
890 		void delete(Collection<T> entities);
891 	}
892 
893 
894 	public static interface RepositoryRegistry {
895 
896 		<T> SimpleGenericRepository<T> getFor(Class<T> entityType);
897 	}
898 
899 
900 	@SuppressWarnings("unchecked")
901 	public static class SettableRepositoryRegistry<R extends SimpleGenericRepository<?>>
902 					implements RepositoryRegistry {
903 
904 		protected void injectInto(R rep) {
905 		}
906 
907 		public void register(R rep) {
908 		}
909 
910 		public void register(R... reps) {
911 		}
912 
913 		public void setRepos(R... reps) {
914 		}
915 
916 		@Override
917 		public <T> SimpleGenericRepository<T> getFor(Class<T> entityType) {
918 			return null;
919 		}
920 
921 		public void afterPropertiesSet() throws Exception {
922 		}
923 	}
924 
925 
926 	public static interface ConvenientGenericRepository<T, ID extends Serializable>
927 			extends SimpleGenericRepository<T> {
928 
929 		T findById(ID id, boolean lock);
930 
931 		List<T> findByExample(T exampleInstance);
932 
933 		void delete(ID id);
934 
935 		void delete(T entity);
936 	}
937 
938 
939 	public static class GenericHibernateRepository<T, ID extends Serializable>
940 					implements ConvenientGenericRepository<T, ID> {
941 
942 		/**
943 		 * @param c Mandatory. The domain class this repository is responsible for.
944 		 */
945 		// Since it is impossible to determine the actual type of a type
946 		// parameter (!), we resort to requiring the caller to provide the
947 		// actual type as parameter, too.
948 		// Not set in a constructor to enable easy CGLIB-proxying (passing
949 		// constructor arguments to Spring AOP proxies is quite cumbersome).
950 		public void setPersistentClass(Class<T> c) {
951 		}
952 
953 		@Override
954 		public Class<T> getPersistentClass() {
955 			return null;
956 		}
957 
958 		@Override
959 		public T findById(ID id, boolean lock) {
960 			return null;
961 		}
962 
963 		@Override
964 		public List<T> findAll() {
965 			return null;
966 		}
967 
968 		@Override
969 		public List<T> findByExample(T exampleInstance) {
970 			return null;
971 		}
972 
973 		@Override
974 		public List<T> findByQuery() {
975 			return null;
976 		}
977 
978 		@Override
979 		public T saveOrUpdate(T entity) {
980 			return null;
981 		}
982 
983 		@Override
984 		public void delete(T entity) {
985 		}
986 
987 		@Override
988 		public T refresh(T entity) {
989 			return null;
990 		}
991 
992 		@Override
993 		public void delete(ID id) {
994 		}
995 
996 		@Override
997 		public void delete(Collection<T> entities) {
998 		}
999 	}
1000 
1001 
1002 	public static class HibernateRepositoryRegistry extends
1003 			SettableRepositoryRegistry<GenericHibernateRepository<?, ?>> {
1004 
1005 		@Override
1006 		public void injectInto(GenericHibernateRepository<?, ?> rep) {
1007 		}
1008 
1009 		@Override
1010 		public <T> GenericHibernateRepository<T, ?> getFor(Class<T> entityType) {
1011 			return null;
1012 		}
1013 	}
1014 
1015 
1016 	//-------------------
1017 	// SPR-2603 classes
1018 	//-------------------
1019 
1020 	public static interface Homer<E> {
1021 
1022 		void foo(E e);
1023 	}
1024 
1025 
1026 	public static class MyHomer<T extends Bounded<T>, L extends T> implements Homer<L> {
1027 
1028 		@Override
1029 		public void foo(L t) {
1030 			throw new UnsupportedOperationException();
1031 		}
1032 	}
1033 
1034 
1035 	public static class YourHomer<T extends AbstractBounded<T>, L extends T> extends
1036 			MyHomer<T, L> {
1037 
1038 		@Override
1039 		public void foo(L t) {
1040 			throw new UnsupportedOperationException();
1041 		}
1042 	}
1043 
1044 
1045 	public static interface GenericDao<T> {
1046 
1047 		public void saveOrUpdate(T t);
1048 	}
1049 
1050 
1051 	public static interface ConvenienceGenericDao<T> extends GenericDao<T> {
1052 	}
1053 
1054 
1055 	public static class GenericSqlMapDao<T extends Serializable> implements
1056 			ConvenienceGenericDao<T> {
1057 
1058 		@Override
1059 		public void saveOrUpdate(T t) {
1060 			throw new UnsupportedOperationException();
1061 		}
1062 	}
1063 
1064 
1065 	public static class GenericSqlMapIntegerDao<T extends Number> extends
1066 			GenericSqlMapDao<T> {
1067 
1068 		@Override
1069 		public void saveOrUpdate(T t) {
1070 		}
1071 	}
1072 
1073 
1074 	public static class Permission {
1075 	}
1076 
1077 
1078 	public static class User {
1079 	}
1080 
1081 
1082 	public static interface UserDao {
1083 
1084 		//@Transactional
1085 		void save(User user);
1086 
1087 		//@Transactional
1088 		void save(Permission perm);
1089 	}
1090 
1091 
1092 	public static abstract class AbstractDao<T> {
1093 
1094 		public void save(T t) {
1095 		}
1096 
1097 		public void saveVararg(T t, Object... args) {
1098 		}
1099 	}
1100 
1101 
1102 	public static class UserDaoImpl extends AbstractDao<User> implements UserDao {
1103 
1104 		@Override
1105 		public void save(Permission perm) {
1106 		}
1107 
1108 		@Override
1109 		public void saveVararg(User user, Object... args) {
1110 		}
1111 	}
1112 
1113 
1114 	public static interface DaoInterface<T, P> {
1115 			T get(P id);
1116 	}
1117 
1118 
1119 	public static abstract class BusinessGenericDao<T, PK extends Serializable>
1120 			implements DaoInterface<T, PK> {
1121 
1122 		public void save(T object) {
1123 		}
1124 	}
1125 
1126 
1127 	public static class Business<T> {
1128 	}
1129 
1130 
1131 	public static class BusinessDao extends BusinessGenericDao<Business<?>, Long> {
1132 
1133 		@Override
1134 		public void save(Business<?> business) {
1135 		}
1136 
1137 		@Override
1138 		public Business<?> get(Long id) {
1139 			return null;
1140 		}
1141 
1142 		public Business<?> get(String code) {
1143 			return null;
1144 		}
1145 	}
1146 
1147 
1148 	//-------------------
1149 	// SPR-3304 classes
1150 	//-------------------
1151 
1152 	private static class MegaEvent {
1153 	}
1154 
1155 
1156 	private static class MegaMessageEvent extends MegaEvent {
1157 	}
1158 
1159 
1160 	private static class NewMegaMessageEvent extends MegaEvent {
1161 	}
1162 
1163 
1164 	private static class ModifiedMegaMessageEvent extends MegaEvent {
1165 	}
1166 
1167 
1168 	public static interface MegaReceiver<E extends MegaEvent> {
1169 
1170 		void receive(E event);
1171 	}
1172 
1173 
1174 	public static interface MegaMessageProducer extends MegaReceiver<MegaMessageEvent> {
1175 	}
1176 
1177 
1178 	private static class Other<S,E> {
1179 	}
1180 
1181 
1182 	@SuppressWarnings("unused")
1183 	private static class MegaMessageProducerImpl extends Other<Long, String> implements MegaMessageProducer {
1184 
1185 		public void receive(NewMegaMessageEvent event) {
1186 			throw new UnsupportedOperationException();
1187 		}
1188 
1189 		public void receive(ModifiedMegaMessageEvent event) {
1190 			throw new UnsupportedOperationException();
1191 		}
1192 
1193 		@Override
1194 		public void receive(MegaMessageEvent event) {
1195 			throw new UnsupportedOperationException();
1196 		}
1197 	}
1198 
1199 
1200 	//-------------------
1201 	// SPR-3357 classes
1202 	//-------------------
1203 
1204 	private static class DomainObjectSuper {
1205 	}
1206 
1207 
1208 	private static class DomainObjectExtendsSuper extends DomainObjectSuper {
1209 	}
1210 
1211 
1212 	public static interface IGenericInterface<D extends DomainObjectSuper> {
1213 
1214 		<T> void doSomething(final D domainObject, final T value);
1215 	}
1216 
1217 
1218 	@SuppressWarnings("unused")
1219 	private static abstract class AbstractImplementsInterface<D extends DomainObjectSuper> implements IGenericInterface<D> {
1220 
1221 		@Override
1222 		public <T> void doSomething(D domainObject, T value) {
1223 		}
1224 
1225 		public void anotherBaseMethod() {
1226 		}
1227 	}
1228 
1229 
1230 	private static class ExtendsAbstractImplementsInterface extends AbstractImplementsInterface<DomainObjectExtendsSuper> {
1231 
1232 		@Override
1233 		public <T> void doSomething(DomainObjectExtendsSuper domainObject, T value) {
1234 			super.doSomething(domainObject, value);
1235 		}
1236 	}
1237 
1238 
1239 	//-------------------
1240 	// SPR-3485 classes
1241 	//-------------------
1242 
1243 	@SuppressWarnings("serial")
1244 	private static class ParameterType implements Serializable {
1245 	}
1246 
1247 
1248 	private static class AbstractDomainObject<P extends Serializable, R> {
1249 
1250 		public R method1(P p) {
1251 			return null;
1252 		}
1253 
1254 		public void method2(P p, R r) {
1255 		}
1256 	}
1257 
1258 
1259 	private static class DomainObject extends AbstractDomainObject<ParameterType, byte[]> {
1260 
1261 		@Override
1262 		public byte[] method1(ParameterType p) {
1263 			return super.method1(p);
1264 		}
1265 
1266 		@Override
1267 		public void method2(ParameterType p, byte[] r) {
1268 			super.method2(p, r);
1269 		}
1270 	}
1271 
1272 
1273 	//-------------------
1274 	// SPR-3534 classes
1275 	//-------------------
1276 
1277 	public static interface SearchProvider<RETURN_TYPE, CONDITIONS_TYPE> {
1278 
1279 		Collection<RETURN_TYPE> findBy(CONDITIONS_TYPE conditions);
1280 	}
1281 
1282 
1283 	public static class SearchConditions {
1284 	}
1285 
1286 
1287 	public static interface IExternalMessageProvider<S extends ExternalMessage, T extends ExternalMessageSearchConditions<?>>
1288 			extends SearchProvider<S, T> {
1289 	}
1290 
1291 
1292 	public static class ExternalMessage {
1293 	}
1294 
1295 
1296 	public static class ExternalMessageSearchConditions<T extends ExternalMessage> extends SearchConditions {
1297 	}
1298 
1299 
1300 	public static class ExternalMessageProvider<S extends ExternalMessage, T extends ExternalMessageSearchConditions<S>>
1301 			implements IExternalMessageProvider<S, T> {
1302 
1303 		@Override
1304 		public Collection<S> findBy(T conditions) {
1305 			return null;
1306 		}
1307 	}
1308 
1309 
1310 	public static class EmailMessage extends ExternalMessage {
1311 	}
1312 
1313 
1314 	public static class EmailSearchConditions extends ExternalMessageSearchConditions<EmailMessage> {
1315 	}
1316 
1317 
1318 	public static class EmailMessageProvider extends ExternalMessageProvider<EmailMessage, EmailSearchConditions> {
1319 	}
1320 
1321 
1322 	public static class TestEmailProvider extends EmailMessageProvider {
1323 
1324 		@Override
1325 		public Collection<EmailMessage> findBy(EmailSearchConditions conditions) {
1326 			return null;
1327 		}
1328 	}
1329 
1330 }