All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.devsurf.injection.guice.scanner.StartupModule Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2010 Daniel Manzke 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.devsurf.injection.guice.scanner;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import com.googlecode.rocoto.configuration.readers.EnvironmentVariablesReader;
import com.googlecode.rocoto.configuration.readers.PropertiesURLReader;
import com.googlecode.rocoto.configuration.readers.SystemPropertiesReader;

import de.devsurf.injection.guice.annotations.features.AutoBindingFeature;
import de.devsurf.injection.guice.annotations.features.ImplementationBindingFeature;
import de.devsurf.injection.guice.annotations.features.ModuleBindingFeature;
import de.devsurf.injection.guice.annotations.features.MultiBindingFeature;
import de.devsurf.injection.guice.configuration.ConfigurationModule;
import de.devsurf.injection.guice.install.BindingTracer;
import de.devsurf.injection.guice.install.InstallationContext;
import de.devsurf.injection.guice.install.bindjob.BindingJob;
import de.devsurf.injection.guice.scanner.features.ScannerFeature;

/**
 * The StartupModule is used for creating an initial Injector, which binds and
 * instantiates the Scanning module. Due the fact that we have multiple Scanner
 * Implementations, you have to pass the Class for the Scanner and the Packages
 * which should be scanned. You can override the bindAnnotationListeners-Method,
 * to add your own {@link ScannerFeature}.
 * 
 * @author Daniel Manzke
 * 
 */
public abstract class StartupModule extends AbstractModule {
	protected Logger _logger = Logger.getLogger(StartupModule.class.getName());
	protected PackageFilter[] _packages;
	protected Class _scanner;
	protected List> _features = new ArrayList>();
	protected boolean bindSystemProperties;
	protected boolean bindEnvironment;
	protected boolean bindStartupConfiguration = true;
	protected boolean verbose = (System.getProperty("gab.verbose") != null ? true :false);

	public StartupModule(Class scanner, PackageFilter... filter) {
		_packages = (filter == null ? new PackageFilter[0] : filter);
		_scanner = scanner;
	}

	@Override
	public void configure() {
		List packages = new ArrayList();
		Collections.addAll(packages, _packages);
		Collections.addAll(packages, bindPackages());
		
		_packages = packages.toArray(new PackageFilter[packages.size()]);
		Module scannerModule = new AbstractModule() {
			@Override
			protected void configure() {
				Binder binder = binder();
				if (_logger.isLoggable(Level.FINE)) {
					_logger.fine("Binding ClasspathScanner to " + _scanner.getName());
					for (PackageFilter p : _packages) {
						_logger.fine("Using Package " + p + " for scanning.");
					}
				}

				binder.bind(InstallationContext.class).asEagerSingleton();
				binder.bind(ClasspathScanner.class).to(_scanner);
				binder.bind(TypeLiteral.get(PackageFilter[].class)).annotatedWith(Names.named("packages"))
					.toInstance(_packages);
				Set classpath = findClassPaths();
				binder.bind(TypeLiteral.get(URL[].class)).annotatedWith(Names.named("classpath"))
					.toInstance(classpath.toArray(new URL[classpath.size()]));

				bindFeatures(binder);
			}
		};

		ConfigurationModule configurationModule = new ConfigurationModule();
		if (bindSystemProperties) {
			configurationModule.addConfigurationReader(new SystemPropertiesReader());
		}
		if (bindEnvironment) {
			configurationModule.addConfigurationReader(new EnvironmentVariablesReader());
		}
		
		if(bindStartupConfiguration){
			URL startup = getClass().getResource("/conf/startup.xml");
			if(startup != null){
				try {
					URI startupURI = startup.toURI();
					_logger.log(Level.INFO, "Startup Config is used from Path: "+startupURI);
					configurationModule.addConfigurationReader(new PropertiesURLReader(new File(startupURI), true));
				} catch (URISyntaxException e) {
					_logger.log(Level.INFO, "Startup Config couldn't be found in Classpath.", e);
				}	
			}else{
				_logger.log(Level.INFO, "Startup Config couldn't be found, so it is not used.");
			}			
		}
		
		Injector internal = Guice.createInjector(scannerModule, configurationModule);
		binder().install(internal.getInstance(ScannerModule.class));
		binder().install(configurationModule);
		
		if(verbose){
			BindingTracer tracer = internal.getInstance(BindingTracer.class);
			
			StringBuilder builder = new StringBuilder();
			builder.append("Following Binding were processed.\n");
			for(BindingJob job : tracer){
				builder.append(job.toString()).append("\n");
			}			
			_logger.info(builder.toString());
		}
	}

	protected abstract Multibinder bindFeatures(Binder binder);

	protected PackageFilter[] bindPackages() {
		return new PackageFilter[0];
	}

	protected Set findClassPaths() {
		Set urlSet = new HashSet();

		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		while (loader != null) {
			if (loader instanceof URLClassLoader) {
				URL[] urls = ((URLClassLoader) loader).getURLs();
				Collections.addAll(urlSet, urls);
			}
			loader = loader.getParent();
		}

		String classpath = System.getProperty("java.class.path");
		if(classpath != null && classpath.length() > 0){
			try {
				URL resource = StartupModule.class.getResource("/");
				if(resource != null){
					classpath = classpath + File.pathSeparator + new File(resource.toURI()).getAbsolutePath();	
				}
			} catch (URISyntaxException e) {
				// ignore
			}

			for (String path : classpath.split(File.pathSeparator)) {
				File file = new File(path);
				try {
					if (file.exists()) {
						urlSet.add(file.toURI().toURL());
					}
				} catch (MalformedURLException e) {
					_logger.log(Level.INFO, "Found invalid URL in Classpath: " + path, e);
				}
			}			
		}

		return urlSet;
	}

	public StartupModule addFeature(Class listener) {
		_features.add(listener);
		return this;
	}

	public StartupModule bindSystemProperties() {
		bindSystemProperties = true;
		return this;
	}
	
	public StartupModule disableStartupConfiguration() {
		bindStartupConfiguration = false;
		return this;
	}

	public StartupModule bindEnvironment() {
		bindEnvironment = true;
		return this;
	}
	
	public void verbose(){
		verbose = true;
	}

	public static StartupModule create(Class scanner,
			PackageFilter... filter) {
		return new DefaultStartupModule(scanner, filter);
	}

	public static class DefaultStartupModule extends StartupModule {
		public DefaultStartupModule(Class scanner, PackageFilter... filter) {
			super(scanner, filter);
		}

		@Override
		protected Multibinder bindFeatures(Binder binder) {
			Multibinder listeners = Multibinder.newSetBinder(binder,
				ScannerFeature.class);
			listeners.addBinding().to(AutoBindingFeature.class);
			listeners.addBinding().to(ImplementationBindingFeature.class);
			listeners.addBinding().to(MultiBindingFeature.class);
			listeners.addBinding().to(ModuleBindingFeature.class);

			for (Class listener : _features) {
				listeners.addBinding().to(listener);
			}

			return listeners;
		}

		@Override
		protected PackageFilter[] bindPackages() {
			return new PackageFilter[] { PackageFilter.create(ConfigurationModule.class, false) };
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy