001 //Copyright (C) 2006 A. Nelson
002 //
003 //This program is free software; you can redistribute it and/or
004 //modify it under the terms of the GNU General Public License
005 //as published by the Free Software Foundation; either version 2
006 //of the License, or (at your option) any later version.
007 //
008 //This program is distributed in the hope that it will be useful,
009 //but WITHOUT ANY WARRANTY; without even the implied warranty of
010 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011 //GNU General Public License for more details.
012 //
013 //You should have received a copy of the GNU General Public License
014 //along with this program; if not, write to the Free Software
015 //Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
016
017 package pluginCore;
018
019 import javax.swing.*;
020 import javax.swing.border.*;
021 import java.awt.GridLayout;
022 import java.awt.event.*;
023 import java.io.File;
024
025 /**
026 * @author Avro Nelson
027 * This plugin is used to administrate plugins running in the core.
028 * It allows the user to load/unload plugins, hot swap plugins
029 * list open plugins, etc...
030 */
031 public class AdminPlugin extends Plugin {
032
033 /**
034 * This should be the path to the plugin you keep the plugins in.
035 * It is used to tell the program where to look to get a list of available
036 * plugins.
037 */
038 private static final String myHomePath = "./";
039
040 /**
041 * This is also a bit of a hack for this, you need to spesify the full package
042 * name of the plugin you want to load.
043 */
044 private static final String pluginPrefix = "ipMedia.Client.plugins.";
045
046 /**
047 * This should be the path to the plugin you keep the plugins in.
048 * It is used to tell the program where to look to get a list of available
049 * plugins.
050 */
051 private static final String pluginDirectoryPath = myHomePath
052 + "workspace/ipMediaProject/ipMedia/Client/plugins/";
053
054
055 private JFrame adminFrame;
056 private FileListModel fileListModel;
057 private JList fileList;
058 private JList loadedPlugList;
059 private DefaultListModel listModel;
060
061 AdminPlugin() {
062
063 pluginName = "AdminPlugin";
064 adminFrame = new JFrame("Plugin Admin");
065 DEBUG = true;
066 }
067
068 /**
069 * This method will get the list of plugins that are loaded
070 * and fill out the list in the interface.
071 */
072 private void fillLoadedPlugList(){
073
074 String plugList[];
075
076 listModel.clear();
077
078 plugList = frameworkCore.listLoadedPlugins();
079
080 if( plugList.length < 1 ) {
081
082 System.out.println("PluginCore.listLoadedPlugins() did not return proper list");
083 return;
084 }
085
086 for( int i = 0, listSize = plugList.length; i < listSize; i++ ){
087
088 listModel.add(i, plugList[i] );
089 }
090 }
091
092 /**
093 * This build the swap menue on the interface.
094 * @return The JPanel that will be loaded into the interface.
095 */
096 private JPanel buildSwapMenue(){
097
098 JPanel swapMenue;
099
100 swapMenue = new JPanel();
101 listModel = new DefaultListModel();
102
103 swapMenue.setBorder( new BevelBorder( BevelBorder.RAISED ) );
104
105
106 loadedPlugList = new JList(listModel);
107 loadedPlugList.setLayoutOrientation( JList.VERTICAL );
108 loadedPlugList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
109
110 fillLoadedPlugList();
111
112 swapMenue.setLayout( new GridLayout(3, 2) );
113
114 swapMenue.add( new JLabel("Currently Loaded Plugins"));
115 swapMenue.add( new JLabel("Available Plugins"));
116
117 swapMenue.add( new JScrollPane( loadedPlugList ) );
118 swapMenue.add( new JScrollPane( this.buildFileList() ) );
119
120 swapMenue.add( getReloadListButton() );
121 swapMenue.add( getSwapButton() );
122
123 swapMenue.validate();
124
125 return swapMenue;
126 }
127
128 public void run() {
129
130 adminFrame.getContentPane().add( this.buildSwapMenue() );
131 adminFrame.pack();
132 adminFrame.setSize(500, 300);
133 adminFrame.setVisible(true);
134
135
136 }
137
138 public void shutdown() {
139
140 adminFrame.dispose();
141 }
142
143 public int receive(Message msgIn) {
144
145 return -1;
146 }
147
148 /**
149 * This is called to swap the plugins that are selected.
150 */
151 private void swapSelected() {
152
153
154 String oldPlugName, newPlugName;
155 Object[] oldState;
156 int oldPlugId;
157
158 if( fileList == null ) {
159
160 printError("File List not Loaded");
161 return;
162 }
163
164 newPlugName = (String) fileList.getSelectedValue();
165 oldPlugName = (String) loadedPlugList.getSelectedValue();
166
167 if( oldPlugName == null || newPlugName == null ) {
168
169 printError("One of the plugins did not report back properly");
170 return;
171 }
172 printDebug( "Swapping " + oldPlugName + " with " + newPlugName );
173
174 oldPlugId = frameworkCore.pluginIDRequest( "ipMedia.Client.plugins." + oldPlugName );
175 if( oldPlugId == -1) {
176
177 printError("Plugin to be swapped out did not exist");
178 return;
179 }
180
181 oldState = frameworkCore.savePlugin(oldPlugId);
182 if( oldState == null ){
183
184 printError("Could not save old plugin state.");
185 return;
186 }
187
188 if( frameworkCore.loadPlugin( pluginPrefix + newPlugName, oldState) == -1 ){
189
190 printError("Could not swap the plugins");
191 return;
192 }
193 }
194
195 private void loadSelected() {
196
197 }
198
199 /**
200 * JButton creation methods.
201 */
202
203 /**
204 * Builds a button labled "Refresh Loaded Plugin List" and calls fillLoadedPlugList()
205 * @return Returns the button that was built.
206 */
207 private JButton getReloadListButton(){
208
209 JButton button = new JButton("Refresh Loaded Plugin List");
210 button.addActionListener( new ActionListener() {
211
212 public void actionPerformed(ActionEvent e){
213
214 fillLoadedPlugList();
215 }
216 });
217
218 return button;
219 }
220
221 /**
222 * Creates the swap button.
223 * @return Returns the button that was built.
224 */
225 private JButton getSwapButton(){
226
227 JButton button = new JButton("Swap Selected Plugin");
228 button.addActionListener( new ActionListener() {
229
230 public void actionPerformed(ActionEvent e){
231
232 swapSelected();
233 }
234 });
235 return button;
236 }
237
238 /**
239 * Creates the load plugin button.
240 * @return Returns the button created.
241 */
242 private JButton getLoadButton(){
243
244 JButton button = new JButton("Load Selected Plugin");
245 button.addActionListener( new ActionListener() {
246
247 public void actionPerformed(ActionEvent e){
248
249 loadSelected();
250 }
251 });
252 return button;
253
254 }
255
256 /**
257 * Creates the file list.
258 * @return Returns the file list created.
259 */
260 private JList buildFileList() {
261
262 File theDir;
263
264 theDir = new File(pluginDirectoryPath );
265
266 if( theDir == null) {
267
268 printError("Could not load the pluginDirectoryPath " + pluginDirectoryPath);
269 return null;
270 }
271
272 fileListModel = new FileListModel( theDir );
273 fileList = new JList( fileListModel );
274
275 return fileList;
276 }
277
278
279
280 public Object[] savePluginState() {
281
282 printError("AdminPlugin Cannot Have its State Saved.");
283 return null;
284 }
285
286 public boolean setPluginState(Object[] stateVec) {
287
288 printError("AdminPlugin Cannot Be Loaded From Saved State.");
289 return false;
290 }
291
292 /**
293 * The FileListModel builds a list of .class files from the directory
294 * declared by AdminPlugin.pluginDirectoryPath excluding internal classes
295 * by ignoring every file with a $ in the name.
296 * @author Avro Nelson.
297 * @since April, 2006.
298 *
299 */
300 private class FileListModel extends AbstractListModel {
301
302 public static final long serialVersionUID = 0xff6897a3;
303
304 /**
305 * The list of available plugin files.
306 */
307 File[] listOfDir;
308
309 public FileListModel( File dir )
310 {
311
312 File theDir;
313 File[] tmpList;
314 int tmpSize;
315
316 theDir = dir;
317 listOfDir = null;
318 tmpSize = 0;
319
320 if( theDir == null ) {
321
322 printError( "Could not load FileListModel off of the File provided.");
323 return;
324 }
325
326 tmpList = theDir.listFiles( );
327
328 if( tmpList == null ) {
329
330 printDebug("The file list was null");
331 return;
332 }
333
334 //Yes, I now that this could be written better. If you dont like it too bad.
335
336 //Lets sort through our file names and count how many .class we have.
337 for(int i = 0; i < tmpList.length; i++ ) {
338
339 if( tmpList[i] != null ){
340
341 if( tmpList[i].getName().endsWith(".class") == true ) {
342
343 if( tmpList[i].getName().contains("$") != true ) {
344
345 tmpSize++;
346 }
347 }
348 }
349 }
350
351 //Now lets create a proper arrya to store all these in and copy the files.
352 listOfDir = new File[tmpSize];
353 for(int i = 0, place = 0; i < tmpList.length; i++ ) {
354
355 if( tmpList[i] != null ){
356
357 if( tmpList[i].getName().endsWith(".class") == true ) {
358
359 //Now lets cull out the internal classes.
360 if( tmpList[i].getName().contains("$") != true ) {
361
362 listOfDir[place] = tmpList[i];
363 place++;
364 }
365 }
366 }
367 }
368 }
369 /**
370 * This will return a string with the name of the file chosen.
371 */
372 public Object getElementAt( int i ){
373
374 if( isValidIndex( i ) == false ) return null;
375 return listOfDir[i].getName().replace(".class", "");
376 }
377
378 /**
379 * gets the lenght of listOfDir
380 * @return listOfDir.length
381 */
382 public int getSize(){
383
384 if( listOfDir == null ) return 0;
385 return listOfDir.length;
386 }
387
388 /**
389 * This returns the File object that is selected.
390 * @return The selected File object.
391 */
392 public File getSelectedFile() {
393
394 int selected;
395 selected = fileList.getSelectedIndex();
396
397 if( isValidIndex( selected ) == false ) return null;
398 return listOfDir[selected];
399 }
400
401 private boolean isValidIndex( int i) {
402
403 if( i >= listOfDir.length ) return false;
404 if( i < 0 ) return false;
405 return true;
406 }
407
408 }
409 }