View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.plugin.freeway;
21  
22  import java.awt.BorderLayout;
23  import java.awt.FlowLayout;
24  import java.awt.GridBagLayout;
25  import java.awt.event.ActionEvent;
26  import java.util.ArrayList;
27  
28  import javax.swing.AbstractAction;
29  import javax.swing.Action;
30  import javax.swing.JLabel;
31  import javax.swing.JPanel;
32  import javax.swing.JScrollPane;
33  import javax.swing.JTable;
34  import javax.swing.SwingUtilities;
35  import javax.swing.border.EmptyBorder;
36  
37  import org.gnu.freeway.DaemonSocket;
38  import org.gnu.freeway.protocol.afs.swing.SController;
39  import org.gnu.freeway.util.CSMessage;
40  import org.gnu.freeway.util.CSReturnValue;
41  import org.gnu.freeway.util.CSStatistics;
42  import org.gnu.freeway.util.CSStatisticsRequest;
43  import org.gnu.freeway.util.ConfigurationService;
44  import org.gnu.freeway.util.CronService;
45  import org.gnu.freeway.util.Statistic;
46  import org.xnap.XNap;
47  import org.xnap.gui.ActionProvider;
48  import org.xnap.gui.component.XNapButton;
49  import org.xnap.gui.table.AbstractColumnTableModel;
50  import org.xnap.gui.table.Column;
51  import org.xnap.gui.util.GUIHelper;
52  import org.xnap.gui.util.GridBagHelper;
53  import org.xnap.gui.util.IconHelper;
54  import org.xnap.util.Formatter;
55  import org.xnap.util.Preferences;
56  
57  public class FreewayPanel extends JPanel implements ActionProvider {
58  
59      //--- Constant(s) ---
60      
61      //--- Data field(s) ---
62  
63      private JLabel jlStatus;
64  	private SController controller;
65  	private FreewayStatsTableModel statsTableModel;
66  
67      //--- Constructor(s) ---
68      
69      public FreewayPanel(SController controller)
70      {
71      	this.controller = controller;
72      	
73  		initialize();
74     	}
75      
76      //--- Method(s) ---
77  
78      public void initialize() 
79      {	
80  		setBorder(new EmptyBorder(5, 5, 5, 5));
81  		setLayout(new GridBagLayout());
82  
83  		JPanel jpStatus = new JPanel(new BorderLayout());
84  		GridBagHelper.add(this, jpStatus);
85  		jpStatus.setBorder(GUIHelper.createDefaultBorder(XNap.tr("Status")));
86  
87  		jlStatus = new JLabel(XNap.tr("Unknown"));
88  		jpStatus.add(jlStatus, BorderLayout.CENTER);
89  
90  		JPanel statsPanel = new JPanel(new BorderLayout());
91  		statsPanel.setBorder
92  			(GUIHelper.createDefaultBorder(XNap.tr("Statistics")));
93  		GridBagHelper.addPanel(this, statsPanel);
94  
95  		statsTableModel = new FreewayStatsTableModel();
96  		JTable statsTable = statsTableModel.createTable(Preferences.getInstance(), "freewayStats");
97  		statsPanel.add(new JScrollPane(statsTable), BorderLayout.CENTER);
98  
99  		GridBagHelper.addVerticalSpacer(this);
100 		
101 		JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
102 		GridBagHelper.add(this, jpButtons);
103 		jpButtons.add(new XNapButton(new UpdateAction()));
104     }
105 
106 	public Action[] getActions()
107     {
108 		return new Action[] { new UpdateAction() };
109     }
110 
111 	public void updateStatus()
112 	{
113 		jlStatus.setText(XNap.tr("Updating statistics") + "...");
114 		statsTableModel.clear();
115 
116 		Thread t = new Thread(new StatsRunner(), "FreewayStatsRunner");
117 		t.start();
118 	}
119 	
120 	/***
121 	 * @param text the status message
122 	 */
123 	private void setStatusLater(final String text)
124 	{
125 		Runnable runner = new Runnable()
126 		{
127 			public void run() 
128 			{
129 				jlStatus.setText(text);
130 			}
131 		 };
132 		 SwingUtilities.invokeLater(runner);
133 	}
134 
135 	private class UpdateAction extends AbstractAction
136 	{
137 	    public UpdateAction()
138 		{
139 			putValue(Action.NAME, XNap.tr("Update"));
140 			putValue(Action.SHORT_DESCRIPTION, XNap.tr("Updates the status."));
141 			putValue(IconHelper.XNAP_ICON, "undo.png");
142 		}
143 
144 		public void actionPerformed(ActionEvent event)
145 		{
146 			updateStatus();
147 		}
148 	}
149 
150 	public class FreewayStatsTableModel extends AbstractColumnTableModel
151 	{
152 
153 	    //--- Data field(s) ---
154 
155 	    private ArrayList data = new ArrayList();
156 
157 	    //--- Constructor(s) ---
158 
159 	    public FreewayStatsTableModel() 
160 	    {
161 			Column columns[] = new Column[] {
162 				new Column("key", XNap.tr("Key"), String.class),
163 				new Column("value", XNap.tr("Value"), String.class),
164 			};
165 			addColumns(columns);
166 	    }
167 
168 	    /***
169 		 * 
170 		 */
171 		public void clear()
172 		{
173 			data.clear();
174 			fireTableDataChanged();
175 		}
176 
177 		//--- Method(s) ---
178 
179 		public void add(final String key, final String value)
180 		{
181 			Runnable runner = new Runnable()
182 				{
183 					public void run()
184 					{
185 						data.add(new Item(key, value));
186 						fireTableRowsInserted(data.size() - 1, data.size() - 1);
187 					}
188 				};
189 			SwingUtilities.invokeLater(runner);
190 		}
191 
192 	    public int getRowCount() 
193 	    {
194 	        return data.size();
195 	    }
196 
197 	    public Object get(int i, int j) 
198 	    {
199 			Item item = (Item)data.get(i);
200 			
201 	        switch (j) {
202 			case 0:
203 				return item.key;
204 			case 1:
205 				return item.value;
206 			default:
207 				return null;
208 	        }
209 	    }
210 
211 	    //--- Inner Class(es) ---
212 
213 	    private class Item
214 	    {
215 		
216 	    	String key;
217 	    	String value;
218 	    	
219 	    	public Item(String key, String value)
220 	    	{
221 	    		this.key = key;
222 	    		this.value = value;
223 	    	}
224 
225 	    }
226 
227 	}
228 
229 	
230 	private class StatsRunner implements Runnable {
231 		
232 		public void run()
233 		{
234 			DaemonSocket socket = DaemonSocket.create
235 			((ConfigurationService)controller.service(ConfigurationService.class),
236 			 controller.getPreferences());
237 
238 			if (socket == null) {
239 				setStatusLater(XNap.tr("Could not establish connection to daemon."));
240 				return;
241 			}
242 
243 			socket.getDecoder().add(CSMessage.IS_STATISTICS,CSStatistics.class);
244 			socket.getDecoder().add(CSMessage.IS_RETURN,CSReturnValue.class);
245 
246 			if (!socket.write(new CSStatisticsRequest())) {
247 				setStatusLater("Error sending request for statistics to gnunetd.");
248 				return;
249 			}
250 
251 			int count = 0;
252 			int totalCounters = 1;
253 			while (count < totalCounters) {
254 				CSStatistics msg = (CSStatistics)socket.read(CSStatistics.class);
255 				if (msg == null) {
256 					setStatusLater("Error receiving reply for statistics from gnunetd.");
257 					return;
258 				}
259 
260 				if (count == 0) {
261 					long t = CronService.toSeconds(CronService.time()) - msg.getStartTime();
262 					setStatusLater(XNap.tr("Daemon Uptime: {0}", Formatter.formatLength(t))); 
263 					totalCounters = msg.getTotalCounters();
264 				}
265 
266 				if (msg.getTotalCounters() != totalCounters) {
267 					setStatusLater("Corrupted data ?");
268 					return;
269 				}
270 
271 				Statistic[] stats = msg.getStatistics();
272 				for (int i = 0; i < stats.length; i++) {
273 					statsTableModel.add(stats[i].getName(), "" + stats[i].get());
274 				}
275 				count += stats.length;
276 			}
277 			socket.destroy();
278 		}
279 
280 	}
281 	
282 }