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