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    }