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 2012/10/06 06:38:09 UTC

svn commit: r1394917 - in /geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core: GeronimoServerBehaviourDelegate.java HotCodeReplaceListener.java internal/Trace.java

Author: gawor
Date: Sat Oct  6 04:38:08 2012
New Revision: 1394917

URL: http://svn.apache.org/viewvc?rev=1394917&view=rev
Log:
GERONIMODEVTOOLS-805: Attempt to restart bundle if Eclipse HCR fails

Added:
    geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.java   (with props)
Modified:
    geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/GeronimoServerBehaviourDelegate.java
    geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/internal/Trace.java

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=1394917&r1=1394916&r2=1394917&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 Sat Oct  6 04:38:08 2012
@@ -17,6 +17,7 @@
 package org.apache.geronimo.st.v30.core;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -64,6 +65,7 @@ import org.apache.geronimo.st.v30.core.o
 import org.apache.geronimo.st.v30.core.osgi.OSGiModuleHandler;
 import org.apache.geronimo.system.jmx.KernelDelegate;
 import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
@@ -86,7 +88,10 @@ import org.eclipse.debug.core.sourcelook
 import org.eclipse.debug.core.sourcelookup.ISourceContainer;
 import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer;
 import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.util.IClassFileReader;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
 import org.eclipse.jdt.internal.launching.RuntimeClasspathEntry;
 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
@@ -622,10 +627,15 @@ public class GeronimoServerBehaviourDele
             /*
              * Try class hot swap first and if it fails fallback to regular bundle update.
              */
-            if (!refreshBundleClasses(dm, ebaModule, bundleModule, ebaName, bundleId)) {
+            ClassReplaceResult result = refreshBundleClasses(dm, ebaModule, bundleModule, ebaName, bundleId);
+            if (result != ClassReplaceResult.SUCCESS) {
                 File file = DeploymentUtils.getTargetFile(getServer(), bundleModule);
                 dm.updateEBAContent(ebaName, bundleId, file);
+                if (result == ClassReplaceResult.FAIL_FORCE_GC) {
+                    invokeGC();
+                }
             }
+            
         } catch (Exception e) {
             return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.REFRESH_FAIL, e);
         }
@@ -635,48 +645,86 @@ 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);    
+    private enum ClassReplaceResult { SUCCESS, FAIL, FAIL_FORCE_GC };
+    
+    private ClassReplaceResult refreshBundleClasses(ExtendedDeploymentManager dm, IModule ebaModule, IModule bundleModule, AbstractName ebaName, long bundleId) throws Exception {
+        Trace.traceEntry(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;
+            Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Class redefinition is not supported");        
+            return ClassReplaceResult.FAIL;
         }
         // ensure only classes have changed
         IModule[] module = new IModule[] { ebaModule, bundleModule };
         IModuleResourceDelta[] delta = getPublishedResourceDelta(module);
         IModuleResource[] classResources = DeploymentUtils.getChangedClassResources(delta);
         if (classResources == null) {
-            Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Non-class resource modifications found");
-            return false;
+            Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Non-class resource modifications found");
+            return ClassReplaceResult.FAIL;
         }
         // 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;
+            Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Error creating file with resource modifications");
+            return ClassReplaceResult.FAIL;
         }
         if (eclipseHotSwap) {
-            // debug mode - Eclipse will do class hot swap for us - save changes only
-            boolean result = dm.updateEBAArchive(ebaName, bundleId, changeSetFile, true);
-            Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Eclipse HCR - updated class files only", result);
-            return true;
+            // debug mode - Eclipse will do class hot swap for us
+            IDebugTarget target = getServer().getLaunch().getDebugTarget();
+            if (isOutOfSynch(target, classResources)) {
+                Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Eclipse HCR failed");
+                return ClassReplaceResult.FAIL_FORCE_GC;
+            } else {            
+                // save changes only
+                boolean result = dm.updateEBAArchive(ebaName, bundleId, changeSetFile, true);
+                Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Eclipse HCR - updated class files only", result);
+                return ClassReplaceResult.SUCCESS;
+            }
         } else {
             // non-debug mode - try class hot swap
             if (!dm.hotSwapEBAContent(ebaName, bundleId, changeSetFile, true)) {
                 changeSetFile.delete();
-                Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Bundle class hot swap cannot be preformed");
-                return false;
+                Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Bundle class hot swap cannot be preformed");
+                return ClassReplaceResult.FAIL;
             } else {
                 changeSetFile.delete();
-                Trace.tracePoint("Exit ", Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Bundle class hot swap was succesfully preformed");
-                return true;
+                Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.refreshBundleClasses", "Bundle class hot swap was succesfully preformed");
+                return ClassReplaceResult.SUCCESS;
+            }
+        }
+    }
+
+    private boolean isOutOfSynch(IDebugTarget target, IModuleResource[] classResources) {
+        Trace.traceEntry(Activator.traceCore, "GeronimoServerBehaviourDelegate.isOutOfSynch");    
+        if (target instanceof JDIDebugTarget) {
+            JDIDebugTarget javaTarget = (JDIDebugTarget) target;
+            for (IModuleResource resource : classResources) {
+                String path = null;
+                IFile srcIFile = (IFile) resource.getAdapter(IFile.class);
+                if (srcIFile != null) {
+                    path = srcIFile.getLocation().toOSString();
+                } else {
+                    File srcFile = (File) resource.getAdapter(File.class);
+                    path = srcFile.getAbsolutePath();
+                }
+            
+                IClassFileReader reader = ToolFactory.createDefaultClassFileReader(path, IClassFileReader.CLASSFILE_ATTRIBUTES);
+                if (reader != null) {
+                    String className = new String(reader.getClassName()).replace('/', '.');
+                    if (javaTarget.isOutOfSynch(className)) {
+                        // out-of-synch class found
+                        Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.isOutOfSynch", "Out-of-synch class found", className);
+                        return true;                        
+                    }                    
+                }
             }
         }
+        Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.isOutOfSynch");   
+        return false;
     }
     
     private boolean isEclipseHotSwapEnabled() {
-        Trace.tracePoint("Enter", Activator.traceCore, "GeronimoServerBehaviourDelegate.isEclipseHotSwapEnabled");
+        Trace.traceEntry(Activator.traceCore, "GeronimoServerBehaviourDelegate.isEclipseHotSwapEnabled");
         boolean enabled = false;
         IServer server = getServer();
         if (ILaunchManager.DEBUG_MODE.equals(server.getMode())) {
@@ -685,11 +733,12 @@ public class GeronimoServerBehaviourDele
                 IDebugTarget target = launch.getDebugTarget();
                 if (target instanceof IJavaDebugTarget) {
                     IJavaDebugTarget javaTarget = (IJavaDebugTarget) target;
+                    javaTarget.addHotCodeReplaceListener(new HotCodeReplaceListener());
                     enabled = javaTarget.supportsHotCodeReplace();
                 }
             }            
         }
-        Trace.tracePoint("Exit", Activator.traceCore, "GeronimoServerBehaviourDelegate.isEclipseHotSwapEnabled", enabled);
+        Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.isEclipseHotSwapEnabled", enabled);
         return enabled;
     }
     
@@ -1493,6 +1542,18 @@ public class GeronimoServerBehaviourDele
         return getMBean(connection, "osgi.core:type=framework,*", "Framework");
     }
     
+    private void invokeGC() {
+        Trace.traceEntry(Activator.traceCore, "GeronimoServerBehaviourDelegate.invokeGC");
+        try {
+            MBeanServerConnection connection = getServerConnection();
+            ObjectName name = getMBean(connection, "java.lang:type=Memory", "Memory");
+            connection.invoke(name, "gc", new Object [0], new String [0]);
+        } catch (Exception e) {
+            Trace.trace(Trace.ERROR, "Error while requesting server gc", e, Activator.traceCore);
+        }
+        Trace.traceExit(Activator.traceCore, "GeronimoServerBehaviourDelegate.invokeGC");
+    }
+    
     public Target[] getTargets() {
         return null;
     }

Added: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.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/HotCodeReplaceListener.java?rev=1394917&view=auto
==============================================================================
--- geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.java (added)
+++ geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.java Sat Oct  6 04:38:08 2012
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.st.v30.core;
+
+import org.apache.geronimo.st.v30.core.internal.Trace;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaHotCodeReplaceListener;
+
+public class HotCodeReplaceListener implements IJavaHotCodeReplaceListener {
+
+    public void hotCodeReplaceFailed(IJavaDebugTarget target, DebugException exception) {
+        Trace.log(Trace.INFO, "Eclipse hot code replace failed - will restart bundle", exception);
+    }
+
+    public void hotCodeReplaceSucceeded(IJavaDebugTarget target) {
+        Trace.trace(Trace.INFO, "Eclipse hot code replace was successful", Activator.traceCore);
+    }
+
+    public void obsoleteMethods(IJavaDebugTarget target) {
+        Trace.trace(Trace.INFO, "Obsolete methods detected", Activator.traceCore);
+    } 
+    
+}

Propchange: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/HotCodeReplaceListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/internal/Trace.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/internal/Trace.java?rev=1394917&r1=1394916&r2=1394917&view=diff
==============================================================================
--- geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/internal/Trace.java (original)
+++ geronimo/devtools/eclipse-plugin/trunk/plugins/org.apache.geronimo.st.v30.core/src/main/java/org/apache/geronimo/st/v30/core/internal/Trace.java Sat Oct  6 04:38:08 2012
@@ -152,4 +152,14 @@ public class Trace {
     public static void traceExit(boolean opt, String classDotMethod, Object... parms) {
         tracePoint("Exit", opt, classDotMethod, parms);
     }
+    
+    public static void log(int level, String message, Throwable exception) {
+        log.trace(level, Activator.PLUGIN_ID, message, exception);
+        if (Activator.console) {
+            System.out.println(buildMessage(message));
+            if (exception != null) {
+                exception.printStackTrace(System.out);
+            }
+        }
+    }
 }