You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2011/10/31 21:49:26 UTC
svn commit: r1195665 - in
/geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core:
DeploymentUtils.java GeronimoServerBehaviourDelegate.java
Author: gawor
Date: Mon Oct 31 20:49:25 2011
New Revision: 1195665
URL: http://svn.apache.org/viewvc?rev=1195665&view=rev
Log:
GERONIMODEVTOOLS-771: Support for class hot swap for OSGi applications
Modified:
geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/DeploymentUtils.java
geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/GeronimoServerBehaviourDelegate.java
Modified: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/DeploymentUtils.java
URL: http://svn.apache.org/viewvc/geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/DeploymentUtils.java?rev=1195665&r1=1195664&r2=1195665&view=diff
==============================================================================
--- geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/DeploymentUtils.java (original)
+++ geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/DeploymentUtils.java Mon Oct 31 20:49:25 2011
@@ -17,6 +17,7 @@
package org.apache.geronimo.st.v30.core;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -36,6 +37,7 @@ import org.eclipse.core.runtime.CoreExce
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jst.j2ee.application.internal.operations.AppClientComponentExportDataModelProvider;
import org.eclipse.jst.j2ee.application.internal.operations.EARComponentExportDataModelProvider;
@@ -58,6 +60,7 @@ import org.eclipse.wst.server.core.model
import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.server.core.model.IModuleResourceDelta;
import org.eclipse.wst.server.core.util.ProjectModule;
+import org.eclipse.wst.server.core.util.PublishHelper;
/**
* @version $Rev$ $Date$
@@ -379,7 +382,7 @@ public class DeploymentUtils {
}
}
return false;
- }
+ }
public static boolean isInstalledModule(IServer server, String configId) {
Trace.tracePoint("Entry", Activator.traceCore, "DeploymentUtils.isInstalledModule", server, configId);
@@ -434,4 +437,74 @@ public class DeploymentUtils {
return configId;
}
+
+ public static IModuleResource[] getChangedClassResources(IModuleResourceDelta[] deltaArray) {
+ Trace.tracePoint("Entry", Activator.traceCore, "DeploymentUtils.getChangedClassResources", deltaArray);
+ List<IModuleResource> changedClassResources = new ArrayList<IModuleResource>();
+ // collect only changed classes resources
+ if (collectChangedClassResources(deltaArray, changedClassResources) && !changedClassResources.isEmpty()) {
+ // modified class resources were only found
+ IModuleResource[] resources = new IModuleResource[changedClassResources.size()];
+ changedClassResources.toArray(resources);
+ Trace.tracePoint("Exit ", Activator.traceCore, "DeploymentUtils.getChangedClassResources", resources);
+ return resources;
+ } else {
+ // added or removed resources or non-class resources were found
+ Trace.tracePoint("Exit ", Activator.traceCore, "DeploymentUtils.getChangedClassResources", "Added or removed resources or non-class resources were found");
+ return null;
+ }
+ }
+
+ private static boolean collectChangedClassResources(IModuleResourceDelta[] deltaArray, List<IModuleResource> list) {
+ for (IModuleResourceDelta delta : deltaArray) {
+ int kind = delta.getKind();
+ if (kind == IModuleResourceDelta.ADDED || kind == IModuleResourceDelta.REMOVED) {
+ return false;
+ }
+ IModuleResource resource = delta.getModuleResource();
+ if (resource instanceof IModuleFile) {
+ String name = resource.getName();
+ if (!name.endsWith(".class")) {
+ return false;
+ }
+ if (kind == IModuleResourceDelta.CHANGED) {
+ list.add(resource);
+ }
+ } else if (resource instanceof IModuleFolder) {
+ IModuleResourceDelta[] childDeltaArray = delta.getAffectedChildren();
+ if (!collectChangedClassResources(childDeltaArray, list)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public static File createChangeSetFile(IModuleResource[] resources) {
+ Trace.tracePoint("Entry", Activator.traceCore, "DeploymentUtils.createChangeSetFile", resources);
+
+ File file = null;
+ try {
+ file = File.createTempFile("changeset", ".jar");
+ } catch (IOException e) {
+ Trace.tracePoint("Exit ", Activator.traceCore, "DeploymentUtils.createChangeSetFile", e);
+ return null;
+ }
+
+ PublishHelper publishHelper = new PublishHelper(null);
+ IStatus[] statusArray = publishHelper.publishZip(resources, new Path(file.getAbsolutePath()), null);
+ if (statusArray != null) {
+ for (IStatus status : statusArray) {
+ if (!status.isOK()) {
+ file.delete();
+ Trace.tracePoint("Exit ", Activator.traceCore, "DeploymentUtils.createChangeSetFile", status);
+ return null;
+ }
+ }
+ }
+
+ Trace.tracePoint("Exit ", Activator.traceCore, "DeploymentUtils.createChangeSetFile", file);
+ return file;
+ }
+
}
Modified: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/GeronimoServerBehaviourDelegate.java
URL: http://svn.apache.org/viewvc/geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/GeronimoServerBehaviourDelegate.java?rev=1195665&r1=1195664&r2=1195665&view=diff
==============================================================================
--- geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/GeronimoServerBehaviourDelegate.java (original)
+++ geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/GeronimoServerBehaviourDelegate.java Mon Oct 31 20:49:25 2011
@@ -105,8 +105,10 @@ import org.eclipse.wst.server.core.Serve
import org.eclipse.wst.server.core.internal.IModulePublishHelper;
import org.eclipse.wst.server.core.internal.ProgressUtil;
import org.eclipse.wst.server.core.model.IModuleFile;
+import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.server.core.model.IModuleResourceDelta;
import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
+import org.eclipse.wst.server.core.util.PublishHelper;
import org.eclipse.wst.server.core.util.SocketUtil;
/**
@@ -589,10 +591,7 @@ public class GeronimoServerBehaviourDele
private IStatus refreshBundle(IModule ebaModule, IModule bundleModule, AbstractName ebaName, Map<String, Long> bundleMap) {
Trace.tracePoint("Entry", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundle", ebaModule, bundleModule, ebaName, bundleMap);
-
try {
- File file = DeploymentUtils.getTargetFile(getServer(), bundleModule);
-
String symbolicName = AriesHelper.getSymbolicName(bundleModule);
Long bundleId = bundleMap.get(symbolicName);
@@ -602,7 +601,13 @@ public class GeronimoServerBehaviourDele
}
ExtendedDeploymentManager dm = (ExtendedDeploymentManager) DeploymentCommandFactory.getDeploymentManager(getServer());
- dm.updateEBAContent(ebaName, bundleId, file);
+ /*
+ * Try class hot swap first and if it fails fallback to regular bundle update.
+ */
+ if (!refreshBundleClasses(dm, ebaModule, bundleModule, ebaName, bundleId)) {
+ File file = DeploymentUtils.getTargetFile(getServer(), bundleModule);
+ dm.updateEBAContent(ebaName, bundleId, file);
+ }
} catch (Exception e) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.REFRESH_FAIL, e);
}
@@ -612,6 +617,52 @@ public class GeronimoServerBehaviourDele
return Status.OK_STATUS;
}
+ private boolean refreshBundleClasses(ExtendedDeploymentManager dm, IModule ebaModule, IModule bundleModule, AbstractName ebaName, long bundleId) throws Exception {
+ Trace.tracePoint("Entry", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", ebaModule, bundleModule, ebaName, bundleId);
+ // check if class hot swap is supported
+ if (!dm.isRedefineClassesSupported()) {
+ Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Class redefinition is not supported");
+ return false;
+ }
+ // ensure only classes have changed
+ IModuleResourceDelta[] delta = getPublishedResourceDelta(new IModule[] { ebaModule, bundleModule });
+ IModuleResource[] classResources = DeploymentUtils.getChangedClassResources(delta);
+ if (classResources == null) {
+ Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Non-class resource modifications found");
+ return false;
+ }
+ // create temp. zip with the changes
+ File changeSetFile = DeploymentUtils.createChangeSetFile(classResources);
+ if (changeSetFile == null) {
+ Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Error creating file with resource modifications");
+ return false;
+ }
+ // get document base for the module if it is expanded
+ String documentBase = getServerDelegate().isNoRedeploy() ? getWebModuleDocumentBase(bundleModule) : null;
+ // see if the classes can be hot swapped - update archive if module is not expanded
+ if (!dm.hotSwapEBAContent(ebaName, bundleId, changeSetFile, documentBase == null)) {
+ Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Bundle class hot swap cannot be preformed");
+ changeSetFile.delete();
+ return false;
+ } else {
+ changeSetFile.delete();
+ }
+ if (documentBase != null) {
+ PublishHelper publishHelper = new PublishHelper(getTempDirectory().toFile());
+ IStatus[] statusArray = publishHelper.publishFull(classResources, new Path(documentBase), null);
+ if (statusArray != null) {
+ // XXX: in case of an error should we return false to force full re-deploy?
+ for (IStatus status : statusArray) {
+ if (!status.isOK()) {
+ Trace.trace(Trace.WARNING, "Error publishing changes: " + status.getMessage(), status.getException(), Activator.traceCore);
+ }
+ }
+ }
+ }
+ Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Bundle class hot swap was succesfully preformed", documentBase);
+ return true;
+ }
+
private static class ModuleDelta {
private final IModule[] module;
private int delta = NO_CHANGE;
@@ -938,28 +989,34 @@ public class GeronimoServerBehaviourDele
Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.invokeCommand");
}
- private IStatus tryFileReplace(IModule[] module) {
- Trace.tracePoint("Entry", Activator.traceCore, "GeronimoServerBehaviourDelegate.tryFileReplace", module.toString());
+ private String getWebModuleDocumentBase(IModule webModule) {
+ Trace.tracePoint("Entry", Activator.traceCore, "GeronimoServerBehaviourDelegate.getWebModuleDocumentBase", webModule);
- IModule webModule = module[module.length - 1];
if (webModule.isExternal()) {
- Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.tryFileReplace", "External module");
+ Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.getWebModuleDocumentBase", "External module");
return null;
}
-
+
String contextPath = getServerDelegate().getContextPath(webModule);
if (contextPath == null) {
- Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.tryFileReplace", "Context path is null");
+ Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.getWebModuleDocumentBase", "Context path is null");
return null;
}
- Trace.trace(Trace.INFO, "Context path: " + contextPath, Activator.logCore);
String documentBase = getWebModuleDocumentBase(contextPath);
- if (documentBase == null || documentBase.length() == 0) {
+ Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.getWebModuleDocumentBase", contextPath, documentBase);
+ return documentBase;
+ }
+
+ private IStatus tryFileReplace(IModule[] module) {
+ Trace.tracePoint("Entry", Activator.traceCore, "GeronimoServerBehaviourDelegate.tryFileReplace", module.toString());
+
+ IModule webModule = module[module.length - 1];
+ String documentBase = getWebModuleDocumentBase(webModule);
+ if (documentBase == null ) {
Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.tryFileReplace", "Document base is null");
return null;
}
- Trace.trace(Trace.INFO, "Document base: " + documentBase, Activator.logCore);
List<IModuleResourceDelta> modifiedFiles = findModifiedFiles(module);
if (modifiedFiles == null) {
@@ -1584,7 +1641,7 @@ public class GeronimoServerBehaviourDele
String moduleContextPath = (String) kernel.getAttribute(name, "contextPath");
if (contextPath.equals(moduleContextPath)) {
String docBase = (String) kernel.getAttribute(name, "docBase");
- return docBase;
+ return (docBase != null && docBase.length() > 0) ? docBase : null;
}
} catch (GBeanNotFoundException e) {
// ignore