aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPolina Genova2012-11-23 04:17:02 (EST)
committerBorislav Kapukaranov2012-11-23 04:17:02 (EST)
commitbe00101d51e72be056da97677031a1a0f7967d4d (patch)
tree86358fcc39cc430c89c1a418562bc5ea3a7b0cfd
parentdcef081f01c65bb0d91262e33c068b7c0efe2b1d (diff)
downloadorg.eclipse.virgo.nano-be00101d51e72be056da97677031a1a0f7967d4d.zip
org.eclipse.virgo.nano-be00101d51e72be056da97677031a1a0f7967d4d.tar.gz
org.eclipse.virgo.nano-be00101d51e72be056da97677031a1a0f7967d4d.tar.bz2
394770 - Introduce new API method and implementations to support offline update of deployable files.
-rw-r--r--org.eclipse.virgo.nano.deployer.api/src/main/java/org/eclipse/virgo/nano/deployer/api/core/ApplicationDeployer.java11
-rw-r--r--org.eclipse.virgo.nano.deployer.hot/src/main/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListener.java37
-rw-r--r--org.eclipse.virgo.nano.deployer.hot/src/test/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListenerTests.java1
-rw-r--r--org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/SimpleDeployer.java12
-rw-r--r--org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/BundleDeployer.java105
-rw-r--r--org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/StandardApplicationDeployer.java30
6 files changed, 166 insertions, 30 deletions
diff --git a/org.eclipse.virgo.nano.deployer.api/src/main/java/org/eclipse/virgo/nano/deployer/api/core/ApplicationDeployer.java b/org.eclipse.virgo.nano.deployer.api/src/main/java/org/eclipse/virgo/nano/deployer/api/core/ApplicationDeployer.java
index 86a74d3..ab2b3e7 100644
--- a/org.eclipse.virgo.nano.deployer.api/src/main/java/org/eclipse/virgo/nano/deployer/api/core/ApplicationDeployer.java
+++ b/org.eclipse.virgo.nano.deployer.api/src/main/java/org/eclipse/virgo/nano/deployer/api/core/ApplicationDeployer.java
@@ -229,5 +229,14 @@ public interface ApplicationDeployer {
* @return <code>true</code> if and only if the given artifact at its file's last modified time is already deployed
*/
boolean isDeployed(URI uri);
-
+
+ /**
+ * Determine whether or not the given artifact has been updated during the application server was stopped. The method is
+ * convenient to track offline updates of deployable files.
+ *
+ * @param uri location of the artifact
+ * @return <code>true</code> if the given artifact has been updated during application server was stopped
+ */
+ boolean isOfflineUpdated(URI uri);
+
}
diff --git a/org.eclipse.virgo.nano.deployer.hot/src/main/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListener.java b/org.eclipse.virgo.nano.deployer.hot/src/main/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListener.java
index 016a4c3..cf06084 100644
--- a/org.eclipse.virgo.nano.deployer.hot/src/main/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListener.java
+++ b/org.eclipse.virgo.nano.deployer.hot/src/main/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListener.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP AG - initial contribution
+ *******************************************************************************/
package org.eclipse.virgo.nano.deployer.hot;
@@ -88,6 +98,7 @@ final class HotDeploymentFileSystemListener implements FileSystemListener {
*
* Reacts to initial event in the pickup directory and calls the bulk deploy method in {@link ApplicationDeployer}.
*/
+ @Override
public void onInitialEvent(List<String> paths) {
this.eventLogger.log(HotDeployerLogEvents.HOT_DEPLOY_PROCESSING_FILE, FileSystemEvent.INITIAL, getConcatenatedPaths(paths));
try {
@@ -107,20 +118,19 @@ final class HotDeploymentFileSystemListener implements FileSystemListener {
}
/**
- * Collects only the source artifacts that are not yet deployed and transforms the given paths to URIs.
- *
+ * Returns only the source artifacts' URIs that need to be deployed or updated.
*/
- private List<URI> getNotDeployedUris(List<String> sourceArtefacts) {
- List<URI> notDeployedFileUris = new ArrayList<URI>();
+ private List<URI> getUrisToDeploy(List<String> sourceArtefacts) {
+ List<URI> resultUris = new ArrayList<URI>();
for (String sourceArtefact : sourceArtefacts) {
- if (!isDeployed(sourceArtefact)) {
- notDeployedFileUris.add(getDefinitiveUri(sourceArtefact));
+ if (!isDeployed(sourceArtefact) || isOfflineUpdated(sourceArtefact)) {
+ resultUris.add(getDefinitiveUri(sourceArtefact));
this.logger.info("ApplicationConditionallyDeploying path '{}'.", sourceArtefact);
} else {
this.eventLogger.log(HotDeployerLogEvents.HOT_DEPLOY_SKIPPED, sourceArtefact);
}
}
- return notDeployedFileUris;
+ return resultUris;
}
/**
@@ -130,7 +140,7 @@ final class HotDeploymentFileSystemListener implements FileSystemListener {
* @throws DeploymentException
*/
private void bulkDeployIfNotDeployed(List<String> sourceArtefacts) throws DeploymentException {
- this.deployer.bulkDeploy(getNotDeployedUris(sourceArtefacts), new DeploymentOptions(true, true, false));
+ this.deployer.bulkDeploy(getUrisToDeploy(sourceArtefacts), new DeploymentOptions(true, true, false));
}
/**
@@ -187,6 +197,15 @@ final class HotDeploymentFileSystemListener implements FileSystemListener {
}
/**
+ * Determine whether there has been offline update of the given artefact.
+ *
+ * @param sourceArtefact the source artefact URI string
+ */
+ private boolean isOfflineUpdated(String sourceArtefact) {
+ return this.deployer.isOfflineUpdated(getDefinitiveUri(sourceArtefact));
+ }
+
+ /**
* Converts a string URI to a URI with a predictable format, particularly in the case where the string URI ends in a
* file separator.
*
@@ -223,7 +242,7 @@ final class HotDeploymentFileSystemListener implements FileSystemListener {
* @throws DeploymentException
*/
private void deployIfNotDeployed(String sourceArtefact, String fileName) throws DeploymentException {
- if (!isDeployed(sourceArtefact)) {
+ if (!isDeployed(sourceArtefact) || isOfflineUpdated(sourceArtefact)) {
deploy(sourceArtefact);
} else {
this.eventLogger.log(HotDeployerLogEvents.HOT_DEPLOY_SKIPPED, fileName);
diff --git a/org.eclipse.virgo.nano.deployer.hot/src/test/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListenerTests.java b/org.eclipse.virgo.nano.deployer.hot/src/test/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListenerTests.java
index 6852b6f..2fb2908 100644
--- a/org.eclipse.virgo.nano.deployer.hot/src/test/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListenerTests.java
+++ b/org.eclipse.virgo.nano.deployer.hot/src/test/java/org/eclipse/virgo/nano/deployer/hot/HotDeployerFileSystemListenerTests.java
@@ -68,6 +68,7 @@ public class HotDeployerFileSystemListenerTests {
public void existingAppDuringStartup() throws Exception {
File app = new File("path/to/app");
expect(deployer.isDeployed(app.toURI())).andReturn(true);
+ expect(deployer.isOfflineUpdated(app.toURI())).andReturn(false);
replay(deployer);
listener.onChange("path/to/app", FileSystemEvent.INITIAL);
verify(deployer);
diff --git a/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/SimpleDeployer.java b/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/SimpleDeployer.java
index bd8ce0e..8fc9f00 100644
--- a/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/SimpleDeployer.java
+++ b/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/SimpleDeployer.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP AG - initial contribution
+ *******************************************************************************/
package org.eclipse.virgo.nano.deployer;
@@ -25,6 +35,8 @@ public interface SimpleDeployer {
public boolean canServeFileType(String fileType);
public boolean isDeployed(URI path);
+
+ public boolean isOfflineUpdated(URI path);
public DeploymentIdentity getDeploymentIdentity(URI path);
diff --git a/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/BundleDeployer.java b/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/BundleDeployer.java
index 68d83be..2e4c120 100644
--- a/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/BundleDeployer.java
+++ b/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/BundleDeployer.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP AG - initial contribution
+ *******************************************************************************/
package org.eclipse.virgo.nano.deployer.internal;
@@ -7,7 +17,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
-import java.net.URISyntaxException;
+import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@@ -20,6 +30,7 @@ import org.eclipse.virgo.nano.deployer.StandardDeploymentIdentity;
import org.eclipse.virgo.nano.deployer.api.core.DeploymentIdentity;
import org.eclipse.virgo.nano.deployer.util.BundleInfosUpdater;
import org.eclipse.virgo.nano.deployer.util.BundleLocationUtil;
+import org.eclipse.virgo.nano.deployer.util.StatusFileModificator;
import org.eclipse.virgo.util.io.FileCopyUtils;
import org.eclipse.virgo.util.io.IOUtils;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
@@ -45,6 +56,8 @@ public class BundleDeployer implements SimpleDeployer {
private static final char SLASH = '/';
+ private static final String PICKUP_DIR = "pickup";
+
private static final String FRAGMEN_HOST_HEADER = "Fragment-Host";
private final EventLogger eventLogger;
@@ -60,9 +73,11 @@ public class BundleDeployer implements SimpleDeployer {
private final PackageAdmin packageAdmin;
private final File workBundleInstallLocation;
-
+
private final File kernelHomeFile;
+ private final File pickupDir;
+
public BundleDeployer(BundleContext bundleContext, PackageAdmin packageAdmin, EventLogger eventLogger) {
this.eventLogger = eventLogger;
this.bundleContext = bundleContext;
@@ -71,13 +86,15 @@ public class BundleDeployer implements SimpleDeployer {
if (kernelHome != null) {
this.kernelHomeFile = new File(kernelHome);
if (this.kernelHomeFile.exists()) {
- File bundlesInfoFile = new File(kernelHomeFile, "configuration/org.eclipse.equinox.simpleconfigurator/bundles.info");
- this.bundleInfosUpdater = new BundleInfosUpdater(bundlesInfoFile, kernelHomeFile);
+ File bundlesInfoFile = new File(this.kernelHomeFile, "configuration/org.eclipse.equinox.simpleconfigurator/bundles.info");
+ this.bundleInfosUpdater = new BundleInfosUpdater(bundlesInfoFile, this.kernelHomeFile);
+ this.pickupDir = new File(this.kernelHomeFile, PICKUP_DIR);
String thisBundleName = this.bundleContext.getBundle().getSymbolicName();
String staging = "staging";
- this.workBundleInstallLocation = new File(kernelHomeFile, "work" + File.separator + thisBundleName + File.separator + staging);
+ this.workBundleInstallLocation = new File(this.kernelHomeFile, "work" + File.separator + thisBundleName + File.separator + staging);
} else {
- throw new IllegalStateException("Required location '" + this.kernelHomeFile.getAbsolutePath() + "' does not exist. Check the value of the '"+ KERNEL_HOME_PROP +"' propery");
+ throw new IllegalStateException("Required location '" + this.kernelHomeFile.getAbsolutePath()
+ + "' does not exist. Check the value of the '" + KERNEL_HOME_PROP + "' propery");
}
} else {
throw new IllegalStateException("Missing value for required property '" + KERNEL_HOME_PROP + "'");
@@ -145,9 +162,14 @@ public class BundleDeployer implements SimpleDeployer {
@Override
public boolean install(URI uri) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING, new File(uri).toString());
+ String jarName = extractDecodedJarNameFromString(uri.toString());
+ final long lastModified = new File(uri).lastModified();
+ StatusFileModificator.deleteStatusFile(jarName, this.pickupDir);
+
try {
if (!validateUri(uri) || !createInstallationFolder()) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING_ERROR, uri);
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
File stagedFile = getStagedFile(uri);
@@ -163,8 +185,11 @@ public class BundleDeployer implements SimpleDeployer {
refreshHosts(hostHolder, installed);
updateBundleInfo(installed, stagedFile, true);
}
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, installed.getBundleId(),
+ lastModified);
} catch (Exception e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING_ERROR, e, uri);
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
return STATUS_OK;
@@ -173,6 +198,10 @@ public class BundleDeployer implements SimpleDeployer {
@Override
public boolean start(URI uri) {
Bundle installedBundle = getInstalledBundle(uri);
+ String jarName = extractDecodedJarNameFromString(uri.toString());
+ final long lastModified = new File(uri).lastModified();
+ StatusFileModificator.deleteStatusFile(jarName, this.pickupDir);
+
File stagedFile = getStagedFile(uri);
if (installedBundle != null) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_STARTING, installedBundle.getSymbolicName(), installedBundle.getVersion());
@@ -180,17 +209,21 @@ public class BundleDeployer implements SimpleDeployer {
if (!isFragment(installedBundle)) {
installedBundle.start();
updateBundleInfo(installedBundle, stagedFile, false);
+ this.eventLogger.log(NanoDeployerLogEvents.NANO_STARTED, installedBundle.getSymbolicName(), installedBundle.getVersion());
} else {
- this.logger.warn("The installed bundle for the given url [" + uri
- + "] is a fragment bundle. Start operation for this url failed. ");
- return STATUS_ERROR;
+ if (this.logger.isWarnEnabled()) {
+ this.logger.warn("The installed bundle for the given url [" + uri
+ + "] is a fragment bundle. Start operation for this url will not be executed.");
+ }
}
} catch (Exception e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_STARTING_ERROR, e, installedBundle.getSymbolicName(), installedBundle.getVersion());
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
- this.eventLogger.log(NanoDeployerLogEvents.NANO_STARTED, installedBundle.getSymbolicName(), installedBundle.getVersion());
}
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, installedBundle.getBundleId(),
+ lastModified);
return STATUS_OK;
}
@@ -198,10 +231,14 @@ public class BundleDeployer implements SimpleDeployer {
public boolean deploy(URI path) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING, new File(path).toString());
final File deployedFile = new File(path);
+ String jarName = extractDecodedJarNameFromString(path.toString());
+ long lastModified = deployedFile.lastModified();
+ StatusFileModificator.deleteStatusFile(jarName, this.pickupDir);
if (!canWrite(path)) {
this.logger.error("Cannot open the file " + path + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING_ERROR, path);
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
final Bundle installed;
@@ -214,6 +251,7 @@ public class BundleDeployer implements SimpleDeployer {
this.logger.error("Failed to create staging directory '" + this.workBundleInstallLocation.getAbsolutePath()
+ "' for bundle deployment.");
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING_ERROR, path);
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
}
@@ -224,6 +262,7 @@ public class BundleDeployer implements SimpleDeployer {
hostHolder = getFragmentHostFromDeployedBundleIfExsiting(stagedFile);
} catch (Exception e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLING_ERROR, e, path);
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
this.eventLogger.log(NanoDeployerLogEvents.NANO_INSTALLED, installed.getSymbolicName(), installed.getVersion());
@@ -245,19 +284,23 @@ public class BundleDeployer implements SimpleDeployer {
installed.start();
} catch (Exception e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_STARTING_ERROR, e, installed.getSymbolicName(), installed.getVersion());
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
this.eventLogger.log(NanoDeployerLogEvents.NANO_STARTED, installed.getSymbolicName(), installed.getVersion());
}
try {
if (this.bundleInfosUpdater != null && this.bundleInfosUpdater.isAvailable()) {
- String bundlesInfoLocation = BundleLocationUtil.getRelativisedURI(kernelHomeFile, stagedFile).toString();
- BundleInfosUpdater.registerToBundlesInfo(installed, bundlesInfoLocation, hostHolder != null && hostHolder.getBundleSymbolicName() != null);
+ String bundlesInfoLocation = BundleLocationUtil.getRelativisedURI(this.kernelHomeFile, stagedFile).toString();
+ BundleInfosUpdater.registerToBundlesInfo(installed, bundlesInfoLocation, hostHolder != null
+ && hostHolder.getBundleSymbolicName() != null);
}
} catch (Exception e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_PERSIST_ERROR, e, installed.getSymbolicName(), installed.getVersion());
}
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, installed.getBundleId(),
+ lastModified);
return STATUS_OK;
}
@@ -278,11 +321,15 @@ public class BundleDeployer implements SimpleDeployer {
@Override
public boolean update(URI path) {
final File updatedFile = new File(path);
+ final String jarName = extractDecodedJarNameFromString(path.toString());
+ long lastModified = updatedFile.lastModified();
final File matchingStagedFile = new File(this.workBundleInstallLocation, extractJarFileNameFromString(path.toString()));
+ StatusFileModificator.deleteStatusFile(jarName, this.pickupDir);
if (!canWrite(path)) {
this.logger.error("Cannot open the file [" + path + "] for writing. Timeout is [" + this.largeFileCopyTimeout + "].");
this.eventLogger.log(NanoDeployerLogEvents.NANO_UPDATING_ERROR, path);
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
return STATUS_ERROR;
}
@@ -301,25 +348,34 @@ public class BundleDeployer implements SimpleDeployer {
this.eventLogger.log(NanoDeployerLogEvents.NANO_UPDATED, bundle.getSymbolicName(), bundle.getVersion());
} catch (Exception e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_UPDATE_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1, lastModified);
+ return STATUS_ERROR;
}
} else {
deploy(path);
}
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundle.getBundleId(),
+ lastModified);
return STATUS_OK;
}
@Override
public boolean undeploy(Bundle bundle) {
if (bundle != null) {
- File stagingFileToDelete = new File(bundle.getLocation().substring(BundleLocationUtil.REFERENCE_FILE_PREFIX.length()));
+ String bundleLocation = bundle.getLocation();
+ File stagingFileToDelete = new File(bundleLocation.substring(BundleLocationUtil.REFERENCE_FILE_PREFIX.length()));
+ String jarName = extractDecodedJarNameFromString(bundleLocation);
+ StatusFileModificator.deleteStatusFile(jarName, this.pickupDir);
+
final FragmentHost hostHolder = getFragmentHostFromDeployedBundleIfExsiting(stagingFileToDelete);
try {
if (this.logger.isInfoEnabled()) {
this.logger.info("Removing bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion() + "' from bundles.info.");
}
if (this.bundleInfosUpdater != null && this.bundleInfosUpdater.isAvailable()) {
- String bundlesInfoLocation = BundleLocationUtil.getRelativisedURI(kernelHomeFile, stagingFileToDelete).toString();
- BundleInfosUpdater.unregisterToBundlesInfo(bundle, bundlesInfoLocation, hostHolder != null && hostHolder.getBundleSymbolicName() != null);
+ String bundlesInfoLocation = BundleLocationUtil.getRelativisedURI(this.kernelHomeFile, stagingFileToDelete).toString();
+ BundleInfosUpdater.unregisterToBundlesInfo(bundle, bundlesInfoLocation, hostHolder != null
+ && hostHolder.getBundleSymbolicName() != null);
this.logger.info("Successfully removed bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion()
+ "' from bundles.info.");
} else {
@@ -344,8 +400,11 @@ public class BundleDeployer implements SimpleDeployer {
}
} catch (BundleException e) {
this.eventLogger.log(NanoDeployerLogEvents.NANO_UNDEPLOY_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_UNDEPLOY, STATUS_ERROR, -1, -1);
return STATUS_ERROR;
}
+
+ StatusFileModificator.createStatusFile(jarName, this.pickupDir, StatusFileModificator.OP_UNDEPLOY, STATUS_OK, -1, -1);
}
return STATUS_OK;
}
@@ -373,6 +432,22 @@ public class BundleDeployer implements SimpleDeployer {
}
@Override
+ public boolean isOfflineUpdated(URI path) {
+ final String jarName = extractDecodedJarNameFromString(path.toString());
+ final File deployFile = new File(path);
+ long deployFileLastModified = deployFile.lastModified();
+ if (deployFileLastModified == StatusFileModificator.getLastModifiedFromStatusFile(jarName, this.pickupDir)) {
+ return false;
+ }
+ return true;
+ }
+
+ private String extractDecodedJarNameFromString(String path) {
+ final String jarName = path.substring(path.lastIndexOf(SLASH) + 1, path.length() - 4);
+ return URLDecoder.decode(jarName);
+ }
+
+ @Override
public DeploymentIdentity getDeploymentIdentity(URI path) {
File matchingStagingBundle = getStagedFile(path);
Bundle bundle = this.bundleContext.getBundle(BundleLocationUtil.createInstallLocation(this.kernelHomeFile, matchingStagingBundle));
diff --git a/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/StandardApplicationDeployer.java b/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/StandardApplicationDeployer.java
index 482959b..3956938 100644
--- a/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/StandardApplicationDeployer.java
+++ b/org.eclipse.virgo.nano.deployer/src/main/java/org/eclipse/virgo/nano/deployer/internal/StandardApplicationDeployer.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP AG - initial contribution
+ *******************************************************************************/
package org.eclipse.virgo.nano.deployer.internal;
@@ -30,7 +40,7 @@ import org.slf4j.LoggerFactory;
public class StandardApplicationDeployer implements ApplicationDeployer {
private static final String TOPIC_RECOVERY_COMPLETED = "org/eclipse/virgo/kernel/deployer/recovery/COMPLETED";
-
+
private EventLogger eventLogger;
private PackageAdmin packageAdmin;
@@ -53,7 +63,7 @@ public class StandardApplicationDeployer implements ApplicationDeployer {
this.bundleContext = context.getBundleContext();
this.defaultDeployer = new BundleDeployer(context.getBundleContext(), this.packageAdmin, this.eventLogger);
this.simpleDeployers.add(this.defaultDeployer);
-
+
recoveryComplete();
initialiseHotDeployer();
@@ -171,6 +181,16 @@ public class StandardApplicationDeployer implements ApplicationDeployer {
return false;
}
+ @Override
+ public boolean isOfflineUpdated(URI uri) {
+ for (SimpleDeployer deployer : this.simpleDeployers) {
+ if (deployer.canServeFileType(getFileTypeFromUri(uri))) {
+ return deployer.isOfflineUpdated(uri);
+ }
+ }
+ return false;
+ }
+
private String getFileTypeFromUri(URI uri) {
String path = uri.toString();
return path.substring(path.lastIndexOf(".") + 1);
@@ -238,7 +258,7 @@ public class StandardApplicationDeployer implements ApplicationDeployer {
public void unbindEventLogger(EventLogger logger) {
this.eventLogger = null;
}
-
+
public void bindEventAdmin(EventAdmin admin) {
this.eventAdmin = admin;
}
@@ -322,7 +342,7 @@ public class StandardApplicationDeployer implements ApplicationDeployer {
}
private void recoveryComplete() {
- eventAdmin.postEvent(new Event(TOPIC_RECOVERY_COMPLETED, (Map<String, ?>)null));
+ this.eventAdmin.postEvent(new Event(TOPIC_RECOVERY_COMPLETED, (Map<String, ?>) null));
}
-
+
}