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 @ 46737
History | View | Annotate | Download (14.7 KB)
1 | 40558 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40558 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | *
|
||
6 | 41258 | jjdelcerro | * 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 | 40558 | jjdelcerro | *
|
11 | 41258 | jjdelcerro | * 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 | 40558 | jjdelcerro | *
|
16 | 41258 | jjdelcerro | * 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 | 40558 | jjdelcerro | *
|
20 | 41258 | jjdelcerro | * For any additional information, do not hesitate to contact us at info AT
|
21 | * gvsig.com, or visit our website www.gvsig.com.
|
||
22 | 40435 | jjdelcerro | */
|
23 | /*
|
||
24 | * AUTHORS (In addition to CIT):
|
||
25 | * 2009 {} {{Task}}
|
||
26 | */
|
||
27 | package org.gvsig.app.extension.dispose; |
||
28 | |||
29 | 41258 | jjdelcerro | import java.awt.Dimension; |
30 | 41043 | jjdelcerro | import java.awt.event.ActionEvent; |
31 | 45707 | jjdelcerro | 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 | 40435 | jjdelcerro | import java.util.Set; |
37 | 41043 | jjdelcerro | import javax.swing.JScrollPane; |
38 | 45707 | jjdelcerro | import javax.swing.JTable; |
39 | 41043 | jjdelcerro | import javax.swing.JTextPane; |
40 | 45707 | jjdelcerro | import javax.swing.ListSelectionModel; |
41 | 41043 | jjdelcerro | import javax.swing.SwingUtilities; |
42 | import javax.swing.event.ListSelectionEvent; |
||
43 | 45707 | jjdelcerro | import javax.swing.table.AbstractTableModel; |
44 | import javax.swing.table.DefaultTableColumnModel; |
||
45 | import javax.swing.table.TableColumn; |
||
46 | 40435 | jjdelcerro | 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 | 41043 | jjdelcerro | import org.gvsig.tools.swing.api.ToolsSwingLocator; |
53 | 45729 | jjdelcerro | import org.gvsig.tools.swing.api.ToolsSwingManager; |
54 | 45707 | jjdelcerro | import org.gvsig.tools.swing.api.ToolsSwingUtils; |
55 | 41043 | jjdelcerro | import org.gvsig.tools.swing.api.windowmanager.WindowManager; |
56 | 45716 | fdiaz | import org.gvsig.tools.util.LabeledValue; |
57 | 40435 | jjdelcerro | import org.slf4j.Logger; |
58 | import org.slf4j.LoggerFactory; |
||
59 | |||
60 | /**
|
||
61 | * An extension to view and manage {@link Disposable} objects which are still
|
||
62 | * bound.
|
||
63 | 41258 | jjdelcerro | *
|
64 | 40435 | jjdelcerro | * TODO: remove this extension and replace with a better one, maybe based on
|
65 | * scripting.
|
||
66 | 41258 | jjdelcerro | *
|
67 | 40435 | jjdelcerro | * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
|
68 | */
|
||
69 | public class DisposableManagementExtension extends Extension { |
||
70 | |||
71 | 41258 | jjdelcerro | public static String SHOW_COMMAND = "tools-devel-disposables-show-pendings"; |
72 | public static String DISPOSE_ALL_COMMAND = "tools-devel-disposables-free-all"; |
||
73 | 40435 | jjdelcerro | |
74 | 41258 | jjdelcerro | private static final Logger LOG |
75 | = LoggerFactory.getLogger(DisposableManagementExtension.class); |
||
76 | 40435 | jjdelcerro | |
77 | 45707 | jjdelcerro | @Override
|
78 | 41258 | jjdelcerro | public void initialize() { |
79 | // Nothing to do
|
||
80 | } |
||
81 | 40435 | jjdelcerro | |
82 | 41258 | jjdelcerro | @Override
|
83 | public void postInitialize() { |
||
84 | super.postInitialize();
|
||
85 | } |
||
86 | 40435 | jjdelcerro | |
87 | 45707 | jjdelcerro | @Override
|
88 | 41258 | jjdelcerro | public void execute(String actionCommand) { |
89 | 40435 | jjdelcerro | |
90 | 41258 | jjdelcerro | if (DISPOSE_ALL_COMMAND.equals(actionCommand)) {
|
91 | disposeAll(); |
||
92 | } else {
|
||
93 | if (SHOW_COMMAND.equals(actionCommand)) {
|
||
94 | DisposablesDoList panel = new DisposablesDoList();
|
||
95 | panel.showPanel(); |
||
96 | } |
||
97 | } |
||
98 | } |
||
99 | 40435 | jjdelcerro | |
100 | 41258 | jjdelcerro | private void disposeAll() { |
101 | DisposableManager manager; |
||
102 | manager = ToolsLocator.getDisposableManager(); |
||
103 | try {
|
||
104 | manager.releaseAll(); |
||
105 | } catch (BaseException ex) {
|
||
106 | LOG.error("Error disposing all bound disposable objects", ex);
|
||
107 | } |
||
108 | } |
||
109 | 40435 | jjdelcerro | |
110 | 45707 | jjdelcerro | @Override
|
111 | 41258 | jjdelcerro | public boolean isEnabled() { |
112 | return true; |
||
113 | } |
||
114 | 40435 | jjdelcerro | |
115 | 45707 | jjdelcerro | @Override
|
116 | 41258 | jjdelcerro | public boolean isVisible() { |
117 | return true; |
||
118 | } |
||
119 | 41043 | jjdelcerro | |
120 | 41258 | jjdelcerro | class DisposablesDoList extends DisposablesDoListLayout { |
121 | 41043 | jjdelcerro | |
122 | 41258 | jjdelcerro | private DisposableManager manager;
|
123 | 45707 | jjdelcerro | private JTable disposablesTable = null; |
124 | 41258 | jjdelcerro | private JTextPane infoTextArea = null; |
125 | |||
126 | public DisposablesDoList() {
|
||
127 | manager = ToolsLocator.getDisposableManager(); |
||
128 | initComponents(); |
||
129 | 45707 | jjdelcerro | SwingUtilities.invokeLater(() -> {
|
130 | refreshList(); |
||
131 | updateMemoryUsage(); |
||
132 | 41258 | jjdelcerro | }); |
133 | } |
||
134 | |||
135 | private void initComponents() { |
||
136 | 45729 | jjdelcerro | ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager(); |
137 | |||
138 | 41258 | jjdelcerro | this.setPreferredSize(new Dimension(600, 550)); |
139 | 45707 | jjdelcerro | |
140 | this.disposablesTable = new JTable(new DisposablesTableModel()); |
||
141 | 45714 | fdiaz | this.disposablesTable.setAutoCreateColumnsFromModel(false); |
142 | 45707 | jjdelcerro | |
143 | 45714 | fdiaz | DefaultTableColumnModel columnModel = new DefaultTableColumnModel(); |
144 | columnModel.addColumn(createTableColumn(0, ToolsSwingUtils.cols2px(5), "refs")); |
||
145 | columnModel.addColumn(createTableColumn(1, ToolsSwingUtils.cols2px(12), "class")); |
||
146 | columnModel.addColumn(createTableColumn(2, ToolsSwingUtils.cols2px(10), "code")); |
||
147 | columnModel.addColumn(createTableColumn(3, ToolsSwingUtils.cols2px(12), "fullClass")); |
||
148 | columnModel.addColumn(createTableColumn(4, ToolsSwingUtils.cols2px(25), "toString")); |
||
149 | this.disposablesTable.setColumnModel(columnModel);
|
||
150 | 45707 | jjdelcerro | |
151 | 45714 | fdiaz | this.disposablesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); |
152 | 46503 | fdiaz | // ToolsSwingUtils.ensureRows(this.disposablesTable, 10);
|
153 | 45729 | jjdelcerro | |
154 | 41258 | jjdelcerro | this.infoTextArea = new JTextPane(); |
155 | this.infoTextArea.setContentType("text/html"); |
||
156 | 45729 | jjdelcerro | toolsSwingManager.setDefaultPopupMenu( |
157 | this.infoTextArea,
|
||
158 | "Disposable information"
|
||
159 | ); |
||
160 | 45716 | fdiaz | |
161 | 45707 | jjdelcerro | JScrollPane listScroller = new JScrollPane(this.disposablesTable); |
162 | 41258 | jjdelcerro | JScrollPane infoScroller = new JScrollPane(this.infoTextArea); |
163 | this.splitPanel.setLeftComponent(listScroller);
|
||
164 | this.splitPanel.setRightComponent(infoScroller);
|
||
165 | 45729 | jjdelcerro | this.splitPanel.setDividerLocation(0.3); |
166 | 41258 | jjdelcerro | |
167 | 45707 | jjdelcerro | this.closeButton.addActionListener((ActionEvent arg0) -> { |
168 | closeWindow(); |
||
169 | 41258 | jjdelcerro | }); |
170 | this.closeButton.setEnabled(true); |
||
171 | 45707 | jjdelcerro | this.disposeAllButton.addActionListener((ActionEvent e) -> { |
172 | disposeAll(); |
||
173 | refreshList(); |
||
174 | updateMemoryUsage(); |
||
175 | 41258 | jjdelcerro | }); |
176 | this.disposeAllButton.setEnabled(true); |
||
177 | 45707 | jjdelcerro | this.disposeButton.addActionListener((ActionEvent e) -> { |
178 | disposeSelecteds(); |
||
179 | refreshList(); |
||
180 | updateMemoryUsage(); |
||
181 | 41258 | jjdelcerro | }); |
182 | this.disposeButton.setEnabled(true); |
||
183 | 45707 | jjdelcerro | this.disposablesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent arg0) -> { |
184 | ListItemSelected(); |
||
185 | updateMemoryUsage(); |
||
186 | 41258 | jjdelcerro | }); |
187 | 45707 | jjdelcerro | this.disposablesTable.setEnabled(true); |
188 | this.refreshButton.addActionListener((ActionEvent arg0) -> { |
||
189 | refreshList(); |
||
190 | updateMemoryUsage(); |
||
191 | 41258 | jjdelcerro | }); |
192 | this.refreshButton.setEnabled(true); |
||
193 | } |
||
194 | 45716 | fdiaz | |
195 | 45714 | fdiaz | private TableColumn createTableColumn(int col, int size, String name) { |
196 | TableColumn tableColumn = new TableColumn(col, size); |
||
197 | tableColumn.setHeaderValue(name); |
||
198 | return tableColumn;
|
||
199 | } |
||
200 | 41258 | jjdelcerro | |
201 | private void refreshList() { |
||
202 | 45707 | jjdelcerro | fillTable(); |
203 | 41258 | jjdelcerro | } |
204 | |||
205 | private void ListItemSelected() { |
||
206 | 45707 | jjdelcerro | DisposablesTableModel model = (DisposablesTableModel) this.disposablesTable.getModel();
|
207 | DisposableInfo info = model.get(this.disposablesTable.getSelectedRow());
|
||
208 | 45716 | fdiaz | if (info == null) { |
209 | 41258 | jjdelcerro | this.infoTextArea.setText(""); |
210 | } else {
|
||
211 | 45707 | jjdelcerro | this.infoTextArea.setText(toHTML(info));
|
212 | 41258 | jjdelcerro | this.infoTextArea.setCaretPosition(0); |
213 | } |
||
214 | } |
||
215 | |||
216 | 45707 | jjdelcerro | private void fillTable() { |
217 | Set<DisposableInfo> disposables = (Set<DisposableInfo>) manager.getBoundDisposables(); |
||
218 | this.messageLabel.setText("Disposables " + disposables.size()); |
||
219 | 41258 | jjdelcerro | |
220 | 45714 | fdiaz | this.disposablesTable.setModel(new DisposablesTableModel(new ArrayList<>(disposables))); |
221 | this.messageLabel.setText("Pending " + disposables.size()); |
||
222 | 41258 | jjdelcerro | this.infoTextArea.setText(""); |
223 | } |
||
224 | 45716 | fdiaz | |
225 | 45707 | jjdelcerro | private void updateMemoryUsage() { |
226 | Runtime rt = Runtime.getRuntime(); |
||
227 | 45716 | fdiaz | this.lblTotalMemory.setText(String.valueOf(rt.totalMemory() / 1024)); |
228 | this.lblMaxMemory.setText(String.valueOf(rt.maxMemory() / 1024)); |
||
229 | this.lblFreeMemory.setText(String.valueOf(rt.freeMemory() / 1024)); |
||
230 | 45707 | jjdelcerro | this.lblActiveThreads.setText(String.valueOf(Thread.activeCount())); |
231 | 45716 | fdiaz | |
232 | 45707 | jjdelcerro | int objectPendingFinalizationCount = -1; |
233 | try {
|
||
234 | 45716 | fdiaz | MemoryMXBean memBean = ManagementFactory.getMemoryMXBean(); |
235 | 45707 | jjdelcerro | objectPendingFinalizationCount = memBean.getObjectPendingFinalizationCount(); |
236 | 45716 | fdiaz | } catch (ThreadDeath th) { |
237 | |||
238 | 45707 | jjdelcerro | } |
239 | this.lblObjectPendingFinalization.setText(String.valueOf(objectPendingFinalizationCount)); |
||
240 | } |
||
241 | 41258 | jjdelcerro | |
242 | 45707 | jjdelcerro | private class DisposablesTableModel extends AbstractTableModel { |
243 | 41258 | jjdelcerro | |
244 | 45716 | fdiaz | private List<DisposableInfo> disposables; |
245 | 45707 | jjdelcerro | private final String[] columnNames; |
246 | private final Class[] columnClass; |
||
247 | 45716 | fdiaz | |
248 | 45707 | jjdelcerro | public DisposablesTableModel() {
|
249 | this(Collections.EMPTY_LIST); |
||
250 | } |
||
251 | 45716 | fdiaz | |
252 | 45707 | jjdelcerro | public DisposablesTableModel(List<DisposableInfo> disposables) { |
253 | this.disposables = disposables;
|
||
254 | 45716 | fdiaz | this.columnNames = new String[]{"Refs.", "Class", "Code", "Full class", "To str."}; |
255 | 45729 | jjdelcerro | this.columnClass = new Class[]{Integer.class, String.class, String.class, String.class, String.class}; |
256 | 45707 | jjdelcerro | } |
257 | 45716 | fdiaz | |
258 | 45707 | jjdelcerro | public DisposableInfo get(int rowIndex) { |
259 | try {
|
||
260 | return this.disposables.get(rowIndex); |
||
261 | 45716 | fdiaz | } catch (Throwable th) { |
262 | 45707 | jjdelcerro | return null; |
263 | } |
||
264 | } |
||
265 | 45716 | fdiaz | |
266 | 45707 | jjdelcerro | @Override
|
267 | public int getRowCount() { |
||
268 | return this.disposables.size(); |
||
269 | } |
||
270 | 41258 | jjdelcerro | |
271 | 45707 | jjdelcerro | @Override
|
272 | public int getColumnCount() { |
||
273 | return this.columnNames.length; |
||
274 | 41258 | jjdelcerro | } |
275 | |||
276 | 45707 | jjdelcerro | @Override
|
277 | public String getColumnName(int columnIndex) { |
||
278 | return this.columnNames[columnIndex]; |
||
279 | 41258 | jjdelcerro | } |
280 | |||
281 | 45707 | jjdelcerro | @Override
|
282 | public Class<?> getColumnClass(int columnIndex) { |
||
283 | return this.columnClass[columnIndex]; |
||
284 | 41258 | jjdelcerro | } |
285 | |||
286 | 45707 | jjdelcerro | @Override
|
287 | public Object getValueAt(int rowIndex, int columnIndex) { |
||
288 | DisposableInfo info = this.disposables.get(rowIndex);
|
||
289 | 45716 | fdiaz | switch (columnIndex) {
|
290 | 45707 | jjdelcerro | case 0: |
291 | return info.getReferencesCount();
|
||
292 | case 1: |
||
293 | try {
|
||
294 | 45729 | jjdelcerro | return info.getDisposable().getClass().getSimpleName();
|
295 | } catch (Throwable th) { |
||
296 | return "(unknown)"; |
||
297 | } |
||
298 | 45707 | jjdelcerro | case 2: |
299 | try {
|
||
300 | 45729 | jjdelcerro | return String.format("%x",info.getDisposable().hashCode()); |
301 | } catch (Throwable th) { |
||
302 | return -1; |
||
303 | } |
||
304 | 45714 | fdiaz | case 3: |
305 | try {
|
||
306 | 45729 | jjdelcerro | return info.getDisposable().getClass().getName();
|
307 | } catch (Throwable th) { |
||
308 | return "(unknown)"; |
||
309 | } |
||
310 | 45714 | fdiaz | case 4: |
311 | 45707 | jjdelcerro | try {
|
312 | 45729 | jjdelcerro | return info.getDisposable().toString();
|
313 | } catch (Throwable th) { |
||
314 | return "(unknown)"; |
||
315 | } |
||
316 | 41258 | jjdelcerro | } |
317 | 45707 | jjdelcerro | return null; |
318 | 41258 | jjdelcerro | } |
319 | 45707 | jjdelcerro | } |
320 | 41258 | jjdelcerro | |
321 | 45716 | fdiaz | public String toHTML(DisposableInfo disposableInfo) { |
322 | 45707 | jjdelcerro | StringBuilder buffer = new StringBuilder(); |
323 | Disposable disposable = disposableInfo.getDisposable(); |
||
324 | 45729 | jjdelcerro | int code = disposable.hashCode();
|
325 | 41258 | jjdelcerro | |
326 | 45707 | jjdelcerro | buffer.append("<b>Class</b>: ").append(disposable.getClass().getSimpleName()).append("<br>\n"); |
327 | buffer.append("<b>Full class</b>: ").append(disposable.getClass().getName()).append("<br>\n"); |
||
328 | buffer.append("<b>References</b>: ").append(disposableInfo.getReferencesCount()).append("<br>\n"); |
||
329 | 45729 | jjdelcerro | buffer.append(String.format("<b>Code</b>: %x (%d)<br>\n", code,code)); |
330 | 45707 | jjdelcerro | buffer.append("<b>toString</b>: ").append(disposable.toString()).append("<br>\n"); |
331 | 41258 | jjdelcerro | |
332 | 45707 | jjdelcerro | try {
|
333 | 45716 | fdiaz | List<LabeledValue<StackTraceElement[]>> allStackTraces = disposableInfo.getAllStackTrace(); |
334 | for (int i = 0; i < allStackTraces.size(); i++) { |
||
335 | LabeledValue<StackTraceElement[]> trace = allStackTraces.get(i); |
||
336 | buffer.append("<b>#");
|
||
337 | buffer.append(i + 1);
|
||
338 | buffer.append(" ");
|
||
339 | buffer.append(trace.getLabel()); |
||
340 | buffer.append(" from (stack)</b>:<br>\n");
|
||
341 | for (StackTraceElement stackTrace1 : trace.getValue()) { |
||
342 | 45714 | fdiaz | buffer.append(" ").append(stackTrace1.toString().replaceAll("[<]", "<").replace("[>]", ">")).append("<br>\n"); |
343 | } |
||
344 | } |
||
345 | 45716 | fdiaz | |
346 | 45707 | jjdelcerro | } catch (Exception ex) { |
347 | buffer.append("<br>\n<br>\nError showing stack.<br>\n").append(ex.getMessage());
|
||
348 | 41258 | jjdelcerro | } |
349 | 45707 | jjdelcerro | return buffer.toString();
|
350 | 41258 | jjdelcerro | } |
351 | |||
352 | public void closeWindow() { |
||
353 | this.setVisible(false); |
||
354 | } |
||
355 | |||
356 | public void disposeAll() { |
||
357 | try {
|
||
358 | manager.releaseAll(); |
||
359 | } catch (BaseException ex) {
|
||
360 | LOG.error("Error disposing all bound disposable objects", ex);
|
||
361 | } |
||
362 | } |
||
363 | |||
364 | public void disposeSelecteds() { |
||
365 | 45707 | jjdelcerro | DisposablesTableModel model = (DisposablesTableModel) this.disposablesTable.getModel();
|
366 | for (int row : this.disposablesTable.getSelectedRows()) { |
||
367 | DisposableInfo info = model.get(row); |
||
368 | this.manager.release(info.getDisposable());
|
||
369 | 41258 | jjdelcerro | } |
370 | refreshList(); |
||
371 | } |
||
372 | |||
373 | public void showPanel() { |
||
374 | WindowManager wm = ToolsSwingLocator.getWindowManager(); |
||
375 | wm.showWindow(this, "Disposable do list", WindowManager.MODE.WINDOW); |
||
376 | } |
||
377 | 45707 | jjdelcerro | |
378 | // private class ActionListenerImpl implements ActionListener {
|
||
379 | //
|
||
380 | // public ActionListenerImpl() {
|
||
381 | // }
|
||
382 | //
|
||
383 | // @Override
|
||
384 | // public void actionPerformed(ActionEvent e) {
|
||
385 | // disposeSelecteds();
|
||
386 | // refreshList();
|
||
387 | // updateMemoryUsage();
|
||
388 | // }
|
||
389 | // }
|
||
390 | 41258 | jjdelcerro | } |
391 | |||
392 | } |