Log in Help
Print
Homereleasesgate-8.4-build5748-ALLpluginsDeveloper_Toolssrcgatecreole 〉 UnusedPluginUnloader.java
 
/*
 * UnusedPluginUnloader.java
 * 
 * Copyright (c) 1995-2014, The University of Sheffield. See the file
 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
 * 
 * This file is part of GATE (see http://gate.ac.uk/), and is free software,
 * licenced under the GNU Library General Public License, Version 2, June 1991
 * (in the distribution as file licence.html, and also available at
 * http://gate.ac.uk/gate/licence.html).
 * 
 * Johann Petrak 2014-05-22
 */
package gate.creole;

import gate.Gate;
import gate.Gate.DirectoryInfo;
import gate.Gate.ResourceInfo;
import gate.Resource;
import gate.creole.metadata.AutoInstance;
import gate.creole.metadata.CreoleResource;
import gate.gui.ActionsPublisher;
import gate.resources.img.svg.PluginUnloaderIcon;
import gate.util.GateException;

import java.awt.event.ActionEvent;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.Action;

/**
 * A tool option that will try its best to unload just the plugins for which we
 * do not have any known instances.
 * 
 * @author Johann Petrak
 * @author Mark A. Greenwood
 */
@SuppressWarnings("serial")
@CreoleResource(tool = true, isPrivate = true, autoinstances = @AutoInstance, name = "Unload Unused Plugins", helpURL = "http://gate.ac.uk/userguide/sec:misc-creole:dev-tools", comment = "Unloads all plugins for which we cannot find any loaded instances")
public class UnusedPluginUnloader extends AbstractResource implements
  ActionsPublisher {

  // the cached set of actions so we don't have to keep creating them
  private List<Action> actions;

  @Override
  public List<Action> getActions() {

    // if we have already built the action list then just return it
    if(actions != null) return actions;

    // create the empty actions list
    actions = new ArrayList<Action>();

    // we need access to the hidden instances as well and we can only do this
    // through the impl so of something weird is going on and we have a
    // different CreoleRegister than we expect then don't add the menu item
    if(!(Gate.getCreoleRegister() instanceof CreoleRegisterImpl))
      return actions;

    actions.add(new AbstractAction("Unload Unused Plugins",
      new PluginUnloaderIcon(24, 24)) {

      @Override
      public void actionPerformed(ActionEvent e) {

        // get a handle to the Creole register implementation
        CreoleRegisterImpl reg = (CreoleRegisterImpl)Gate.getCreoleRegister();

        // this will hold the set of plugins that are to be unloaded
        Set<URL> pluginsToUnload = new HashSet<URL>();

        for(URL plugin : reg.getDirectories()) {
          // for each registered plugin...

          // assume the plugin is unused
          boolean unused = true;

          // get the plugin nifo
          DirectoryInfo dInfo = Gate.getDirectoryInfo(plugin);

          for(ResourceInfo rInfo : dInfo.getResourceInfoList()) {
            // for each Resource the plugin defines...

            try {
              // get the instances of the resource
              List<Resource> loaded =
                reg.getAllInstances(rInfo.getResourceClassName(), true);

              if(!loaded.isEmpty()) {
                // if there are any instances then the plugin is in use
                unused = false;
                break;
              }
            } catch(GateException e1) {
              // ignore this, in the worst case we won't unload this plugin ...
            }
          }

          // if we went through all the Resources and there aren't instances of
          // any of them then the plugin is not in use and can be unloaded
          if(unused) pluginsToUnload.add(plugin);
        }

        //TODO replace this with a GUI to give users some control        
        if(pluginsToUnload.isEmpty()) {
          System.out.println("No plugin unloaded");
        } else {
          for(URL plugin : pluginsToUnload) {
            // The system logs plugins getting unloaded, so we do not have to do
            // it
            System.out.println("Trying to unload plugin: " + plugin);
            reg.removeDirectory(plugin);           
          }
          System.out.println("Plugins unloaded: " + pluginsToUnload.size());
          System.out.println("\nPlugins still loaded:");
          for(URL plugin : reg.getDirectories()) {
            System.out.println("  " + plugin);
          }
        }        
      }
    });

    // return the list of actions
    return actions;
  }
}