Xcos: fix memory leaks 78/10578/2
Clément DAVID [Fri, 22 Feb 2013 12:41:55 +0000 (13:41 +0100)]
Change-Id: I62f59e582a1636b35e1b32972112013b8f00e724

scilab/modules/graph/src/java/org/scilab/modules/graph/actions/RedoAction.java
scilab/modules/graph/src/java/org/scilab/modules/graph/actions/UndoAction.java
scilab/modules/graph/src/java/org/scilab/modules/graph/actions/base/DefaultAction.java
scilab/modules/graph/src/java/org/scilab/modules/graph/actions/base/GraphActionManager.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/XcosTab.java

index 4e7db9b..e43ad67 100644 (file)
@@ -17,6 +17,7 @@ package org.scilab.modules.graph.actions;
 import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+import java.lang.ref.WeakReference;
 
 import org.scilab.modules.graph.ScilabGraph;
 import org.scilab.modules.graph.actions.base.ActionConstraint;
@@ -47,14 +48,14 @@ public class RedoAction extends DefaultAction {
      * Manage enable modification
      */
     private final class RedoConstraint extends ActionConstraint {
-        private final ScilabGraph scilabGraph;
+        private final WeakReference<ScilabGraph> scilabGraph;
 
         /**
          * Default constructor
          * @param scilabGraph the graph to work on
          */
         public RedoConstraint(ScilabGraph scilabGraph) {
-            this.scilabGraph = scilabGraph;
+            this.scilabGraph = new WeakReference<ScilabGraph>(scilabGraph);
         }
 
         /**
@@ -90,7 +91,12 @@ public class RedoAction extends DefaultAction {
          */
         @Override
         public void invoke(Object sender, mxEventObject evt) {
-            boolean canRedo = scilabGraph.getUndoManager().canRedo();
+            final ScilabGraph graph = scilabGraph.get();
+            if (graph == null) {
+                return;
+            }
+
+            boolean canRedo = graph.getUndoManager().canRedo();
             super.setEnabled(canRedo);
         }
     }
index 091431e..7d38824 100644 (file)
@@ -17,6 +17,7 @@ package org.scilab.modules.graph.actions;
 import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+import java.lang.ref.WeakReference;
 
 import org.scilab.modules.graph.ScilabGraph;
 import org.scilab.modules.graph.actions.base.ActionConstraint;
@@ -47,14 +48,14 @@ public class UndoAction extends DefaultAction {
      * Manage enable modification
      */
     private final class UndoConstraint extends ActionConstraint {
-        private final ScilabGraph scilabGraph;
+        private final WeakReference<ScilabGraph> scilabGraph;
 
         /**
          * Default constructor
          * @param scilabGraph the associated scilab graph
          */
         public UndoConstraint(ScilabGraph scilabGraph) {
-            this.scilabGraph = scilabGraph;
+            this.scilabGraph = new WeakReference<ScilabGraph>(scilabGraph);
         }
 
         /**
@@ -89,7 +90,12 @@ public class UndoAction extends DefaultAction {
          */
         @Override
         public void invoke(Object sender, mxEventObject evt) {
-            boolean canUndo = scilabGraph.getUndoManager().canUndo();
+            final ScilabGraph graph = scilabGraph.get();
+            if (graph == null) {
+                return;
+            }
+
+            boolean canUndo = graph.getUndoManager().canUndo();
             super.setEnabled(canUndo);
         }
     }
index ca3ecff..f1101c7 100644 (file)
@@ -2,11 +2,11 @@
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2009-2009 - DIGITEO - Bruno JOFRET
  * Copyright (C) 2009-2010 - DIGITEO - Clement DAVID
- * 
+ *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
  * you should have received as part of this distribution.  The terms
- * are also available at    
+ * are also available at
  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
  *
  */
@@ -16,6 +16,7 @@ package org.scilab.modules.graph.actions.base;
 import java.awt.Component;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+import java.lang.ref.WeakReference;
 
 import javax.swing.AbstractAction;
 import javax.swing.Action;
@@ -41,11 +42,11 @@ import com.mxgraph.swing.mxGraphComponent;
  * Default action for a Scilab Graph
  */
 public abstract class DefaultAction extends CommonCallBack {
-    private final ScilabGraph scilabGraph;
+    private final WeakReference<ScilabGraph> scilabGraph;
 
     /**
      * Default constructor.
-     * 
+     *
      * The {@link AbstractAction} object is configured using the reflection API.
      * So you have to be sure that the following fields are declared as static
      * final fields of each subclasses.
@@ -57,13 +58,13 @@ public abstract class DefaultAction extends CommonCallBack {
      * {@link KeyEvent})</li>
      * <li>int ACCELERATOR_KEY : The key mask to apply to the mnemonic</li>
      * </ul>
-     * 
+     *
      * @param scilabGraph
      *            corresponding Scilab Graph
      */
     public DefaultAction(ScilabGraph scilabGraph) {
         super("");
-        this.scilabGraph = scilabGraph;
+        this.scilabGraph = new WeakReference<ScilabGraph>(scilabGraph);
 
         installProperties();
     }
@@ -111,7 +112,7 @@ public abstract class DefaultAction extends CommonCallBack {
          * Set up the accelerator instead of the mnemonic as the menu is the
          * preferred way on keyboard control. We are using Action.MNEMONIC_KEY
          * as keyboard key and Action.ACCELERATOR_KEY as a mask.
-         * 
+         *
          * Install it only when there is a real shortcut (with a mnemonic).
          */
         if (mnemonic != 0) {
@@ -122,14 +123,14 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Create a menu item associated with the graph
-     * 
+     *
      * @param graph
      *            the graph to work on
      * @param klass
      *            the associated klass
      * @return the menu item
      */
-    protected static MenuItem createMenu(ScilabGraph graph, final Class<? extends DefaultAction> klass) {
+    protected static MenuItem createMenu(ScilabGraph graph, final Class <? extends DefaultAction > klass) {
         DefaultAction action = GraphActionManager.getInstance(graph, klass);
         MenuItem item = ScilabMenuItem.createMenuItem();
 
@@ -141,14 +142,14 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Create a menu item associated with the graph
-     * 
+     *
      * @param graph
      *            the graph to work on
      * @param klass
      *            the associated klass
      * @return the push button
      */
-    protected static PushButton createButton(ScilabGraph graph, final Class<? extends DefaultAction> klass) {
+    protected static PushButton createButton(ScilabGraph graph, final Class <? extends DefaultAction > klass) {
         DefaultAction action = GraphActionManager.getInstance(graph, klass);
         PushButton item = ScilabPushButton.createPushButton();
 
@@ -163,14 +164,14 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Create a menu item associated with the graph
-     * 
+     *
      * @param graph
      *            the graph to work on
      * @param klass
      *            the associated klass
      * @return the checkbox item
      */
-    protected static CheckBoxMenuItem createCheckBoxMenu(ScilabGraph graph, Class<? extends DefaultAction> klass) {
+    protected static CheckBoxMenuItem createCheckBoxMenu(ScilabGraph graph, Class <? extends DefaultAction > klass) {
         DefaultAction action = GraphActionManager.getInstance(graph, klass);
         CheckBoxMenuItem item = ScilabCheckBoxMenuItem.createCheckBoxMenuItem();
 
@@ -182,7 +183,7 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Constructor
-     * 
+     *
      * @param label
      *            action descriptor
      * @param scilabGraph
@@ -191,19 +192,20 @@ public abstract class DefaultAction extends CommonCallBack {
     @Deprecated
     protected DefaultAction(String label, ScilabGraph scilabGraph) {
         super(label);
-        this.scilabGraph = scilabGraph;
+        this.scilabGraph = new WeakReference<ScilabGraph>(scilabGraph);
     }
 
     /**
      * Get associated graph
-     * 
+     *
      * @param e
      *            event
      * @return Returns the graph for the given action event.
      */
     protected final ScilabGraph getGraph(ActionEvent e) {
-        if (this.scilabGraph != null) {
-            return this.scilabGraph;
+        final ScilabGraph graph = scilabGraph.get();
+        if (graph != null) {
+            return graph;
         }
 
         if (e == null) {
@@ -225,7 +227,7 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Create a button for a graph toolbar
-     * 
+     *
      * @param title
      *            label of the menu
      * @param icon
@@ -251,7 +253,7 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Action
-     * 
+     *
      * @param e
      *            parameters
      * @see org.scilab.modules.gui.events.callback.CallBack#actionPerformed(java.awt.event.ActionEvent)
@@ -261,7 +263,7 @@ public abstract class DefaultAction extends CommonCallBack {
 
     /**
      * Not used
-     * 
+     *
      * @see org.scilab.modules.gui.events.callback.CallBack#callBack()
      */
     @Override
index 32cb600..7ed85fe 100644 (file)
 package org.scilab.modules.graph.actions.base;
 
 import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.WeakHashMap;
 
 import javax.swing.Action;
 import javax.swing.KeyStroke;
@@ -27,8 +30,8 @@ import org.scilab.modules.graph.ScilabGraph;
  * Implement construction methods for Actions.
  */
 public final class GraphActionManager {
-    private static HashMap<ScilabGraph, Set<DefaultAction>> perGraphAction = new HashMap<ScilabGraph, Set<DefaultAction>>();
-    private static HashSet<DefaultAction> nullGraphAction = new HashSet<DefaultAction>();
+    private static Map<ScilabGraph, Set<DefaultAction>> perGraphAction = new WeakHashMap<ScilabGraph, Set<DefaultAction>>();
+    private static Set<DefaultAction> nullGraphAction = Collections.newSetFromMap(new WeakHashMap<DefaultAction, Boolean>());
 
     /**
      * Static class so private constructor
@@ -97,7 +100,7 @@ public final class GraphActionManager {
             if (perGraphAction.containsKey(graph)) {
                 actionSet = perGraphAction.get(graph);
             } else {
-                actionSet = new HashSet<DefaultAction>();
+                actionSet = Collections.newSetFromMap(new WeakHashMap<DefaultAction, Boolean>());
                 perGraphAction.put(graph, actionSet);
             }
         }
index 0f49341..d2000db 100644 (file)
@@ -14,6 +14,7 @@ package org.scilab.modules.xcos;
 
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.lang.ref.WeakReference;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.List;
@@ -156,26 +157,41 @@ public class XcosTab extends SwingScilabTab implements SimpleTab {
     private PushButton xcosDocumentationAction;
 
     private static class ClosingOperation implements org.scilab.modules.gui.utils.ClosingOperationsManager.ClosingOperation {
-        private final XcosDiagram graph;
+        private final WeakReference<XcosDiagram> graph;
 
         public ClosingOperation(XcosDiagram graph) {
-            this.graph = graph;
+            this.graph = new WeakReference<XcosDiagram>(graph);
         }
 
         @Override
         public int canClose() {
-            return Xcos.getInstance().canClose(graph) ? 1 : 0;
+            final XcosDiagram diag = graph.get();
+            if (diag == null) {
+                return 1;
+            }
+
+            return Xcos.getInstance().canClose(diag) ? 1 : 0;
         }
 
         @Override
         public void destroy() {
-            Xcos.getInstance().destroy(graph);
-            graph.setOpened(false);
+            final XcosDiagram diag = graph.get();
+            if (diag == null) {
+                return;
+            }
+
+            Xcos.getInstance().destroy(diag);
+            diag.setOpened(false);
         }
 
         @Override
         public String askForClosing(final List<SwingScilabTab> list) {
-            return Xcos.getInstance().askForClosing(graph, list);
+            final XcosDiagram diag = graph.get();
+            if (diag == null) {
+                return null;
+            }
+
+            return Xcos.getInstance().askForClosing(diag, list);
         }
 
         @Override
@@ -209,17 +225,22 @@ public class XcosTab extends SwingScilabTab implements SimpleTab {
     }
 
     private static class EndedRestoration implements WindowsConfigurationManager.EndedRestoration {
-        private final XcosDiagram graph;
+        private final WeakReference<XcosDiagram> graph;
 
         public EndedRestoration(XcosDiagram graph) {
-            this.graph = graph;
+            this.graph = new WeakReference<XcosDiagram>(graph);
         }
 
         @Override
         public void finish() {
-            graph.updateTabTitle();
+            final XcosDiagram diag = graph.get();
+            if (diag == null) {
+                return;
+            }
+
+            diag.updateTabTitle();
 
-            ConfigurationManager.getInstance().removeFromRecentTabs(graph.getGraphTab());
+            ConfigurationManager.getInstance().removeFromRecentTabs(diag.getGraphTab());
         }
     }