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 @ 45707
History | View | Annotate | Download (13.4 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 |
|
38 |
import javax.swing.JScrollPane; |
39 |
import javax.swing.JTable; |
40 |
import javax.swing.JTextPane; |
41 |
import javax.swing.ListSelectionModel; |
42 |
import javax.swing.SwingUtilities; |
43 |
import javax.swing.event.ListSelectionEvent; |
44 |
import javax.swing.table.AbstractTableModel; |
45 |
import javax.swing.table.DefaultTableColumnModel; |
46 |
import javax.swing.table.TableColumn; |
47 |
import javax.swing.table.TableColumnModel; |
48 |
|
49 |
import org.gvsig.andami.plugins.Extension; |
50 |
import org.gvsig.tools.ToolsLocator; |
51 |
import org.gvsig.tools.dispose.Disposable; |
52 |
import org.gvsig.tools.dispose.DisposableInfo; |
53 |
import org.gvsig.tools.dispose.DisposableManager; |
54 |
import org.gvsig.tools.exception.BaseException; |
55 |
import org.gvsig.tools.swing.api.ToolsSwingLocator; |
56 |
import org.gvsig.tools.swing.api.ToolsSwingUtils; |
57 |
import org.gvsig.tools.swing.api.windowmanager.WindowManager; |
58 |
import org.slf4j.Logger; |
59 |
import org.slf4j.LoggerFactory; |
60 |
|
61 |
/**
|
62 |
* An extension to view and manage {@link Disposable} objects which are still
|
63 |
* bound.
|
64 |
*
|
65 |
* TODO: remove this extension and replace with a better one, maybe based on
|
66 |
* scripting.
|
67 |
*
|
68 |
* @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
|
69 |
*/
|
70 |
public class DisposableManagementExtension extends Extension { |
71 |
|
72 |
public static String SHOW_COMMAND = "tools-devel-disposables-show-pendings"; |
73 |
public static String DISPOSE_ALL_COMMAND = "tools-devel-disposables-free-all"; |
74 |
|
75 |
private static final Logger LOG |
76 |
= LoggerFactory.getLogger(DisposableManagementExtension.class); |
77 |
|
78 |
@Override
|
79 |
public void initialize() { |
80 |
// Nothing to do
|
81 |
} |
82 |
|
83 |
@Override
|
84 |
public void postInitialize() { |
85 |
super.postInitialize();
|
86 |
} |
87 |
|
88 |
@Override
|
89 |
public void execute(String actionCommand) { |
90 |
|
91 |
if (DISPOSE_ALL_COMMAND.equals(actionCommand)) {
|
92 |
disposeAll(); |
93 |
} else {
|
94 |
if (SHOW_COMMAND.equals(actionCommand)) {
|
95 |
DisposablesDoList panel = new DisposablesDoList();
|
96 |
panel.showPanel(); |
97 |
} |
98 |
} |
99 |
} |
100 |
|
101 |
private void disposeAll() { |
102 |
DisposableManager manager; |
103 |
manager = ToolsLocator.getDisposableManager(); |
104 |
try {
|
105 |
manager.releaseAll(); |
106 |
} catch (BaseException ex) {
|
107 |
LOG.error("Error disposing all bound disposable objects", ex);
|
108 |
} |
109 |
} |
110 |
|
111 |
@Override
|
112 |
public boolean isEnabled() { |
113 |
return true; |
114 |
} |
115 |
|
116 |
@Override
|
117 |
public boolean isVisible() { |
118 |
return true; |
119 |
} |
120 |
|
121 |
class DisposablesDoList extends DisposablesDoListLayout { |
122 |
|
123 |
private DisposableManager manager;
|
124 |
private JTable disposablesTable = null; |
125 |
private JTextPane infoTextArea = null; |
126 |
|
127 |
public DisposablesDoList() {
|
128 |
manager = ToolsLocator.getDisposableManager(); |
129 |
initComponents(); |
130 |
SwingUtilities.invokeLater(() -> {
|
131 |
refreshList(); |
132 |
updateMemoryUsage(); |
133 |
}); |
134 |
} |
135 |
|
136 |
private void initComponents() { |
137 |
this.setPreferredSize(new Dimension(600, 550)); |
138 |
|
139 |
this.disposablesTable = new JTable(new DisposablesTableModel()); |
140 |
this.disposablesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); |
141 |
|
142 |
// DefaultTableColumnModel columnModel = new DefaultTableColumnModel();
|
143 |
// columnModel.addColumn(new TableColumn(0, ToolsSwingUtils.cols2px(5)));
|
144 |
// columnModel.addColumn(new TableColumn(1, ToolsSwingUtils.cols2px(12)));
|
145 |
// columnModel.addColumn(new TableColumn(2, ToolsSwingUtils.cols2px(12)));
|
146 |
// columnModel.addColumn(new TableColumn(3, ToolsSwingUtils.cols2px(25)));
|
147 |
// this.disposablesTable.setColumnModel(columnModel);
|
148 |
|
149 |
this.infoTextArea = new JTextPane(); |
150 |
this.infoTextArea.setContentType("text/html"); |
151 |
|
152 |
JScrollPane listScroller = new JScrollPane(this.disposablesTable); |
153 |
JScrollPane infoScroller = new JScrollPane(this.infoTextArea); |
154 |
this.splitPanel.setLeftComponent(listScroller);
|
155 |
this.splitPanel.setRightComponent(infoScroller);
|
156 |
|
157 |
// Dimension dim = this.splitPanel.getPreferredSize();
|
158 |
// dim.height = dim.height / 2;
|
159 |
// this.disposablesTable.setPreferredSize(dim);
|
160 |
// this.splitPanel.invalidate();
|
161 |
|
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 void refreshList() { |
191 |
fillTable(); |
192 |
} |
193 |
|
194 |
private void ListItemSelected() { |
195 |
DisposablesTableModel model = (DisposablesTableModel) this.disposablesTable.getModel();
|
196 |
DisposableInfo info = model.get(this.disposablesTable.getSelectedRow());
|
197 |
if( info==null ) { |
198 |
this.infoTextArea.setText(""); |
199 |
} else {
|
200 |
this.infoTextArea.setText(toHTML(info));
|
201 |
this.infoTextArea.setCaretPosition(0); |
202 |
} |
203 |
} |
204 |
|
205 |
private void fillTable() { |
206 |
Set<DisposableInfo> disposables = (Set<DisposableInfo>) manager.getBoundDisposables(); |
207 |
this.messageLabel.setText("Disposables " + disposables.size()); |
208 |
|
209 |
this.disposablesTable.setModel(new DisposablesTableModel(new ArrayList<>(disposables))); this.messageLabel.setText("Pending " + disposables.size()); |
210 |
this.infoTextArea.setText(""); |
211 |
} |
212 |
|
213 |
private void updateMemoryUsage() { |
214 |
Runtime rt = Runtime.getRuntime(); |
215 |
this.lblTotalMemory.setText(String.valueOf(rt.totalMemory()/1024)); |
216 |
this.lblMaxMemory.setText(String.valueOf(rt.maxMemory()/1024)); |
217 |
this.lblFreeMemory.setText(String.valueOf(rt.freeMemory()/1024)); |
218 |
this.lblActiveThreads.setText(String.valueOf(Thread.activeCount())); |
219 |
|
220 |
int objectPendingFinalizationCount = -1; |
221 |
try {
|
222 |
MemoryMXBean memBean = ManagementFactory.getMemoryMXBean() ; |
223 |
objectPendingFinalizationCount = memBean.getObjectPendingFinalizationCount(); |
224 |
} catch(ThreadDeath th) { |
225 |
|
226 |
} |
227 |
this.lblObjectPendingFinalization.setText(String.valueOf(objectPendingFinalizationCount)); |
228 |
} |
229 |
|
230 |
private class DisposablesTableModel extends AbstractTableModel { |
231 |
|
232 |
private List<DisposableInfo> disposables; |
233 |
private final String[] columnNames; |
234 |
private final Class[] columnClass; |
235 |
|
236 |
public DisposablesTableModel() {
|
237 |
this(Collections.EMPTY_LIST); |
238 |
} |
239 |
|
240 |
public DisposablesTableModel(List<DisposableInfo> disposables) { |
241 |
this.disposables = disposables;
|
242 |
this.columnNames = new String[] {"Refs.", "Class", "Full class", "To str."}; |
243 |
this.columnClass = new Class[] {Integer.class, String.class, String.class, String.class}; |
244 |
} |
245 |
|
246 |
public DisposableInfo get(int rowIndex) { |
247 |
try {
|
248 |
return this.disposables.get(rowIndex); |
249 |
} catch(Throwable th) { |
250 |
return null; |
251 |
} |
252 |
} |
253 |
|
254 |
@Override
|
255 |
public int getRowCount() { |
256 |
return this.disposables.size(); |
257 |
} |
258 |
|
259 |
@Override
|
260 |
public int getColumnCount() { |
261 |
return this.columnNames.length; |
262 |
} |
263 |
|
264 |
@Override
|
265 |
public String getColumnName(int columnIndex) { |
266 |
return this.columnNames[columnIndex]; |
267 |
} |
268 |
|
269 |
@Override
|
270 |
public Class<?> getColumnClass(int columnIndex) { |
271 |
return this.columnClass[columnIndex]; |
272 |
} |
273 |
|
274 |
@Override
|
275 |
public Object getValueAt(int rowIndex, int columnIndex) { |
276 |
DisposableInfo info = this.disposables.get(rowIndex);
|
277 |
switch(columnIndex) {
|
278 |
case 0: |
279 |
return info.getReferencesCount();
|
280 |
case 1: |
281 |
try {
|
282 |
return info.getDisposable().getClass().getSimpleName();
|
283 |
} catch(Throwable th) { |
284 |
return "(unknown)"; |
285 |
} |
286 |
case 2: |
287 |
try {
|
288 |
return info.getDisposable().getClass().getName();
|
289 |
} catch(Throwable th) { |
290 |
return "(unknown)"; |
291 |
} |
292 |
case 3: |
293 |
try {
|
294 |
return info.getDisposable().toString();
|
295 |
} catch(Throwable th) { |
296 |
return "(unknown)"; |
297 |
} |
298 |
} |
299 |
return null; |
300 |
} |
301 |
} |
302 |
|
303 |
public String toHTML(DisposableInfo disposableInfo) { |
304 |
StringBuilder buffer = new StringBuilder(); |
305 |
Disposable disposable = disposableInfo.getDisposable(); |
306 |
|
307 |
buffer.append("<b>Class</b>: ").append(disposable.getClass().getSimpleName()).append("<br>\n"); |
308 |
buffer.append("<b>Full class</b>: ").append(disposable.getClass().getName()).append("<br>\n"); |
309 |
buffer.append("<b>References</b>: ").append(disposableInfo.getReferencesCount()).append("<br>\n"); |
310 |
buffer.append("<b>toString</b>: ").append(disposable.toString()).append("<br>\n"); |
311 |
|
312 |
buffer.append("<b>Binded from (stack)</b>:<br>\n");
|
313 |
try {
|
314 |
StackTraceElement[] stackTrace = disposableInfo |
315 |
.getBindDisposableStackTrace(); |
316 |
for (StackTraceElement stackTrace1 : stackTrace) { |
317 |
buffer.append(" ").append(stackTrace1.toString().replaceAll("[<]", "<").replace("[>]", ">")).append("<br>\n"); |
318 |
} |
319 |
} catch (Exception ex) { |
320 |
buffer.append("<br>\n<br>\nError showing stack.<br>\n").append(ex.getMessage());
|
321 |
} |
322 |
return buffer.toString();
|
323 |
} |
324 |
|
325 |
public void closeWindow() { |
326 |
this.setVisible(false); |
327 |
} |
328 |
|
329 |
public void disposeAll() { |
330 |
try {
|
331 |
manager.releaseAll(); |
332 |
} catch (BaseException ex) {
|
333 |
LOG.error("Error disposing all bound disposable objects", ex);
|
334 |
} |
335 |
} |
336 |
|
337 |
public void disposeSelecteds() { |
338 |
DisposablesTableModel model = (DisposablesTableModel) this.disposablesTable.getModel();
|
339 |
for (int row : this.disposablesTable.getSelectedRows()) { |
340 |
DisposableInfo info = model.get(row); |
341 |
this.manager.release(info.getDisposable());
|
342 |
} |
343 |
refreshList(); |
344 |
} |
345 |
|
346 |
public void showPanel() { |
347 |
WindowManager wm = ToolsSwingLocator.getWindowManager(); |
348 |
wm.showWindow(this, "Disposable do list", WindowManager.MODE.WINDOW); |
349 |
} |
350 |
|
351 |
// private class ActionListenerImpl implements ActionListener {
|
352 |
//
|
353 |
// public ActionListenerImpl() {
|
354 |
// }
|
355 |
//
|
356 |
// @Override
|
357 |
// public void actionPerformed(ActionEvent e) {
|
358 |
// disposeSelecteds();
|
359 |
// refreshList();
|
360 |
// updateMemoryUsage();
|
361 |
// }
|
362 |
// }
|
363 |
} |
364 |
|
365 |
} |