1 package org.codehaus.plexus.component.collections;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8
9 import org.codehaus.plexus.MutablePlexusContainer;
10 import org.codehaus.plexus.classworlds.ClassWorld;
11 import org.codehaus.plexus.classworlds.realm.ClassRealm;
12 import org.codehaus.plexus.component.repository.ComponentDescriptor;
13 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
14 import org.codehaus.plexus.logging.Logger;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 public abstract class AbstractComponentCollection<T> {
43
44 protected MutablePlexusContainer container;
45
46
47 protected final Class<T> componentType;
48
49
50 protected String role;
51
52
53 protected List<String> roleHints;
54
55
56 protected String hostComponent;
57
58
59 protected Logger logger;
60
61 private ClassLoader tccl;
62 private Collection<ClassRealm> realms;
63
64 private Map<String, ComponentDescriptor<T>> componentDescriptorMap;
65 private final ClassWorld world;
66
67 public AbstractComponentCollection(
68 final MutablePlexusContainer container,
69 final Class<T> componentType,
70 final String role,
71 final List<String> roleHints,
72 final String hostComponent) {
73 this.container = container;
74
75 this.componentType = componentType;
76
77 this.role = role;
78
79 this.roleHints = roleHints;
80
81 this.hostComponent = hostComponent;
82
83 logger = container.getLoggerManager().getLoggerForComponent(role);
84
85 world = container.getContainerRealm().getWorld();
86 }
87
88 private boolean realmsHaveChanged() {
89 return (tccl != Thread.currentThread().getContextClassLoader())
90 || (realms == null)
91 || (!realms.equals(world.getRealms()));
92 }
93
94 protected synchronized Map<String, ComponentDescriptor<T>> getComponentDescriptorMap() {
95 checkUpdate();
96
97 return componentDescriptorMap;
98 }
99
100 @SuppressWarnings("unchecked")
101 protected boolean checkUpdate() {
102 if (componentDescriptorMap != null && !realmsHaveChanged()) {
103 return false;
104 }
105
106 tccl = Thread.currentThread().getContextClassLoader();
107 Collection fromWorld = world.getRealms();
108 if (fromWorld == null || fromWorld.isEmpty()) {
109 realms = null;
110 } else {
111 realms = new HashSet<ClassRealm>(fromWorld);
112 }
113
114 Map<String, ComponentDescriptor<T>> componentMap = container.getComponentDescriptorMap(componentType, role);
115 Map<String, ComponentDescriptor<T>> newComponentDescriptors =
116 new HashMap<String, ComponentDescriptor<T>>(componentMap.size() * 2);
117
118 if (roleHints != null && !roleHints.isEmpty()) {
119 for (String roleHint : roleHints) {
120 ComponentDescriptor<T> componentDescriptor = componentMap.get(roleHint);
121 if (componentDescriptor != null) {
122 newComponentDescriptors.put(roleHint, componentDescriptor);
123 }
124 }
125 } else {
126 newComponentDescriptors.putAll(componentMap);
127 }
128
129 if (componentDescriptorMap == null || !newComponentDescriptors.equals(componentDescriptorMap)) {
130 componentDescriptorMap = newComponentDescriptors;
131
132 return true;
133 }
134
135 return false;
136 }
137
138 protected T lookup(ComponentDescriptor<T> componentDescriptor) {
139 T component = null;
140
141 try {
142 if (componentDescriptor != null) {
143 component = container.lookup(componentDescriptor);
144 }
145 } catch (ComponentLookupException e) {
146 logger.debug(
147 "Failed to lookup a member of active collection with role: " + role + " and role-hint: "
148 + componentDescriptor.getRoleHint(),
149 e);
150 }
151
152 return component;
153 }
154
155 public synchronized void clear() {
156 releaseAllCallback();
157
158 componentDescriptorMap = null;
159
160 tccl = null;
161 realms = null;
162 }
163
164 protected abstract void releaseAllCallback();
165 }