1 | |
package org.apache.onami.autobind.configuration; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
import static com.google.inject.TypeLiteral.get; |
21 | |
import static java.lang.System.getProperty; |
22 | |
import static java.util.Collections.addAll; |
23 | |
import static java.util.logging.Level.FINE; |
24 | |
import static java.util.logging.Level.INFO; |
25 | |
import static java.util.logging.Logger.getLogger; |
26 | |
import static org.apache.onami.autobind.jsr330.Names.named; |
27 | |
|
28 | |
import java.io.File; |
29 | |
import java.net.MalformedURLException; |
30 | |
import java.net.URI; |
31 | |
import java.net.URISyntaxException; |
32 | |
import java.net.URL; |
33 | |
import java.net.URLClassLoader; |
34 | |
import java.util.ArrayList; |
35 | |
import java.util.Collections; |
36 | |
import java.util.HashSet; |
37 | |
import java.util.List; |
38 | |
import java.util.Set; |
39 | |
import java.util.logging.Logger; |
40 | |
|
41 | |
import org.apache.onami.autobind.annotations.features.AutoBindingFeature; |
42 | |
import org.apache.onami.autobind.annotations.features.ImplementationBindingFeature; |
43 | |
import org.apache.onami.autobind.annotations.features.ModuleBindingFeature; |
44 | |
import org.apache.onami.autobind.annotations.features.MultiBindingFeature; |
45 | |
import org.apache.onami.autobind.install.BindingTracer; |
46 | |
import org.apache.onami.autobind.install.InstallationContext; |
47 | |
import org.apache.onami.autobind.install.bindjob.BindingJob; |
48 | |
import org.apache.onami.autobind.scanner.ClasspathScanner; |
49 | |
import org.apache.onami.autobind.scanner.PackageFilter; |
50 | |
import org.apache.onami.autobind.scanner.ScannerModule; |
51 | |
import org.apache.onami.autobind.scanner.features.ScannerFeature; |
52 | |
import org.apache.onami.configuration.PropertiesURLReader; |
53 | |
|
54 | |
import com.google.inject.AbstractModule; |
55 | |
import com.google.inject.Binder; |
56 | |
import com.google.inject.Guice; |
57 | |
import com.google.inject.Injector; |
58 | |
import com.google.inject.Module; |
59 | |
import com.google.inject.multibindings.Multibinder; |
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | |
|
67 | |
|
68 | |
public abstract class StartupModule extends AbstractModule { |
69 | |
|
70 | 0 | protected final Logger _logger = getLogger(getClass().getName()); |
71 | |
|
72 | |
protected PackageFilter[] _packages; |
73 | |
|
74 | |
protected Class<? extends ClasspathScanner> _scanner; |
75 | |
|
76 | 0 | protected List<Class<? extends ScannerFeature>> _features = new ArrayList<Class<? extends ScannerFeature>>(); |
77 | |
|
78 | |
protected boolean bindSystemProperties; |
79 | |
|
80 | |
protected boolean bindEnvironment; |
81 | |
|
82 | 0 | protected boolean bindStartupConfiguration = true; |
83 | |
|
84 | 0 | protected boolean verbose = (getProperty("org.apache.onami.autobind.verbose") != null ? true |
85 | |
: false); |
86 | |
|
87 | |
public StartupModule(Class<? extends ClasspathScanner> scanner, |
88 | 0 | PackageFilter... filter) { |
89 | 0 | _packages = (filter == null ? new PackageFilter[0] : filter); |
90 | 0 | _scanner = scanner; |
91 | 0 | } |
92 | |
|
93 | |
@Override |
94 | |
public void configure() { |
95 | 0 | List<PackageFilter> packages = new ArrayList<PackageFilter>(); |
96 | 0 | addAll(packages, _packages); |
97 | 0 | addAll(packages, bindPackages()); |
98 | |
|
99 | 0 | _packages = packages.toArray(new PackageFilter[packages.size()]); |
100 | 0 | Module scannerModule = new AbstractModule() { |
101 | |
@Override |
102 | |
protected void configure() { |
103 | 0 | Binder binder = binder(); |
104 | 0 | if (_logger.isLoggable(FINE)) { |
105 | 0 | _logger.fine("Binding ClasspathScanner to " |
106 | |
+ _scanner.getName()); |
107 | 0 | for (PackageFilter p : _packages) { |
108 | 0 | _logger.fine("Using Package " + p + " for scanning."); |
109 | |
} |
110 | |
} |
111 | |
|
112 | 0 | binder.bind(InstallationContext.class).asEagerSingleton(); |
113 | 0 | binder.bind(ClasspathScanner.class).to(_scanner); |
114 | 0 | binder.bind(get(PackageFilter[].class)) |
115 | |
.annotatedWith(named("packages")).toInstance(_packages); |
116 | 0 | Set<URL> classpath = findClassPaths(); |
117 | 0 | binder.bind(get(URL[].class)) |
118 | |
.annotatedWith(named("classpath")) |
119 | |
.toInstance( |
120 | |
classpath.toArray(new URL[classpath.size()])); |
121 | |
|
122 | 0 | bindFeatures(binder); |
123 | 0 | } |
124 | |
}; |
125 | |
|
126 | 0 | ConfigurationModule configurationModule = new ConfigurationModule(); |
127 | 0 | if (bindSystemProperties) { |
128 | 0 | configurationModule.bindSystemProperties(); |
129 | |
} |
130 | 0 | if (bindEnvironment) { |
131 | 0 | configurationModule.bindEnvironmentVariables(); |
132 | |
} |
133 | |
|
134 | 0 | if (bindStartupConfiguration) { |
135 | 0 | URL startup = getClass().getResource("/conf/startup.xml"); |
136 | 0 | if (startup != null) { |
137 | |
try { |
138 | 0 | URI startupURI = startup.toURI(); |
139 | 0 | _logger.log(INFO, "Startup Config is used from Path: " |
140 | |
+ startupURI); |
141 | 0 | PropertiesURLReader reader = new PropertiesURLReader( |
142 | |
startup); |
143 | 0 | reader.inXMLFormat(); |
144 | 0 | configurationModule.addConfigurationReader(reader); |
145 | 0 | } catch (URISyntaxException e) { |
146 | 0 | _logger.log(INFO, |
147 | |
"Startup Config couldn't be found in Classpath.", e); |
148 | 0 | } |
149 | |
} else { |
150 | 0 | _logger.log(INFO, |
151 | |
"Startup Config couldn't be found, so it is not used."); |
152 | |
} |
153 | |
} |
154 | |
|
155 | 0 | Injector internal = Guice.createInjector(scannerModule, |
156 | |
configurationModule); |
157 | 0 | binder().install(internal.getInstance(ScannerModule.class)); |
158 | 0 | binder().install(configurationModule); |
159 | |
|
160 | 0 | if (verbose) { |
161 | 0 | BindingTracer tracer = internal.getInstance(BindingTracer.class); |
162 | |
|
163 | 0 | StringBuilder builder = new StringBuilder( |
164 | |
"Following Binding were processed.\n"); |
165 | 0 | for (BindingJob job : tracer) { |
166 | 0 | builder.append(job.toString()).append("\n"); |
167 | |
} |
168 | 0 | _logger.info(builder.toString()); |
169 | |
} |
170 | 0 | } |
171 | |
|
172 | |
protected abstract Multibinder<ScannerFeature> bindFeatures(Binder binder); |
173 | |
|
174 | |
protected PackageFilter[] bindPackages() { |
175 | 0 | return new PackageFilter[0]; |
176 | |
} |
177 | |
|
178 | |
protected Set<URL> findClassPaths() { |
179 | 0 | Set<URL> urlSet = new HashSet<URL>(); |
180 | |
|
181 | 0 | ClassLoader loader = Thread.currentThread().getContextClassLoader(); |
182 | 0 | while (loader != null) { |
183 | 0 | if (loader instanceof URLClassLoader) { |
184 | 0 | URL[] urls = ((URLClassLoader) loader).getURLs(); |
185 | 0 | Collections.addAll(urlSet, urls); |
186 | |
} |
187 | 0 | loader = loader.getParent(); |
188 | |
} |
189 | |
|
190 | 0 | String classpath = System.getProperty("java.class.path"); |
191 | 0 | if (classpath != null && classpath.length() > 0) { |
192 | |
try { |
193 | 0 | URL resource = StartupModule.class.getResource("/"); |
194 | |
|
195 | 0 | if (resource == null) { |
196 | 0 | String className = StartupModule.class.getName().replace( |
197 | |
'.', '/') |
198 | |
+ ".class"; |
199 | 0 | resource = StartupModule.class.getResource(className); |
200 | |
|
201 | 0 | if (resource != null) { |
202 | 0 | String url = resource.toExternalForm(); |
203 | 0 | url = url.substring(0, |
204 | |
url.length() - className.length()); |
205 | 0 | resource = new URL(url); |
206 | |
} |
207 | |
} |
208 | |
|
209 | 0 | if (resource != null) { |
210 | 0 | classpath = classpath + File.pathSeparator |
211 | |
+ new File(resource.toURI()).getAbsolutePath(); |
212 | |
} |
213 | 0 | } catch (URISyntaxException e) { |
214 | |
|
215 | 0 | } catch (MalformedURLException e) { |
216 | |
|
217 | 0 | } |
218 | |
|
219 | 0 | for (String path : classpath.split(File.pathSeparator)) { |
220 | 0 | File file = new File(path); |
221 | |
try { |
222 | 0 | if (file.exists()) { |
223 | 0 | urlSet.add(file.toURI().toURL()); |
224 | |
} |
225 | 0 | } catch (MalformedURLException e) { |
226 | 0 | _logger.log(INFO, |
227 | |
"Found invalid URL in Classpath: " + path, e); |
228 | 0 | } |
229 | |
} |
230 | |
} |
231 | |
|
232 | 0 | return urlSet; |
233 | |
} |
234 | |
|
235 | |
public StartupModule addFeature(Class<? extends ScannerFeature> listener) { |
236 | 0 | _features.add(listener); |
237 | 0 | return this; |
238 | |
} |
239 | |
|
240 | |
public StartupModule bindSystemProperties() { |
241 | 0 | bindSystemProperties = true; |
242 | 0 | return this; |
243 | |
} |
244 | |
|
245 | |
public StartupModule disableStartupConfiguration() { |
246 | 0 | bindStartupConfiguration = false; |
247 | 0 | return this; |
248 | |
} |
249 | |
|
250 | |
public StartupModule bindEnvironment() { |
251 | 0 | bindEnvironment = true; |
252 | 0 | return this; |
253 | |
} |
254 | |
|
255 | |
public void verbose() { |
256 | 0 | verbose = true; |
257 | 0 | } |
258 | |
|
259 | |
public static StartupModule create( |
260 | |
Class<? extends ClasspathScanner> scanner, PackageFilter... filter) { |
261 | 0 | return new DefaultStartupModule(scanner, filter); |
262 | |
} |
263 | |
|
264 | |
public static class DefaultStartupModule extends StartupModule { |
265 | |
public DefaultStartupModule(Class<? extends ClasspathScanner> scanner, |
266 | |
PackageFilter... filter) { |
267 | 0 | super(scanner, filter); |
268 | 0 | } |
269 | |
|
270 | |
@Override |
271 | |
protected Multibinder<ScannerFeature> bindFeatures(Binder binder) { |
272 | 0 | Multibinder<ScannerFeature> listeners = Multibinder.newSetBinder( |
273 | |
binder, ScannerFeature.class); |
274 | 0 | listeners.addBinding().to(AutoBindingFeature.class); |
275 | 0 | listeners.addBinding().to(ImplementationBindingFeature.class); |
276 | 0 | listeners.addBinding().to(MultiBindingFeature.class); |
277 | 0 | listeners.addBinding().to(ModuleBindingFeature.class); |
278 | |
|
279 | 0 | for (Class<? extends ScannerFeature> listener : _features) { |
280 | 0 | listeners.addBinding().to(listener); |
281 | |
} |
282 | |
|
283 | 0 | return listeners; |
284 | |
} |
285 | |
|
286 | |
@Override |
287 | |
protected PackageFilter[] bindPackages() { |
288 | |
try { |
289 | 0 | return new PackageFilter[] { PackageFilter |
290 | |
.create(Thread |
291 | |
.currentThread() |
292 | |
.getContextClassLoader() |
293 | |
.loadClass( |
294 | |
"org.apache.onami.autobind.configuration.ConfigurationModule"), |
295 | |
false) }; |
296 | 0 | } catch (ClassNotFoundException e) { |
297 | |
|
298 | 0 | e.printStackTrace(); |
299 | 0 | return new PackageFilter[0]; |
300 | |
} |
301 | |
} |
302 | |
} |
303 | |
|
304 | |
} |