blob: 852a73b892834b8b0b708b2ec548fd2a9f1976f8 [file] [log] [blame]
package org.eclipse.virgo.nano.war.deployer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.eclipse.gemini.web.core.InstallationOptions;
import org.eclipse.gemini.web.core.WebBundleManifestTransformer;
import org.eclipse.virgo.nano.core.KernelConfig;
import org.eclipse.virgo.nano.deployer.api.core.DeploymentIdentity;
import org.eclipse.virgo.medic.eventlog.EventLogger;
import org.eclipse.virgo.nano.deployer.SimpleDeployer;
import org.eclipse.virgo.nano.deployer.StandardDeploymentIdentity;
import org.eclipse.virgo.nano.deployer.util.BundleInfosUpdater;
import org.eclipse.virgo.util.io.FileSystemUtils;
import org.eclipse.virgo.util.io.IOUtils;
import org.eclipse.virgo.util.io.JarUtils;
import org.eclipse.virgo.util.io.PathReference;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.packageadmin.PackageAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings("deprecation")
public class WARDeployer implements SimpleDeployer {
private static final String WAR = "war";
private static final boolean STATUS_OK = true;
private static final boolean STATUS_ERROR = false;
private static final String PICKUP_DIR = "pickup";
private static final String INSTALL_BY_REFERENCE_PREFIX = "reference:file:";
private static final char SLASH = '/';
private static final char BACKSLASH = '\\';
private static final char DOT = '.';
private static final char NEW_LINE = '\n';
private static final String SUCCESS_MARK = "ok";
private static final String ERROR_MARK = "error";
private static final String OP_DEPLOY = "deploy";
private static final String OP_UNDEPLOY = "undeploy";
private static final String FEEDBACK_FILE_NAME = ".state";
private static final String BUNDLE_ID_RECORD = "bundle-id";
static final String LAST_MODIFIED = "last-modified";
private static final String DELIMITER = "=";
static final String EMPTY_STRING = "";
private static final String WEBAPPS_DIR = "webapps";
private static final String WEBBUNDLE_PROTOCOL = "webbundle";
private static final String FILE_PROTOCOL = "file";
private static final String UNKNOWN = "unknown";
private static final String HEADER_WEB_CONTEXT_PATH = "Web-ContextPath";
//private static final String HEADER_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
private static final String DEFAULT_CONTEXT_PATH = "/";
private static final String ROOT_WAR_NAME = "ROOT";
private static final String PROPERTY_WAB_HEADERS = "WABHeaders";
private static final String PROPERTY_VALUE_WAB_HEADERS_STRICT = "strict";
private static final String PROPERTY_VALUE_WAB_HEADERS_DEFAULTED = "defaulted";
private static final String HEADER_DEFAULT_WAB_HEADERS = "org-eclipse-gemini-web-DefaultWABHeaders";
private static final String WEB_BUNDLE_MODULE_TYPE = "web-bundle";
private EventLogger eventLogger;
private BundleInfosUpdater bundleInfosUpdaterUtil;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private BundleContext bundleContext;
private PackageAdmin packageAdmin;
private WebBundleManifestTransformer webBundleManifestTransformer;
private long largeFileCopyTimeout = 4000;
private File pickupDir;
private File webAppsDir;
private KernelConfig kernelConfig;
public WARDeployer() {
warDeployerInternalInit(null);
}
public WARDeployer(BundleContext bundleContext, PackageAdmin packageAdmin, WebBundleManifestTransformer webBundleManifestTransformer,
EventLogger eventLogger, KernelConfig kernelConfig) {
warDeployerInternalInit(bundleContext);
this.packageAdmin = packageAdmin;
this.webBundleManifestTransformer = webBundleManifestTransformer;
this.eventLogger = eventLogger;
this.kernelConfig = kernelConfig;
}
public void activate(ComponentContext context) {
warDeployerInternalInit(context.getBundleContext());
}
@Override
public final boolean deploy(URI path) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING, new File(path).toString());
final String warName = extractWarNameFromString(path.toString());
final File deployedFile = new File(path);
final File warDir = new File(this.webAppsDir, warName);
deleteStatusFile(warName, this.pickupDir);
long bundleId = -1L;
final long lastModified = deployedFile.lastModified();
if (!canWrite(path)) {
this.logger.error("Cannot open the file " + path + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, path);
return STATUS_ERROR;
}
final Bundle installed;
try {
// extract the war file to the webapps directory
JarUtils.unpackTo(new PathReference(deployedFile), new PathReference(warDir));
// make the manifest transformation in the unpacked location
transformUnpackedManifest(warDir, warName);
// install the bundle
installed = this.bundleContext.installBundle(createInstallLocation(warDir));
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, e, path);
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLED, installed.getSymbolicName(), installed.getVersion());
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTING, installed.getSymbolicName(), installed.getVersion());
try {
installed.start();
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STARTING_ERROR, e, installed.getSymbolicName(), installed.getVersion());
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTED, installed.getSymbolicName(), installed.getVersion());
bundleId = installed.getBundleId();
// now update bundle's info
if (this.logger.isInfoEnabled()) {
this.logger.info("Bundles info will be updated for war with path '" + path + "'.");
}
try {
if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
registerToBundlesInfo(installed);
}
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_PERSIST_ERROR, e, installed.getSymbolicName(), installed.getVersion());
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
createStatusFile(warName, OP_DEPLOY, STATUS_OK, bundleId, lastModified);
return STATUS_OK;
}
@Override
public boolean isDeployFileValid(File file) {
JarFile jarFile = null;
try {
jarFile = new JarFile(file);
} catch (IOException e) {
this.logger.error("The deployed file '" + file.getAbsolutePath() + "' is an invalid zip file.");
return false;
} finally {
try {
if (jarFile != null) {
jarFile.close();
}
} catch (IOException e) {
// do nothing
}
}
return true;
}
private String createInstallLocation(final File warDir) {
return INSTALL_BY_REFERENCE_PREFIX + warDir.getAbsolutePath();
}
private String extractWarNameFromString(String path) {
final String warName = path.substring(path.lastIndexOf(SLASH) + 1, path.length() - 4);
return warName;
}
@Override
public final boolean undeploy(Bundle bundle) {
String bundleLocation = removeTrailingFileSeparator(bundle.getLocation());
String warPath = extractWarPath(bundleLocation);
final File warDir = new File(warPath);
String warName = extractWarName(warPath);
deleteStatusFile(warName, this.pickupDir);
if (bundle != null) {
try {
if (this.logger.isInfoEnabled()) {
this.logger.info("Removing bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion() + "' from bundles.info.");
}
if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
unregisterToBundlesInfo(bundle);
this.logger.info("Successfully removed bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion()
+ "' from bundles.info.");
} else {
this.logger.error("BundleInfosUpdater not available. Failed to remove bundle '" + bundle.getSymbolicName() + "' version '"
+ bundle.getVersion() + "' from bundles.info.");
}
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STOPPING, bundle.getSymbolicName(), bundle.getVersion());
bundle.stop();
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STOPPED, bundle.getSymbolicName(), bundle.getVersion());
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UNINSTALLING, bundle.getSymbolicName(), bundle.getVersion());
bundle.uninstall();
FileSystemUtils.deleteRecursively(warDir);
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UNINSTALLED, bundle.getSymbolicName(), bundle.getVersion());
} catch (BundleException e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UNDEPLOY_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
return STATUS_ERROR;
}
}
createStatusFile(warName, OP_UNDEPLOY, STATUS_OK, bundle.getBundleId(), bundle.getLastModified());
return STATUS_OK;
}
private String extractWarName(String warPath) {
return warPath.substring(warPath.lastIndexOf(File.separatorChar) + 1, warPath.length());
}
private String extractWarPath(String bundleLocation) {
String warPath;
if (bundleLocation.startsWith(INSTALL_BY_REFERENCE_PREFIX)) {
warPath = bundleLocation.substring(INSTALL_BY_REFERENCE_PREFIX.length());
} else {
warPath = bundleLocation;
}
return warPath;
}
private String removeTrailingFileSeparator(String bundleLocation) {
if (bundleLocation.endsWith(File.separator)) {
bundleLocation = bundleLocation.substring(0, bundleLocation.length() - 1);
}
return bundleLocation;
}
@Override
public final boolean update(URI path) {
final String warName = extractWarNameFromString(path.toString());
final File updatedFile = new File(path);
final File warDir = new File(this.webAppsDir, warName);
if (!warDir.exists()) {
this.logger.info("Can't update artifact for path '" + path + "'. It is not deployed.");
}
deleteStatusFile(warName, this.pickupDir);
final long bundleId = -1L;
final long lastModified = updatedFile.lastModified();
if (!canWrite(path)) {
this.logger.error("Cannot open the file [" + path + "] for writing. Timeout is [" + this.largeFileCopyTimeout + "].");
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATING_ERROR, path);
return STATUS_ERROR;
}
final Bundle bundle = this.bundleContext.getBundle(createInstallLocation(warDir));
if (bundle != null) {
try {
// extract the war file to the webapps directory
JarUtils.unpackToDestructive(new PathReference(updatedFile), new PathReference(warDir));
// make the manifest transformation in the unpacked location
transformUnpackedManifest(warDir, warName);
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATING, bundle.getSymbolicName(), bundle.getVersion());
bundle.update();
if (this.packageAdmin != null) {
this.packageAdmin.refreshPackages(new Bundle[] { bundle });
this.logger.info("Update of file with path [" + path + "] is successful.");
}
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATED, bundle.getSymbolicName(), bundle.getVersion());
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_UPDATE_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
createStatusFile(warName, OP_DEPLOY, STATUS_OK, bundleId, lastModified);
} else {
deploy(path);
}
return STATUS_OK;
}
public void setLargeFileCopyTimeout(long timeout) {
if (this.logger.isInfoEnabled()) {
this.logger.info("setLargeFileCopyTimeout(" + timeout + ")");
}
this.largeFileCopyTimeout = timeout;
}
private void createStatusFile(String warName, String operation, boolean status, long bundleId, long lastModified) {
final File stateDir = new File(this.pickupDir, FEEDBACK_FILE_NAME);
if (!stateDir.exists() && !stateDir.mkdirs()) {
this.logger.error("Cannot create directory [" + stateDir.getAbsolutePath() + "]. Status file for the operation cannot be created.");
return;
}
final File statusFile = new File(stateDir, warName + DOT + operation + DOT + (status ? SUCCESS_MARK : ERROR_MARK));
FileWriter fw = null;
try {
fw = new FileWriter(statusFile, true);
fw.write(BUNDLE_ID_RECORD + DELIMITER + bundleId);
fw.write(NEW_LINE);
fw.write(LAST_MODIFIED + DELIMITER + lastModified);
fw.write(NEW_LINE);
fw.flush();
} catch (IOException e) {
this.logger.error("Cannot update the status of operation.", e);
} finally {
IOUtils.closeQuietly(fw);
}
}
private void deleteStatusFile(String warName, File pickupDir) {
final File stateDir = new File(pickupDir, FEEDBACK_FILE_NAME);
if (stateDir.exists()) {
File statusFile = new File(stateDir, warName + DOT + OP_DEPLOY + DOT + SUCCESS_MARK);
if (statusFile.exists() && !statusFile.delete()) {
this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
}
statusFile = new File(stateDir, warName + DOT + OP_DEPLOY + DOT + ERROR_MARK);
if (statusFile.exists() && !statusFile.delete()) {
this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
}
statusFile = new File(stateDir, warName + DOT + OP_UNDEPLOY + DOT + SUCCESS_MARK);
if (statusFile.exists() && !statusFile.delete()) {
this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
}
statusFile = new File(stateDir, warName + DOT + OP_UNDEPLOY + DOT + ERROR_MARK);
if (statusFile.exists() && !statusFile.delete()) {
this.logger.error("Cannot delete file [" + statusFile.getAbsolutePath() + "].");
}
}
}
private boolean canWrite(URI path) {
int tries = -1;
boolean isWritable = false;
// Some big files are copied very slowly, but the event is received
// immediately.
// So we will wait 0.5 x 240 i.e. 2 minutes
final long timeout = this.largeFileCopyTimeout / 500;
while (tries < timeout) {
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(path));
isWritable = true;
break;
} catch (FileNotFoundException e) {
if (this.logger.isInfoEnabled()) {
this.logger.info("File is still locked.", e);
}
} finally {
IOUtils.closeQuietly(fis);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
this.logger.error("InterruptedException occurred.", e);
}
tries++;
}
return isWritable;
}
private final void transformUnpackedManifest(File srcFile, String warName) throws IOException {
if (srcFile == null) {
throw new NullPointerException("Source file is null.");
}
if (!srcFile.isDirectory() || !srcFile.canRead()) {
throw new IllegalArgumentException("Source file must be a readable directory [" + srcFile + "].");
}
File destFile = new File(srcFile, JarFile.MANIFEST_NAME);
if (!destFile.exists()) {
destFile.getParentFile().mkdirs();
destFile.createNewFile();
}
if (!destFile.isFile() || !destFile.canRead()) {
throw new IllegalArgumentException("Destination file must be a readable file [" + destFile + "].");
}
FileOutputStream fos = null;
InputStream mfIS = null;
try {
mfIS = new FileInputStream(srcFile + File.separator + JarFile.MANIFEST_NAME);
BundleManifest manifest = BundleManifestFactory.createBundleManifest(new InputStreamReader(mfIS));
if (manifest.getModuleType() == null || "web".equalsIgnoreCase(manifest.getModuleType())) {
boolean strictWABHeaders = getStrictWABHeadersValue();
if (!strictWABHeaders) {
manifest.setHeader(HEADER_DEFAULT_WAB_HEADERS, "true");
}
manifest.setModuleType(WEB_BUNDLE_MODULE_TYPE);
InstallationOptions installationOptions = prepareInstallationOptions(strictWABHeaders, warName, manifest);
boolean isWebBundle = WebBundleUtils.isWebApplicationBundle(manifest);
this.webBundleManifestTransformer.transform(manifest, srcFile.toURI().toURL(), installationOptions, isWebBundle);
} else {
this.logger.info("Skipping transformation of application '" + warName + "' because it is already a web bundle.");
return;
}
fos = new FileOutputStream(destFile);
toManifest(manifest.toDictionary()).write(fos);
} finally {
IOUtils.closeQuietly(fos);
IOUtils.closeQuietly(mfIS);
}
}
private InstallationOptions prepareInstallationOptions(boolean strictWABHeaders, String warName, BundleManifest manifest) {
Map<String, String> map = new HashMap<String, String>();
String webContextPathHeader = manifest.getHeader(HEADER_WEB_CONTEXT_PATH);
if (webContextPathHeader == null || webContextPathHeader.trim().length() == 0) {
if (warName.equals(ROOT_WAR_NAME)) {
map.put(HEADER_WEB_CONTEXT_PATH, DEFAULT_CONTEXT_PATH);
} else {
map.put(HEADER_WEB_CONTEXT_PATH, warName);
}
}
InstallationOptions installationOptions = new InstallationOptions(map);
installationOptions.setDefaultWABHeaders(!strictWABHeaders);
return installationOptions;
}
private final Manifest toManifest(Dictionary<String, String> headers) {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
Enumeration<String> names = headers.keys();
while (names.hasMoreElements()) {
String name = names.nextElement();
String value = headers.get(name);
attributes.putValue(name, value);
}
return manifest;
}
private final void registerToBundlesInfo(Bundle bundle) throws URISyntaxException, IOException, BundleException {
String location = bundle.getLocation().replace(BACKSLASH, SLASH);
if (!location.contains(WEBBUNDLE_PROTOCOL)) {
location = location.replaceAll(" ", "%20");
String scheme = new URI(location).getScheme();
if (scheme != null && !scheme.equals(FILE_PROTOCOL)) {
location = new URI(location).getRawSchemeSpecificPart();
}
String symbolicName = bundle.getSymbolicName();
this.bundleInfosUpdaterUtil.addBundleToBundlesInfo(symbolicName == null ? UNKNOWN : symbolicName, new URI(location),
bundle.getVersion().toString(), SimpleDeployer.HOT_DEPLOYED_ARTIFACTS_START_LEVEL, true);
this.bundleInfosUpdaterUtil.updateBundleInfosRepository();
}
}
private final void unregisterToBundlesInfo(Bundle bundle) {
try {
String location = bundle.getLocation().replace(BACKSLASH, SLASH);
if (!location.contains(WEBBUNDLE_PROTOCOL)) {
location = location.replaceAll(" ", "%20");
String scheme = new URI(location).getScheme();
if (scheme != null && !scheme.equals(FILE_PROTOCOL)) {
location = new URI(location).getRawSchemeSpecificPart();
}
String symbolicName = bundle.getSymbolicName();
this.bundleInfosUpdaterUtil.removeBundleFromBundlesInfo(symbolicName == null ? UNKNOWN : symbolicName, new URI(location),
bundle.getVersion().toString(), SimpleDeployer.HOT_DEPLOYED_ARTIFACTS_START_LEVEL, true);
this.bundleInfosUpdaterUtil.updateBundleInfosRepository();
}
} catch (Exception e) {
this.logger.error("Cannot update bundles info while unregistering [" + bundle.getSymbolicName() + "].", e);
}
}
@Override
public boolean canServeFileType(String fileType) {
return fileType.toLowerCase().equals(WAR);
}
@Override
public boolean isDeployed(URI path) {
final String warName = extractWarNameFromString(path.toString());
final File warDir = new File(this.webAppsDir, warName);
if (!warDir.exists()) {
return false;
}
if (this.bundleContext.getBundle(createInstallLocation(warDir)) == null) {
return false;
}
return true;
}
@Override
public DeploymentIdentity getDeploymentIdentity(URI path) {
final String warName = extractWarNameFromString(path.toString());
final File warDir = new File(this.webAppsDir, warName);
if (!warDir.exists()) {
return null;
}
Bundle bundle = this.bundleContext.getBundle(createInstallLocation(warDir));
if (bundle == null) {
return null;
}
return new StandardDeploymentIdentity(WAR, bundle.getSymbolicName(), bundle.getVersion().toString());
}
@Override
public List<String> getAcceptedFileTypes() {
List<String> types = new ArrayList<String>();
types.add(WAR);
return types;
}
private void warDeployerInternalInit(BundleContext bundleContext) {
String kernelHome = System.getProperty("org.eclipse.virgo.kernel.home");
File kernelHomeFile = new File(kernelHome);
File bundlesInfoFile = new File(kernelHomeFile, "configuration/org.eclipse.equinox.simpleconfigurator/bundles.info");
this.pickupDir = new File(kernelHomeFile, PICKUP_DIR);
this.webAppsDir = new File(kernelHomeFile, WEBAPPS_DIR);
this.bundleContext = bundleContext;
this.bundleInfosUpdaterUtil = new BundleInfosUpdater(bundlesInfoFile, kernelHomeFile);
}
private boolean getStrictWABHeadersValue() {
boolean strictWABHeaders = true;
String wabHeadersPropertyValue = null;
if (kernelConfig.getProperty(PROPERTY_WAB_HEADERS) != null) {
wabHeadersPropertyValue = kernelConfig.getProperty(PROPERTY_WAB_HEADERS).toString();
}
if (wabHeadersPropertyValue != null) {
if (PROPERTY_VALUE_WAB_HEADERS_DEFAULTED.equals(wabHeadersPropertyValue)) {
strictWABHeaders = false;
logger.info("Property '%s' has value [defaulted]", new String[] { PROPERTY_WAB_HEADERS });
} else if (!PROPERTY_VALUE_WAB_HEADERS_STRICT.equals(wabHeadersPropertyValue)) {
logger.error("Property '%s' has invalid value '%s'", new String[] { PROPERTY_WAB_HEADERS, wabHeadersPropertyValue });
}
}
return strictWABHeaders;
}
public void bindWebBundleManifestTransformer(WebBundleManifestTransformer transformer) {
this.webBundleManifestTransformer = transformer;
}
public void unbindWebBundleManifestTransformer(WebBundleManifestTransformer transformer) {
this.webBundleManifestTransformer = null;
}
public void bindEventLogger(EventLogger logger) {
this.eventLogger = logger;
}
public void unbindEventLogger(EventLogger logger) {
this.eventLogger = null;
}
public void bindPackageAdmin(PackageAdmin packageAdmin) {
this.packageAdmin = packageAdmin;
}
public void unbindPackageAdmin(PackageAdmin packageAdmin) {
this.packageAdmin = null;
}
public void bindKernelConfig(KernelConfig kernelConfig) {
this.kernelConfig = kernelConfig;
}
public void unbindKernelConfig(KernelConfig kernelConfig) {
this.kernelConfig = null;
}
@Override
public boolean install(URI uri) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING, new File(uri).toString());
final String warName = extractWarNameFromString(uri.toString());
final File deployedFile = new File(uri);
final File warDir = new File(this.webAppsDir, warName);
deleteStatusFile(warName, this.pickupDir);
final long lastModified = deployedFile.lastModified();
if (!canWrite(uri)) {
this.logger.error("Cannot open the file " + uri + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, uri);
return false;
}
final Bundle installed;
try {
// extract the war file to the webapps directory
JarUtils.unpackTo(new PathReference(deployedFile), new PathReference(warDir));
// make the manifest transformation in the unpacked location
transformUnpackedManifest(warDir, warName);
// install the bundle
installed = this.bundleContext.installBundle(createInstallLocation(warDir));
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLED, installed.getSymbolicName(), installed.getVersion());
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_INSTALLING_ERROR, e, uri);
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
return false;
}
return true;
}
@Override
public boolean start(URI uri) {
Bundle bundle = getInstalledBundle(uri);
final String warName = extractWarNameFromString(uri.toString());
deleteStatusFile(warName, this.pickupDir);
final long lastModified = new File(uri).lastModified();
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTING, bundle.getSymbolicName(), bundle.getVersion());
try {
bundle.start();
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_STARTING_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(), lastModified);
return STATUS_ERROR;
}
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_WEB_STARTED, bundle.getSymbolicName(), bundle.getVersion());
// now update bundle's info
if (!updateBundlesInfo(bundle)){
createStatusFile(warName, OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(), lastModified);
return STATUS_ERROR;
}
createStatusFile(warName, OP_DEPLOY, STATUS_OK, bundle.getBundleId(), lastModified);
return STATUS_OK;
}
private boolean updateBundlesInfo(Bundle bundle){
if (this.logger.isInfoEnabled()) {
this.logger.info("Bundles info will be updated for web app bundle with simbolic name '" + bundle.getSymbolicName() + "' .");
}
try {
if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
registerToBundlesInfo(bundle);
}
} catch (Exception e) {
this.eventLogger.log(NanoWARDeployerLogEvents.NANO_PERSIST_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
return STATUS_ERROR;
}
return STATUS_OK;
}
private Bundle getInstalledBundle(URI path){
final String warName = extractWarNameFromString(path.toString());
final File warDir = new File(this.webAppsDir, warName);
if (!warDir.exists()) {
return null;
}
return this.bundleContext.getBundle(createInstallLocation(warDir));
}
}