1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.xchain.framework.scanner;
17
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.WeakHashMap;
23 import java.net.URL;
24
25 import org.xchain.framework.lifecycle.LifecycleClass;
26 import org.xchain.framework.lifecycle.LifecycleAccessor;
27 import org.apache.commons.collections.map.LRUMap;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31
32
33
34
35
36
37
38 @LifecycleClass(uri="http://www.xchain.org/scanner")
39 public class ScannerLifecycle
40 {
41
42
43
44 private static final boolean MEMOIZE_SCAN_NODE = true;
45 private static Logger log = LoggerFactory.getLogger(ScannerLifecycle.class);
46
47 private static ScannerLifecycle instance = new ScannerLifecycle();
48 private Map<ClassLoader, Map<RootUrlLocator, ScanNode>> cache;
49
50
51 @LifecycleAccessor
52 public static ScannerLifecycle getInstance()
53 {
54 return instance;
55 }
56
57 private Map<String, ProtocolScanner> protocolMap = new HashMap<String, ProtocolScanner>();
58
59 public ScannerLifecycle()
60 {
61 protocolMap.put("file", new FileProtocolScanner());
62 protocolMap.put("jar", new JarProtocolScanner());
63
64
65 if( isVfsDefined() ) {
66 protocolMap.put("vfszip", new VfsProtocolScanner());
67 protocolMap.put("vfsfile", new VfsProtocolScanner());
68 protocolMap.put("vfsmemory", new VfsProtocolScanner());
69 }
70 if( isZipDefined() ) {
71 protocolMap.put("zip", new ZipProtocolScanner());
72 }
73 if( isBundleDefined() ) {
74 protocolMap.put("bundle", new BundleProtocolScanner());
75 protocolMap.put("bundleresource", new BundleProtocolScanner());
76 }
77
78 if( MEMOIZE_SCAN_NODE ) {
79 cache = Collections.synchronizedMap(new WeakHashMap<ClassLoader, Map<RootUrlLocator,ScanNode>>());
80 }
81 }
82
83
84
85
86
87 public ScanNode scanNode()
88 throws Exception
89 {
90 return scanNode( Thread.currentThread().getContextClassLoader(), new MarkerResourceLocator("META-INF/xchain.xml") );
91 }
92
93
94
95
96 public ScanNode scanNode( RootUrlLocator locator )
97 throws Exception
98 {
99 return scanNode( Thread.currentThread().getContextClassLoader(), locator );
100 }
101
102 public ScanNode scanNode( ClassLoader classLoader, RootUrlLocator locator )
103 throws Exception
104 {
105 if( MEMOIZE_SCAN_NODE ) {
106 ScanNode cachedScanNode = getCached(classLoader, locator);
107 if( cachedScanNode != null ) {
108 log.debug("Using cached ScanNode instance '{}' for ClassLoader '{}' and RootUrlLocator '{}'.", new Object[] {cachedScanNode, classLoader, locator});
109 return cachedScanNode;
110 }
111 }
112
113 ScanNode rootScanNode = new ScanNode();
114 Set<URL> roots = locator.findRoots(Thread.currentThread().getContextClassLoader());
115
116 for( URL root : roots ) {
117
118 String protocol = root.getProtocol();
119 ProtocolScanner scanner = protocolMap.get(protocol);
120 if( scanner == null ) {
121 if( log.isDebugEnabled() ) {
122 log.debug("Could not scan protocol "+protocol+" of url "+root+", because a scanner for this protocol is not defined.");
123 }
124 continue;
125 }
126 scanner.scan(rootScanNode, root);
127 }
128
129 if( MEMOIZE_SCAN_NODE ) {
130 putCached(classLoader, locator, rootScanNode);
131 }
132 return rootScanNode;
133 }
134
135
136
137
138 public void clearCache() {
139 if( MEMOIZE_SCAN_NODE )
140 this.cache.clear();
141 }
142
143
144
145
146 private ScanNode getCached( ClassLoader classLoader, RootUrlLocator locator ) {
147 Map<RootUrlLocator, ScanNode> locatorScanNodeMap = cache.get(classLoader);
148 if( locatorScanNodeMap != null )
149 return locatorScanNodeMap.get(locator);
150 return null;
151 }
152
153
154
155
156 private void putCached( ClassLoader classLoader, RootUrlLocator locator, ScanNode scanNode ) {
157 Map<RootUrlLocator, ScanNode> locatorScanNodeMap = this.cache.get(classLoader);
158 if( locatorScanNodeMap == null ) {
159 locatorScanNodeMap = Collections.synchronizedMap(new LRUMap(20));
160 this.cache.put(classLoader, locatorScanNodeMap);
161 }
162 locatorScanNodeMap.put(locator, scanNode);
163 }
164
165 private boolean isVfsDefined() {
166 try {
167 Thread.currentThread().getContextClassLoader().loadClass("org.jboss.virtual.VirtualFile");
168
169 return true;
170 }
171 catch( Exception e ) {
172 return false;
173 }
174 }
175
176 private boolean isZipDefined() {
177 try {
178 Thread.currentThread().getContextClassLoader().loadClass("weblogic.utils.zip.ZipURLConnection");
179 return true;
180 }
181 catch( Exception e ) {
182 return false;
183 }
184 }
185
186 private boolean isBundleDefined() {
187 try {
188 Thread.currentThread().getContextClassLoader().loadClass("org.osgi.framework.Bundle");
189 return true;
190 }
191 catch( Exception e ) {
192 return false;
193 }
194 }
195 }