/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.service;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.diirt.util.config.Configuration;
/**
* A service provider that can create a service instance for each file in
* the configuration directory.
* <p>
* If the configuration directory does not exist, it is created. If the path given is
* not a directory, an empty list is return and a warning message is logged.
* By default, the configuration directory will be located in $DIIRT_HOME/services/SERVICE_PROVIDER_NAME.
* <p>
* This class provides the crawling of the configuration directory
* and the logging of both service creation and errors.
*
* @author carcassi
*/
public abstract class AbstractFileServiceProvider implements ServiceProvider {
private static final Logger log = Logger.getLogger(AbstractFileServiceProvider.class.getName());
private final File directory;
/**
* Creates a new provider that looks for configuration files in the
* given directory.
*
* @param directory the configuration directory
*/
public AbstractFileServiceProvider(File directory) {
this.directory = directory;
}
/**
* Creates a new factory using the default configuration directory.
*/
public AbstractFileServiceProvider() {
this(null);
}
/**
* The default location for the configuration. By default, it is
* $DIIRT_HOME/services/SERVICE_PROVIDER_NAME.
*
* @return the configuration location
*/
public File getDefaultConfigurationDirectory() {
return new File(Configuration.getDirectory(), "services/" + getName());
}
/**
* Creates a service from the given file.
* <p>
* Implementors of this method need not to care about logging and service registration.
*
* @param file a file in the configuration directory
* @return the new service or null if no service corresponds to the file
* @throws Exception if there is a problem creating the service from the file
*/
public abstract Service createService(File file) throws Exception;
/**
* Creates additional services that are not read from files. This can be
* useful in case the service provider has additional services that are
* not user defined through configuration files.
* <p>
* Implementors need not to care about logging and service registration.
*
* @return a collection of services
*/
public Collection<Service> additionalServices() {
return Collections.emptyList();
}
/**
* Creates all the service instances by crawling the configuration
* directory, creating a service for each file found, and creating
* the additional services.
* <p>
* Given that this method provides the error handling and logging, it
* is declared final so that subclasses cannot accidently remove it.
*
* @return the new service instances
*/
@Override
public final Collection<Service> createServices() {
List<Service> services = new ArrayList<>();
File path = directory;
if (path == null) {
path = getDefaultConfigurationDirectory();
}
if (path.exists()) {
if (path.isDirectory()) { // We have a configuration directory
log.log(Level.CONFIG, "Loading {0} services from ''{1}''", new Object[] {getName(), path});
for (File file : path.listFiles()) {
try {
Service service = createService(file);
if (service != null) {
services.add(service);
log.log(Level.CONFIG, "Created {0} service ''{1}'' from ''{2}''", new Object[] {getName(), service.getName(), file.getName()});
}
} catch (Exception ex) {
log.log(Level.WARNING, "Failed to create " + getName() + " service from '" + file + "'", ex);
}
}
} else { // The path is not a directory
log.log(Level.WARNING, "Configuration path for {0} services ''{1}'' is not a directory", new Object[] {getName(), path});
}
} else { // The path does not exist
path.mkdirs();
log.log(Level.CONFIG, "Creating configuration path for {0} services at ''{1}''", new Object[] {getName(), path});
}
for (Service additionalService : additionalServices()) {
services.add(additionalService);
log.log(Level.CONFIG, "Created {0} service ''{1}''", new Object[] {getName(), additionalService.getName()});
}
log.log(Level.CONFIG, "Created {0} {1} services", new Object[] {services.size(), getName()});
return services;
}
}