1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.composite.specialize.specializers;
17
18 import java.lang.reflect.InvocationHandler;
19 import java.lang.reflect.Proxy;
20 import java.util.List;
21
22 import net.sf.composite.specialize.SpecializationException;
23 import net.sf.composite.specialize.Specializer;
24 import net.sf.composite.util.ClassUtils;
25 import net.sf.composite.util.ContainerUtils;
26 import net.sf.composite.util.DelegatingInvocationHandler;
27 import net.sf.composite.util.ObjectUtils;
28
29 /***
30 * <p>
31 * A composite specializer that is implemented using JDK 1.3 proxies. This
32 * specializer requires that the composite to be specialized has a public
33 * no-argument constructor. It also requires that the specialized type be an
34 * interface, and any methods that are to be executed on the composite are
35 * expressed in a separate interface (i.e. they cannot be specified in the
36 * implementation class only). Finally, component access methods must be
37 * specified in an interface. The {@link net.sf.composite.SimpleComposite},
38 * {@link net.sf.composite.RegistryComposite} etc. interfaces can be used for
39 * this purpose.
40 * </p>
41 *
42 * <p>
43 * The main benefit of this specializer is that it does not require the
44 * composite to implement all the interfaces to which it may be specialized. The
45 * main drawback is that the use of JDK proxies is much slower than regular
46 * method calls (such as you would get when using the
47 * {@link net.sf.composite.specialize.specializers.CloningSpecializer}.
48 * </p>
49 *
50 * @author Matt Sgarlata
51 * @since Mar 11, 2005
52 */
53 public class Jdk13ProxySpecializer extends BaseSpecializer implements Specializer {
54
55 protected boolean isSpecializableImpl(Object composite,
56 Class specializedType) throws Exception {
57
58 if (!specializedType.isInterface()) {
59 throw new SpecializationException(ObjectUtils.getObjectDescription(specializedType) + " must be an interface");
60 }
61
62 List components = getComponentAccessor().getComponents(composite);
63
64 return
65 specializedType.isAssignableFrom(composite.getClass()) ||
66 ContainerUtils.hasElementOfType(components, specializedType);
67 }
68
69 protected Object createNewComposite(Object composite) throws Exception {
70 return composite.getClass().newInstance();
71 }
72
73 protected InvocationHandler createInvocationHandler(Object composite)
74 throws Exception {
75 return new DelegatingInvocationHandler(createNewComposite(composite));
76 }
77
78 protected Object specializeImpl(Object composite, Class specializedType) throws Exception {
79
80 if (specializedType.isAssignableFrom(composite.getClass())) {
81 return composite;
82 }
83
84 Class[] interfaces = ClassUtils.getInterfaces(composite.getClass());
85 Class[] newInterfaces = new Class[interfaces.length + 1];
86 System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length);
87 newInterfaces[interfaces.length] = specializedType;
88
89
90 Object newComposite = Proxy.newProxyInstance(
91 specializedType.getClassLoader(), newInterfaces,
92 createInvocationHandler(composite));
93
94 List components =
95 getComponentAccessor().getComponents(composite);
96
97 List specializedComponents =
98 ContainerUtils.getElementsOfType(components, specializedType);
99
100
101 getComponentAccessor().setComponents(newComposite,
102 specializedComponents);
103
104 return newComposite;
105
106 }
107 }