Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / extension / dispose / DisposableManagementExtension.java @ 45716

History | View | Annotate | Download (14.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 {}  {{Task}}
26
 */
27
package org.gvsig.app.extension.dispose;
28

    
29
import java.awt.Dimension;
30
import java.awt.event.ActionEvent;
31
import java.lang.management.ManagementFactory;
32
import java.lang.management.MemoryMXBean;
33
import java.util.ArrayList;
34
import java.util.Collections;
35
import java.util.List;
36
import java.util.Set;
37
import javax.swing.JScrollPane;
38
import javax.swing.JTable;
39
import javax.swing.JTextPane;
40
import javax.swing.ListSelectionModel;
41
import javax.swing.SwingUtilities;
42
import javax.swing.event.ListSelectionEvent;
43
import javax.swing.table.AbstractTableModel;
44
import javax.swing.table.DefaultTableColumnModel;
45
import javax.swing.table.TableColumn;
46
import org.gvsig.andami.plugins.Extension;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dispose.Disposable;
49
import org.gvsig.tools.dispose.DisposableInfo;
50
import org.gvsig.tools.dispose.DisposableManager;
51
import org.gvsig.tools.exception.BaseException;
52
import org.gvsig.tools.swing.api.ToolsSwingLocator;
53
import org.gvsig.tools.swing.api.ToolsSwingUtils;
54
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
55
import org.gvsig.tools.util.LabeledValue;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58

    
59
/**
60
 * An extension to view and manage {@link Disposable} objects which are still
61
 * bound.
62
 *
63
 * TODO: remove this extension and replace with a better one, maybe based on
64
 * scripting.
65
 *
66
 * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
67
 */
68
public class DisposableManagementExtension extends Extension {
69

    
70
    public static String SHOW_COMMAND = "tools-devel-disposables-show-pendings";
71
    public static String DISPOSE_ALL_COMMAND = "tools-devel-disposables-free-all";
72

    
73
    private static final Logger LOG
74
            = LoggerFactory.getLogger(DisposableManagementExtension.class);
75

    
76
    @Override
77
    public void initialize() {
78
        // Nothing to do
79
    }
80

    
81
    @Override
82
    public void postInitialize() {
83
        super.postInitialize();
84
    }
85

    
86
    @Override
87
    public void execute(String actionCommand) {
88

    
89
        if (DISPOSE_ALL_COMMAND.equals(actionCommand)) {
90
            disposeAll();
91
        } else {
92
            if (SHOW_COMMAND.equals(actionCommand)) {
93
                DisposablesDoList panel = new DisposablesDoList();
94
                panel.showPanel();
95
            }
96
        }
97
    }
98

    
99
    private void disposeAll() {
100
        DisposableManager manager;
101
        manager = ToolsLocator.getDisposableManager();
102
        try {
103
            manager.releaseAll();
104
        } catch (BaseException ex) {
105
            LOG.error("Error disposing all bound disposable objects", ex);
106
        }
107
    }
108

    
109
    @Override
110
    public boolean isEnabled() {
111
        return true;
112
    }
113

    
114
    @Override
115
    public boolean isVisible() {
116
        return true;
117
    }
118

    
119
    class DisposablesDoList extends DisposablesDoListLayout {
120

    
121
        private DisposableManager manager;
122
        private JTable disposablesTable = null;
123
        private JTextPane infoTextArea = null;
124

    
125
        public DisposablesDoList() {
126
            manager = ToolsLocator.getDisposableManager();
127
            initComponents();
128
            SwingUtilities.invokeLater(() -> {
129
                refreshList();
130
                updateMemoryUsage();
131
            });
132
        }
133

    
134
        private void initComponents() {
135
            this.setPreferredSize(new Dimension(600, 550));
136

    
137
            this.disposablesTable = new JTable(new DisposablesTableModel());
138
            this.disposablesTable.setAutoCreateColumnsFromModel(false);
139

    
140
            DefaultTableColumnModel columnModel = new DefaultTableColumnModel();
141
            columnModel.addColumn(createTableColumn(0, ToolsSwingUtils.cols2px(5), "refs"));
142
            columnModel.addColumn(createTableColumn(1, ToolsSwingUtils.cols2px(12), "class"));
143
            columnModel.addColumn(createTableColumn(2, ToolsSwingUtils.cols2px(10), "code"));
144
            columnModel.addColumn(createTableColumn(3, ToolsSwingUtils.cols2px(12), "fullClass"));
145
            columnModel.addColumn(createTableColumn(4, ToolsSwingUtils.cols2px(25), "toString"));
146
            this.disposablesTable.setColumnModel(columnModel);
147

    
148
            this.disposablesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
149

    
150
            this.infoTextArea = new JTextPane();
151
            this.infoTextArea.setContentType("text/html");
152

    
153
            JScrollPane listScroller = new JScrollPane(this.disposablesTable);
154
            JScrollPane infoScroller = new JScrollPane(this.infoTextArea);
155
            this.splitPanel.setLeftComponent(listScroller);
156
            this.splitPanel.setRightComponent(infoScroller);
157

    
158
//            Dimension dim = this.splitPanel.getPreferredSize();
159
//            dim.height = dim.height / 2;
160
//            this.disposablesTable.setPreferredSize(dim);
161
//            this.splitPanel.invalidate();
162
            this.closeButton.addActionListener((ActionEvent arg0) -> {
163
                closeWindow();
164
            });
165
            this.closeButton.setEnabled(true);
166
            this.disposeAllButton.addActionListener((ActionEvent e) -> {
167
                disposeAll();
168
                refreshList();
169
                updateMemoryUsage();
170
            });
171
            this.disposeAllButton.setEnabled(true);
172
            this.disposeButton.addActionListener((ActionEvent e) -> {
173
                disposeSelecteds();
174
                refreshList();
175
                updateMemoryUsage();
176
            });
177
            this.disposeButton.setEnabled(true);
178
            this.disposablesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent arg0) -> {
179
                ListItemSelected();
180
                updateMemoryUsage();
181
            });
182
            this.disposablesTable.setEnabled(true);
183
            this.refreshButton.addActionListener((ActionEvent arg0) -> {
184
                refreshList();
185
                updateMemoryUsage();
186
            });
187
            this.refreshButton.setEnabled(true);
188
        }
189

    
190
        private TableColumn createTableColumn(int col, int size, String name) {
191
            TableColumn tableColumn = new TableColumn(col, size);
192
            tableColumn.setHeaderValue(name);
193
            return tableColumn;
194
        }
195

    
196
        private void refreshList() {
197
            fillTable();
198
        }
199

    
200
        private void ListItemSelected() {
201
            DisposablesTableModel model = (DisposablesTableModel) this.disposablesTable.getModel();
202
            DisposableInfo info = model.get(this.disposablesTable.getSelectedRow());
203
            if (info == null) {
204
                this.infoTextArea.setText("");
205
            } else {
206
                this.infoTextArea.setText(toHTML(info));
207
                this.infoTextArea.setCaretPosition(0);
208
            }
209
        }
210

    
211
        private void fillTable() {
212
            Set<DisposableInfo> disposables = (Set<DisposableInfo>) manager.getBoundDisposables();
213
            this.messageLabel.setText("Disposables " + disposables.size());
214

    
215
            this.disposablesTable.setModel(new DisposablesTableModel(new ArrayList<>(disposables)));
216
            this.messageLabel.setText("Pending " + disposables.size());
217
            this.infoTextArea.setText("");
218
        }
219

    
220
        private void updateMemoryUsage() {
221
            Runtime rt = Runtime.getRuntime();
222
            this.lblTotalMemory.setText(String.valueOf(rt.totalMemory() / 1024));
223
            this.lblMaxMemory.setText(String.valueOf(rt.maxMemory() / 1024));
224
            this.lblFreeMemory.setText(String.valueOf(rt.freeMemory() / 1024));
225
            this.lblActiveThreads.setText(String.valueOf(Thread.activeCount()));
226

    
227
            int objectPendingFinalizationCount = -1;
228
            try {
229
                MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
230
                objectPendingFinalizationCount = memBean.getObjectPendingFinalizationCount();
231
            } catch (ThreadDeath th) {
232

    
233
            }
234
            this.lblObjectPendingFinalization.setText(String.valueOf(objectPendingFinalizationCount));
235
        }
236

    
237
        private class DisposablesTableModel extends AbstractTableModel {
238

    
239
            private List<DisposableInfo> disposables;
240
            private final String[] columnNames;
241
            private final Class[] columnClass;
242

    
243
            public DisposablesTableModel() {
244
                this(Collections.EMPTY_LIST);
245
            }
246

    
247
            public DisposablesTableModel(List<DisposableInfo> disposables) {
248
                this.disposables = disposables;
249
                this.columnNames = new String[]{"Refs.", "Class", "Code", "Full class", "To str."};
250
                this.columnClass = new Class[]{Integer.class, String.class, Integer.class, String.class, String.class};
251
            }
252

    
253
            public DisposableInfo get(int rowIndex) {
254
                try {
255
                    return this.disposables.get(rowIndex);
256
                } catch (Throwable th) {
257
                    return null;
258
                }
259
            }
260

    
261
            @Override
262
            public int getRowCount() {
263
                return this.disposables.size();
264
            }
265

    
266
            @Override
267
            public int getColumnCount() {
268
                return this.columnNames.length;
269
            }
270

    
271
            @Override
272
            public String getColumnName(int columnIndex) {
273
                return this.columnNames[columnIndex];
274
            }
275

    
276
            @Override
277
            public Class<?> getColumnClass(int columnIndex) {
278
                return this.columnClass[columnIndex];
279
            }
280

    
281
            @Override
282
            public Object getValueAt(int rowIndex, int columnIndex) {
283
                DisposableInfo info = this.disposables.get(rowIndex);
284
                switch (columnIndex) {
285
                    case 0:
286
                        return info.getReferencesCount();
287
                    case 1:
288
                        try {
289
                        return info.getDisposable().getClass().getSimpleName();
290
                    } catch (Throwable th) {
291
                        return "(unknown)";
292
                    }
293
                    case 2:
294
                        try {
295
                        return info.getDisposable().hashCode();
296
                    } catch (Throwable th) {
297
                        return -1;
298
                    }
299
                    case 3:
300
                        try {
301
                        return info.getDisposable().getClass().getName();
302
                    } catch (Throwable th) {
303
                        return "(unknown)";
304
                    }
305
                    case 4:
306
                        try {
307
                        return info.getDisposable().toString();
308
                    } catch (Throwable th) {
309
                        return "(unknown)";
310
                    }
311
                }
312
                return null;
313
            }
314
        }
315

    
316
        public String toHTML(DisposableInfo disposableInfo) {
317
            StringBuilder buffer = new StringBuilder();
318
            Disposable disposable = disposableInfo.getDisposable();
319

    
320
            buffer.append("<b>Class</b>: ").append(disposable.getClass().getSimpleName()).append("<br>\n");
321
            buffer.append("<b>Full class</b>: ").append(disposable.getClass().getName()).append("<br>\n");
322
            buffer.append("<b>References</b>: ").append(disposableInfo.getReferencesCount()).append("<br>\n");
323
            buffer.append("<b>toString</b>: ").append(disposable.toString()).append("<br>\n");
324

    
325
            try {
326
                List<LabeledValue<StackTraceElement[]>> allStackTraces = disposableInfo.getAllStackTrace();
327
                for (int i = 0; i < allStackTraces.size(); i++) {
328
                    LabeledValue<StackTraceElement[]> trace = allStackTraces.get(i);
329
                    buffer.append("<b>#");
330
                    buffer.append(i + 1);
331
                    buffer.append(" ");
332
                    buffer.append(trace.getLabel());
333
                    buffer.append(" from (stack)</b>:<br>\n");
334
                    for (StackTraceElement stackTrace1 : trace.getValue()) {
335
                        buffer.append("&nbsp;&nbsp;").append(stackTrace1.toString().replaceAll("[<]", "&lt;").replace("[>]", "&gt;")).append("<br>\n");
336
                    }
337
                }
338

    
339
            } catch (Exception ex) {
340
                buffer.append("<br>\n<br>\nError showing stack.<br>\n").append(ex.getMessage());
341
            }
342
            return buffer.toString();
343
        }
344

    
345
        public void closeWindow() {
346
            this.setVisible(false);
347
        }
348

    
349
        public void disposeAll() {
350
            try {
351
                manager.releaseAll();
352
            } catch (BaseException ex) {
353
                LOG.error("Error disposing all bound disposable objects", ex);
354
            }
355
        }
356

    
357
        public void disposeSelecteds() {
358
            DisposablesTableModel model = (DisposablesTableModel) this.disposablesTable.getModel();
359
            for (int row : this.disposablesTable.getSelectedRows()) {
360
                DisposableInfo info = model.get(row);
361
                this.manager.release(info.getDisposable());
362
            }
363
            refreshList();
364
        }
365

    
366
        public void showPanel() {
367
            WindowManager wm = ToolsSwingLocator.getWindowManager();
368
            wm.showWindow(this, "Disposable do list", WindowManager.MODE.WINDOW);
369
        }
370

    
371
//        private class ActionListenerImpl implements ActionListener {
372
//
373
//            public ActionListenerImpl() {
374
//            }
375
//
376
//            @Override
377
//            public void actionPerformed(ActionEvent e) {
378
//                disposeSelecteds();
379
//                refreshList();
380
//                updateMemoryUsage();
381
//            }
382
//        }
383
    }
384

    
385
}