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 }