Coverage Report - org.crosswire.jsword.book.install.InstallManager
 
Classes in this File Line Coverage Branch Coverage Complexity
InstallManager
0%
0/115
0%
0/38
2.714
 
 1  
 /**
 2  
  * Distribution License:
 3  
  * JSword is free software; you can redistribute it and/or modify it under
 4  
  * the terms of the GNU Lesser General Public License, version 2.1 or later
 5  
  * as published by the Free Software Foundation. This program is distributed
 6  
  * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 7  
  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 8  
  * See the GNU Lesser General Public License for more details.
 9  
  *
 10  
  * The License is available on the internet at:
 11  
  *      http://www.gnu.org/copyleft/lgpl.html
 12  
  * or by writing to:
 13  
  *      Free Software Foundation, Inc.
 14  
  *      59 Temple Place - Suite 330
 15  
  *      Boston, MA 02111-1307, USA
 16  
  *
 17  
  * © CrossWire Bible Society, 2005 - 2016
 18  
  *
 19  
  */
 20  
 package org.crosswire.jsword.book.install;
 21  
 
 22  
 import java.io.IOException;
 23  
 import java.net.URI;
 24  
 import java.util.Collections;
 25  
 import java.util.Iterator;
 26  
 import java.util.LinkedHashMap;
 27  
 import java.util.List;
 28  
 import java.util.Map;
 29  
 import java.util.Set;
 30  
 import java.util.concurrent.CopyOnWriteArrayList;
 31  
 
 32  
 import org.crosswire.common.util.CWProject;
 33  
 import org.crosswire.common.util.FileUtil;
 34  
 import org.crosswire.common.util.NetUtil;
 35  
 import org.crosswire.common.util.PluginUtil;
 36  
 import org.crosswire.common.util.PropertyMap;
 37  
 import org.crosswire.common.util.Reporter;
 38  
 import org.slf4j.Logger;
 39  
 import org.slf4j.LoggerFactory;
 40  
 
 41  
 /**
 42  
  * A manager to abstract out the non-view specific book installation tasks.
 43  
  * 
 44  
  * @see gnu.lgpl.License The GNU Lesser General Public License for details.
 45  
  * @author Joe Walker
 46  
  * @author DM Smith
 47  
  */
 48  0
 public final class InstallManager {
 49  
     /**
 50  
      * Simple ctor
 51  
      */
 52  0
     public InstallManager() {
 53  0
         listeners = new CopyOnWriteArrayList<InstallerListener>();
 54  0
         installers = new LinkedHashMap<String, Installer>();
 55  
 
 56  
         try {
 57  0
             PropertyMap sitemap = PluginUtil.getPlugin(getClass());
 58  0
             factories = PluginUtil.getImplementorsMap(InstallerFactory.class);
 59  0
             int i = 0;
 60  0
             for (String def = sitemap.get(PREFIX + ++i); def != null; def = sitemap.get(PREFIX + ++i)) {
 61  
                 try {
 62  0
                     String[] parts = def.split(",", 3);
 63  0
                     String type = parts[0];
 64  0
                     String name = parts[1];
 65  0
                     String rest = parts[2];
 66  
 
 67  0
                     Class<InstallerFactory> clazz = factories.get(type);
 68  0
                     if (clazz == null) {
 69  0
                         log.warn("Unable to get class for {}", type);
 70  
                     } else {
 71  0
                         InstallerFactory ifactory = clazz.newInstance();
 72  0
                         Installer installer = ifactory.createInstaller(rest);
 73  
 
 74  0
                         internalAdd(name, installer);
 75  
                     }
 76  0
                 } catch (InstantiationException e) {
 77  0
                     Reporter.informUser(this, e);
 78  0
                 } catch (IllegalAccessException e) {
 79  0
                     Reporter.informUser(this, e);
 80  0
                 }
 81  
             }
 82  0
         } catch (IOException ex) {
 83  0
             Reporter.informUser(this, ex);
 84  0
         }
 85  0
     }
 86  
 
 87  
     /**
 88  
      * Save all properties to the user's local area. Uses the same property name
 89  
      * so as to override it.
 90  
      */
 91  
     public void save() {
 92  0
         PropertyMap props = new PropertyMap();
 93  0
         StringBuilder buf = new StringBuilder();
 94  0
         int i = 1;
 95  0
         for (String name : installers.keySet()) {
 96  0
             Installer installer = installers.get(name);
 97  
             // Clear the buffer
 98  0
             buf.delete(0, buf.length());
 99  0
             buf.append(installer.getType());
 100  0
             buf.append(',');
 101  0
             buf.append(name);
 102  0
             buf.append(',');
 103  0
             buf.append(installer.getInstallerDefinition());
 104  0
             props.put(PREFIX + i++, buf.toString());
 105  0
         }
 106  0
         URI outputURI = CWProject.instance().getWritableURI(getClass().getName(), FileUtil.EXTENSION_PLUGIN);
 107  
         try {
 108  0
             NetUtil.storeProperties(props, outputURI, "Saved Installer Sites");
 109  0
         } catch (IOException e) {
 110  0
             log.error("Failed to save installers", e);
 111  0
         }
 112  0
     }
 113  
 
 114  
     /**
 115  
      * The names of all the known InstallerFactories
 116  
      * 
 117  
      * @return the set of all installer factory names
 118  
      */
 119  
     public Set<String> getInstallerFactoryNames() {
 120  0
         return Collections.unmodifiableSet(factories.keySet());
 121  
     }
 122  
 
 123  
     /**
 124  
      * Find the registered name of the InstallerFactory that created the given
 125  
      * installer. There isn't a nice way to do this right now so we just do a
 126  
      * trawl through all the known factories looking!
 127  
      * 
 128  
      * @param installer the installer
 129  
      * @return the name of the factory for the installer
 130  
      */
 131  
     public String getFactoryNameForInstaller(Installer installer) {
 132  0
         Class<? extends Installer> match = installer.getClass();
 133  0
         for (String name : factories.keySet()) {
 134  0
             Class<InstallerFactory> factclazz = factories.get(name);
 135  
             try {
 136  0
                 InstallerFactory ifactory = factclazz.newInstance();
 137  0
                 Class<? extends Installer> clazz = ifactory.createInstaller().getClass();
 138  0
                 if (clazz == match) {
 139  0
                     return name;
 140  
                 }
 141  0
             } catch (InstantiationException e) {
 142  0
                 log.warn("Failed to instantiate installer factory: {}={}", name, factclazz.getName(), e);
 143  0
             } catch (IllegalAccessException e) {
 144  0
                 log.warn("Failed to instantiate installer factory: {}={}", name, factclazz.getName(), e);
 145  0
             }
 146  0
         }
 147  
 
 148  0
         log.warn("Failed to find factory name for {} among the {} factories.", installer, Integer.toString(factories.size()));
 149  0
         return null;
 150  
     }
 151  
 
 152  
     /**
 153  
      * Find the registered name of the Installer. There isn't a nice way to do
 154  
      * this right now so we just do a trawl through all the known factories
 155  
      * looking!
 156  
      * 
 157  
      * @param installer the installer
 158  
      * @return the name of the installer
 159  
      */
 160  
     public String getInstallerNameForInstaller(Installer installer) {
 161  0
         for (String name : installers.keySet()) {
 162  0
             Installer test = installers.get(name);
 163  0
             if (installer.equals(test)) {
 164  0
                 return name;
 165  
             }
 166  0
         }
 167  
 
 168  0
         log.warn("Failed to find installer name for {} among the {} installers.", installer, Integer.toString(installers.size()));
 169  0
         for (String name : installers.keySet()) {
 170  0
             Installer test = installers.get(name);
 171  0
             log.warn("  it isn't equal to {}", test.getInstallerDefinition());
 172  0
         }
 173  0
         return null;
 174  
     }
 175  
 
 176  
     /**
 177  
      * Find the InstallerFactory associated with the given name.
 178  
      * 
 179  
      * @param name
 180  
      *            The InstallerFactory name to look-up
 181  
      * @return The found InstallerFactory or null if the name was not found
 182  
      */
 183  
     public InstallerFactory getInstallerFactory(String name) {
 184  0
         Class<InstallerFactory> clazz = factories.get(name);
 185  
         try {
 186  0
             return clazz.newInstance();
 187  0
         } catch (InstantiationException e) {
 188  0
             assert false : e;
 189  0
         } catch (IllegalAccessException e) {
 190  0
             assert false : e;
 191  0
         }
 192  0
         return null;
 193  
     }
 194  
 
 195  
     /**
 196  
      * Accessor for the known installers
 197  
      * @return a map of named installers
 198  
      */
 199  
     public Map<String, Installer> getInstallers() {
 200  0
         return Collections.unmodifiableMap(installers);
 201  
     }
 202  
 
 203  
     /**
 204  
      * Find an installer by name
 205  
      * 
 206  
      * @param name
 207  
      *            The name of the installer to find
 208  
      * @return The installer or null if none was found by the given name
 209  
      */
 210  
     public Installer getInstaller(String name) {
 211  0
         return installers.get(name);
 212  
     }
 213  
 
 214  
     /**
 215  
      * Add an installer to our list of installers
 216  
      * 
 217  
      * @param name
 218  
      *            The name by which we reference the installer
 219  
      * @param installer
 220  
      *            The installer to add
 221  
      */
 222  
     public void addInstaller(String name, Installer installer) {
 223  0
         assert installer != null;
 224  0
         assert name != null;
 225  
 
 226  0
         removeInstaller(name);
 227  
 
 228  0
         internalAdd(name, installer);
 229  0
         fireInstallersChanged(this, installer, true);
 230  0
     }
 231  
 
 232  
     /**
 233  
      * InstallManager is a Map, however we demand that both names and installers
 234  
      * are unique (so we can lookup a name from an installer)
 235  
      * 
 236  
      * @param name
 237  
      *            The name of the new installer
 238  
      * @param installer
 239  
      *            The installer to associate with the given name
 240  
      */
 241  
     private void internalAdd(String name, Installer installer) {
 242  0
         Iterator<String> it = installers.keySet().iterator();
 243  0
         while (it.hasNext()) {
 244  0
             String tname = it.next();
 245  0
             Installer tinstaller = installers.get(tname);
 246  
 
 247  0
             if (tinstaller.equals(installer)) {
 248  
                 // We have a dupe - remove the old name
 249  0
                 log.warn("duplicate installers: {}={}. removing {}", name, tname, tname);
 250  
 
 251  
                 // Can't call removeInstaller while iterating.
 252  0
                 it.remove();
 253  0
                 fireInstallersChanged(this, tinstaller, false);
 254  
             }
 255  0
         }
 256  
 
 257  0
         installers.put(name, installer);
 258  0
     }
 259  
 
 260  
     /**
 261  
      * Remove an installer from our list
 262  
      * 
 263  
      * @param name
 264  
      *            The name by which this installer is referenced
 265  
      */
 266  
     public void removeInstaller(String name) {
 267  0
         if (installers.containsKey(name)) {
 268  0
             Installer old = installers.remove(name);
 269  0
             fireInstallersChanged(this, old, false);
 270  
         }
 271  0
     }
 272  
 
 273  
     /**
 274  
      * Remove a BibleListener from our list of listeners
 275  
      * 
 276  
      * @param li
 277  
      *            The old listener
 278  
      */
 279  
     public void addInstallerListener(InstallerListener li) {
 280  0
         listeners.add(li);
 281  0
     }
 282  
 
 283  
     /**
 284  
      * Add a BibleListener to our list of listeners
 285  
      * 
 286  
      * @param li
 287  
      *            The new listener
 288  
      */
 289  
     public void removeBooksListener(InstallerListener li) {
 290  0
         listeners.remove(li);
 291  0
     }
 292  
 
 293  
     /**
 294  
      * Kick of an event sequence
 295  
      * 
 296  
      * @param source
 297  
      *            The event source
 298  
      * @param installer
 299  
      *            The meta-data of the changed Bible
 300  
      * @param added
 301  
      *            Is it added?
 302  
      */
 303  
     protected void fireInstallersChanged(Object source, Installer installer, boolean added) {
 304  0
         InstallerEvent ev = new InstallerEvent(source, installer, added);
 305  0
         for (InstallerListener listener : listeners) {
 306  0
             if (added) {
 307  0
                 listener.installerAdded(ev);
 308  
             } else {
 309  0
                 listener.installerRemoved(ev);
 310  
             }
 311  
         }
 312  0
     }
 313  
 
 314  
     /**
 315  
      * The prefix for the keys in the installer property file.
 316  
      */
 317  
     private static final String PREFIX = "Installer.";
 318  
 
 319  
     /**
 320  
      * The map of installer factories
 321  
      */
 322  
     private Map<String, Class<InstallerFactory>> factories;
 323  
 
 324  
     /**
 325  
      * The list of discovered installers
 326  
      */
 327  
     private Map<String, Installer> installers;
 328  
 
 329  
     /**
 330  
      * The list of listeners
 331  
      */
 332  
     private List<InstallerListener> listeners;
 333  
 
 334  
     /**
 335  
      * The log stream
 336  
      */
 337  0
     private static final Logger log = LoggerFactory.getLogger(InstallManager.class);
 338  
 }