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(" ").append(stackTrace1.toString().replaceAll("[<]", "<").replace("[>]", ">")).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 |
} |