|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
ImplementationHidingComponentAdapter.java | 75% | 84.8% | 100% | 83.6% |
|
1 |
/*****************************************************************************
|
|
2 |
* Copyright (C) PicoContainer Organization. All rights reserved. *
|
|
3 |
* ------------------------------------------------------------------------- *
|
|
4 |
* The software in this package is published under the terms of the BSD *
|
|
5 |
* style license a copy of which has been included with this distribution in *
|
|
6 |
* the LICENSE.txt file. *
|
|
7 |
* *
|
|
8 |
* Original code by *
|
|
9 |
*****************************************************************************/
|
|
10 |
package org.picocontainer.defaults;
|
|
11 |
|
|
12 |
import org.picocontainer.ComponentAdapter;
|
|
13 |
import org.picocontainer.PicoInitializationException;
|
|
14 |
import org.picocontainer.PicoIntrospectionException;
|
|
15 |
|
|
16 |
import java.lang.reflect.InvocationHandler;
|
|
17 |
import java.lang.reflect.Method;
|
|
18 |
import java.lang.reflect.Proxy;
|
|
19 |
import java.util.ArrayList;
|
|
20 |
import java.util.List;
|
|
21 |
|
|
22 |
/**
|
|
23 |
* This component adapter makes it possible to hide the implementation
|
|
24 |
* of a real subject (behind a proxy).
|
|
25 |
* If the key of the component is of type {@link java.lang.Class} and that class represents an interface, the proxy
|
|
26 |
* will only implement the interface represented by that Class. Otherwise (if the key is
|
|
27 |
* something else), the proxy will implement all the interfaces of the underlying subject.
|
|
28 |
* In any case, the proxy will also implement
|
|
29 |
* {@link Swappable}, making it possible to swap out the underlying
|
|
30 |
* subject at runtime.
|
|
31 |
* <p>
|
|
32 |
* <em>
|
|
33 |
* Note that this class doesn't cache instances. If you want caching,
|
|
34 |
* use a {@link CachingComponentAdapter} around this one.
|
|
35 |
* </em>
|
|
36 |
*
|
|
37 |
* @deprecated Use {@link org.nanocontainer.proxytoys.HotSwappingComponentAdapter} instead.
|
|
38 |
* @author Paul Hammant
|
|
39 |
* @author Aslak Hellesøy
|
|
40 |
* @version $Revision: 1.15 $
|
|
41 |
*/
|
|
42 |
public class ImplementationHidingComponentAdapter extends DecoratingComponentAdapter { |
|
43 |
private static Method hotswap; |
|
44 |
static {
|
|
45 | 3 |
try {
|
46 | 3 |
hotswap = Swappable.class.getMethod("hotswap", new Class[]{Object.class}); |
47 |
} catch (NoSuchMethodException e) {
|
|
48 | 0 |
throw new InternalError(); |
49 |
} |
|
50 |
} |
|
51 |
|
|
52 |
private final boolean strict; |
|
53 |
|
|
54 |
/**
|
|
55 |
* Alternative constructor allowing to set interface-only strictness.
|
|
56 |
* @param delegate the delegate adapter
|
|
57 |
* @param strict true if the adapter should only accept classes that are hideable behind interfaces.
|
|
58 |
* If false, a non-implementation hidden instance will be created instead of throwing an exception.
|
|
59 |
*/
|
|
60 | 19 |
public ImplementationHidingComponentAdapter(ComponentAdapter delegate, boolean strict) { |
61 | 19 |
super(delegate);
|
62 | 19 |
this.strict = strict;
|
63 |
} |
|
64 |
|
|
65 |
|
|
66 |
/**
|
|
67 |
* Creates a strict ImplementationHidingComponentAdapter that will throw an exception
|
|
68 |
* when trying to instantiate a class that doesn't implement any interfaces.
|
|
69 |
* @param delegate the delegate adapter
|
|
70 |
*/
|
|
71 | 3 |
public ImplementationHidingComponentAdapter(ComponentAdapter delegate) {
|
72 | 3 |
this(delegate, true); |
73 |
} |
|
74 |
|
|
75 | 18 |
public Object getComponentInstance()
|
76 |
throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
|
|
77 |
|
|
78 | 18 |
List interfaces = new ArrayList();
|
79 | 18 |
if(getDelegate().getComponentKey() instanceof Class && ((Class)getDelegate().getComponentKey()).isInterface()) { |
80 | 5 |
interfaces.add(getDelegate().getComponentKey()); |
81 |
} else {
|
|
82 | 13 |
interfaces.addAll(ClassHierarchyIntrospector.getAllInterfaces(getDelegate().getComponentImplementation())); |
83 |
} |
|
84 | 18 |
if (interfaces.size() == 0) {
|
85 | 3 |
if(strict) {
|
86 | 0 |
throw new PicoIntrospectionException("Can't hide implementation for " + getDelegate().getComponentImplementation().getName() + ". It doesn't implement any interfaces."); |
87 |
} else {
|
|
88 | 3 |
return getDelegate().getComponentInstance();
|
89 |
} |
|
90 |
} |
|
91 | 15 |
interfaces.add(Swappable.class);
|
92 | 15 |
final DelegatingInvocationHandler delegatingInvocationHandler = new DelegatingInvocationHandler();
|
93 | 15 |
return Proxy.newProxyInstance(
|
94 |
getClass().getClassLoader(), |
|
95 |
(Class[]) interfaces.toArray(new Class[interfaces.size()]),
|
|
96 |
delegatingInvocationHandler); |
|
97 |
} |
|
98 |
|
|
99 | 11 |
private Object getDelegatedComponentInstance() {
|
100 | 11 |
return super.getComponentInstance(); |
101 |
} |
|
102 |
|
|
103 |
private class DelegatingInvocationHandler implements InvocationHandler { |
|
104 |
private Object delegatedInstance;
|
|
105 |
|
|
106 | 37 |
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
107 | 37 |
Class declaringClass = method.getDeclaringClass(); |
108 | 37 |
if (declaringClass.equals(Object.class)) { |
109 | 2 |
if (method.equals(ClassHierarchyIntrospector.hashCode)) {
|
110 |
// Return the hashCode of ourself, as Proxy.newProxyInstance() may
|
|
111 |
// return cached proxies. We want a unique hashCode for each created proxy!
|
|
112 | 2 |
return new Integer(System.identityHashCode(this)); |
113 |
} |
|
114 | 0 |
if (method.equals(ClassHierarchyIntrospector.equals)) {
|
115 | 0 |
return new Boolean(proxy == args[0]); |
116 |
} |
|
117 |
// If it's any other method defined by Object, call on ourself.
|
|
118 | 0 |
return method.invoke(this, args); |
119 | 35 |
} else if (hotswap.equals(method)) { |
120 | 6 |
return hotswap(args[0]);
|
121 |
} else {
|
|
122 | 29 |
if (delegatedInstance == null) { |
123 | 11 |
delegatedInstance = ImplementationHidingComponentAdapter.this.getDelegatedComponentInstance();
|
124 |
} |
|
125 | 29 |
return method.invoke(delegatedInstance, args);
|
126 |
} |
|
127 |
} |
|
128 |
|
|
129 | 6 |
private Object hotswap(Object newSubject) {
|
130 | 6 |
Object result = delegatedInstance; |
131 | 6 |
delegatedInstance = newSubject; |
132 | 6 |
return result;
|
133 |
} |
|
134 |
} |
|
135 |
} |
|
136 |
|
|