
org.ow2.petals.extension.autoloader.AutoLoaderServiceImpl Maven / Gradle / Ivy
/**
* Copyright (c) 2005-2012 EBM WebSourcing, 2012-2016 Linagora
*
* This program/library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or (at your
* option) any later version.
*
* This program/library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program/library; If not, see http://www.gnu.org/licenses/
* for the GNU Lesser General Public License version 2.1.
*/
package org.ow2.petals.extension.autoloader;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Timer;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.fraclet.annotations.Interface;
import org.objectweb.fractal.fraclet.annotations.Lifecycle;
import org.objectweb.fractal.fraclet.annotations.Requires;
import org.objectweb.fractal.fraclet.extensions.Controller;
import org.objectweb.fractal.fraclet.types.Step;
import org.ow2.petals.clientserverapi.configuration.ContainerConfiguration;
import org.ow2.petals.launcher.api.server.conf.ConfigurationProperties;
import org.ow2.petals.microkernel.api.configuration.ConfigurationService;
import org.ow2.petals.microkernel.api.extension.InstallationExtension;
import org.ow2.petals.microkernel.api.extension.InstallationExtensionException;
import org.ow2.petals.microkernel.api.extension.PetalsPostExtensionController;
import com.ebmwebsourcing.easycommons.log.LoggingUtil;
import com.ebmwebsourcing.easycommons.properties.PropertiesException;
import com.ebmwebsourcing.easycommons.properties.PropertiesHelper;
/**
* This class is used to load automatically components which are placed in the "autoLoad" directory.
*
* It scans the directory periodically and check if new
* components are presents. The @ link InstallationServiceMBean} is called for
* each of those components. The whole process of installation is done (install
* + start) After being threat, the archives of the components are removed. A
* file "fileName.success" will be created if success A file "fileName.failed"
* will be created otherwise, containing the related exception.
*
*
* @author Adrien Louis - EBM WebSourcing
*/
@org.objectweb.fractal.fraclet.annotations.Component(provides = @Interface(name = PetalsPostExtensionController.INST_EXT_SRV_ITF_NAME, signature = InstallationExtension.class) )
public class AutoLoaderServiceImpl implements InstallationExtension {
/**
* The component.
*/
@Controller
private Component comp;
/**
* Name of the property defining the directory scanned to install artifacts.
*/
public static final String PATH_INSTALL_PROPERTY_NAME = "petals.autoloader.path.install";
/**
* Default value of the directory scanned to install artifacts: ${
* {@value ConfigurationProperties#DATA_ROOT_DIRECTORY_PROPERTY_NAME}/install
*/
private static final String DEFAULT_PATH_INSTALL = "${"
+ ConfigurationProperties.DATA_ROOT_DIRECTORY_PROPERTY_NAME + "}" + File.separator
+ "install";
/**
* Name of the property defining the directory scanned to uninstall
* artifacts.
*/
public static final String PATH_INSTALLED_PROPERTY_NAME = "petals.autoloader.path.installed";
/**
* Default value of the directory scanned to uninstall artifacts: ${
* {@value ConfigurationProperties#DATA_ROOT_DIRECTORY_PROPERTY_NAME}/installed
*/
private static final String DEFAULT_PATH_INSTALLED = "${"
+ ConfigurationProperties.DATA_ROOT_DIRECTORY_PROPERTY_NAME + "}" + File.separator
+ "installed";
/**
* Name of the property defining the scan period of the auto-loader.
*/
public static final String SCAN_PERIOD_PROPERTY_NAME = "petals.autoloader.scan.period";
/**
* Default value, in milliseconds, of the period between two scans of
* directories
*/
public static final long DEFAULT_SCAN_PERIOD = 4000L;
@Requires(name = "configuration")
private ConfigurationService configurationService;
@Requires(name = "installDirectoryScanner")
private DirectoryScanner installDirectoryScanner;
@Requires(name = "installedDirectoryScanner")
private DirectoryScanner installedDirectoryScanner;
private File installDirectory;
private File installedDirectory;
private final LoggingUtil log = new LoggingUtil(Logger.getLogger(AutoLoaderService.FRACTAL_COMPONENT_LOGGER_NAME));
/**
* The local container information.
*/
private ContainerConfiguration containerConfiguration;
/**
* Timer that launch scans of directories
*/
private Timer directoriesToScanTimer;
/**
* Initialize the autoloader.
*/
@Lifecycle(step = Step.START)
public void start() throws PropertiesException {
this.log.start();
this.containerConfiguration = this.configurationService.getContainerConfiguration();
final Map extraConfProperties = this.containerConfiguration
.getExtraConfiguration();
{
final String installDirectoryPropertyValue = extraConfProperties
.get(PATH_INSTALL_PROPERTY_NAME);
if (installDirectoryPropertyValue == null || installDirectoryPropertyValue.isEmpty()) {
// No value defined for the directory to scan to install
// artifacts, we use the default value
final String installDirectoryStr = PropertiesHelper.resolveString(
DEFAULT_PATH_INSTALL, this.configurationService.getServerProperties());
this.installDirectory = new File(installDirectoryStr);
} else {
this.installDirectory = new File(installDirectoryPropertyValue);
}
if (!this.installDirectory.exists()) {
if (!this.installDirectory.mkdirs()) {
this.log.warning(String
.format("Unable to create the directory for installation '%s'. Potential problems can occurs later.",
this.installDirectory.getAbsolutePath()));
}
} else if (!this.installDirectory.isDirectory()) {
this.log.warning(String
.format("The directory for installation '%s' is invalid. Potential problems can occurs later.",
this.installDirectory.getAbsolutePath()));
}
}
{
final String installedDirectoryPropertyValue = extraConfProperties
.get(PATH_INSTALLED_PROPERTY_NAME);
if (installedDirectoryPropertyValue == null
|| installedDirectoryPropertyValue.isEmpty()) {
// No value defined for the directory to scan to uninstall
// artifacts, we use the default value
final String installedDirectoryStr = PropertiesHelper.resolveString(
DEFAULT_PATH_INSTALLED, this.configurationService.getServerProperties());
this.installedDirectory = new File(installedDirectoryStr);
} else {
this.installedDirectory = new File(installedDirectoryPropertyValue);
}
if (!this.installedDirectory.exists()) {
if (!this.installedDirectory.mkdirs()) {
this.log.warning(String
.format("Unable to create the directory for uninstallation '%s'. Potential problems can occurs later.",
this.installedDirectory.getAbsolutePath()));
}
} else if (!this.installedDirectory.isDirectory()) {
this.log.warning(String
.format("The directory for uninstallation '%s' is invalid. Potential problems can occurs later.",
this.installedDirectory.getAbsolutePath()));
}
}
final String scanPeriodStr = extraConfProperties.get(SCAN_PERIOD_PROPERTY_NAME);
long scanPeriod;
if (scanPeriodStr == null || scanPeriodStr.isEmpty()) {
scanPeriod = DEFAULT_SCAN_PERIOD;
} else {
try {
scanPeriod = Long.parseLong(scanPeriodStr);
} catch (final NumberFormatException e) {
this.log.warning(String.format(
"Invalid value '%s' for property '%s'. Default value used: %d",
scanPeriodStr, SCAN_PERIOD_PROPERTY_NAME, DEFAULT_SCAN_PERIOD));
scanPeriod = DEFAULT_SCAN_PERIOD;
}
}
this.directoriesToScanTimer = new Timer("Autoloader Timer scanning directories");
this.installDirectoryScanner.startScanner(this.installDirectory,
this.directoriesToScanTimer, scanPeriod);
this.installedDirectoryScanner.startScanner(this.installedDirectory,
this.directoriesToScanTimer, scanPeriod);
this.log.info("Petals extension \"Autoloader\" started.");
this.log.end();
}
/**
* Stop the autoload of the components. TODO : synchronization, does the
* autoload must wait before the end of an installation before closing?
*/
@Lifecycle(step = Step.STOP)
public void stop() {
this.log.start();
this.directoriesToScanTimer.cancel();
this.log.info("Petals extension \"Autoloader\" stopped.");
this.log.end();
}
/**
* {@inheritDoc}
*/
public void onInstallation(final String installedArchive) throws InstallationExtensionException {
// On installation, the archive is copied into the direction scanned to uninstall artifacts.
try {
FileUtils.copyFileToDirectory(new File(installedArchive), this.installedDirectory);
} catch (final IOException e) {
throw new InstallationExtensionException(
"Error copying the installed archive into the repository of the auto-loader.",
e);
}
}
/**
* {@inheritDoc}
*/
public void onInstallationUndo(final String installedArchive)
throws InstallationExtensionException {
final File targetFile = new File(this.installedDirectory,
new File(installedArchive).getName());
if (targetFile.exists()) {
try {
FileUtils.forceDelete(targetFile);
} catch (final IOException e) {
this.log.error("Installed archive can not be undo from the autoloader repository",
e);
}
}
}
/**
* {@inheritDoc}
*/
public void onUninstallation(final String uninstalledArchive)
throws InstallationExtensionException {
final File targetFile = new File(this.installedDirectory,
new File(uninstalledArchive).getName());
if ((targetFile != null) && targetFile.exists()) {
targetFile.delete();
}
}
/**
* {@inheritDoc}
*/
public void onUninstallationUndo(final String uninstalledArchive)
throws InstallationExtensionException {
// NOP
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy