Coverage report

  %line %branch
nl.toolforge.karma.core.cmd.CommandFactory
0% 
0% 

 1  
 /*
 2  
 Karma core - Core of the Karma application
 3  
 Copyright (C) 2004  Toolforge <www.toolforge.nl>
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, write to the Free Software
 17  
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 */
 19  
 package nl.toolforge.karma.core.cmd;
 20  
 
 21  
 import net.sf.sillyexceptions.OutOfTheBlueException;
 22  
 import nl.toolforge.karma.core.KarmaRuntimeException;
 23  
 import org.apache.commons.cli.CommandLineParser;
 24  
 import org.apache.commons.cli.MissingArgumentException;
 25  
 import org.apache.commons.cli.MissingOptionException;
 26  
 import org.apache.commons.cli.Options;
 27  
 import org.apache.commons.cli.ParseException;
 28  
 import org.apache.commons.cli.PosixParser;
 29  
 import org.apache.commons.cli.UnrecognizedOptionException;
 30  
 
 31  
 import java.lang.reflect.Constructor;
 32  
 import java.lang.reflect.InvocationTargetException;
 33  
 import java.util.ArrayList;
 34  
 import java.util.Collection;
 35  
 import java.util.HashSet;
 36  
 import java.util.Iterator;
 37  
 import java.util.List;
 38  
 import java.util.Map;
 39  
 import java.util.Set;
 40  
 import java.util.TreeMap;
 41  
 
 42  
 //import net.sf.sillyexceptions.OutOfTheBlueException;
 43  
 
 44  
 /**
 45  
  * This factory is the single resource of Command objects. <code>KarmaRuntimeException</code>s are thrown when
 46  
  * something fails.
 47  
  *
 48  
  * @author W.H. Schraal
 49  
  * @version $Id: CommandFactory.java,v 1.34 2004/11/10 23:53:07 asmedes Exp $
 50  
  */
 51  
 public final class CommandFactory {
 52  
 
 53  
   // Singleton
 54  
   //
 55  0
   private static CommandFactory factory = null;
 56  
 
 57  
   // Reference ro all command names
 58  
   //
 59  0
   private static Set commandNames = null;
 60  
 
 61  0
   private static Map commandsByName = null;
 62  0
   private static Map commandsByAlias = null;
 63  
 
 64  
   /**
 65  
    * Only static methods
 66  
    */
 67  0
   private CommandFactory() throws CommandLoadException {
 68  0
     init();
 69  0
   }
 70  
 
 71  
   private synchronized void init() throws CommandLoadException {
 72  
 
 73  0
     CommandDescriptorMap descriptors = CommandLoader.getInstance().load();
 74  
 
 75  0
     commandsByName = new TreeMap();
 76  0
     commandsByAlias = new TreeMap();
 77  0
     commandNames = new HashSet();
 78  
 
 79  
     // Store all commands by name in a hash
 80  
     // Create a set of all command names.
 81  
     //
 82  0
     for (Iterator i = descriptors.values().iterator(); i.hasNext();) {
 83  0
       CommandDescriptor descriptor = (CommandDescriptor) i.next();
 84  
 
 85  0
       commandsByName.put(descriptor.getName(), descriptor);
 86  0
       commandNames.add(descriptor.getName());
 87  
 
 88  0
       for (Iterator j = descriptor.getAliasList().iterator(); j.hasNext();) {
 89  0
         String alias = (String) j.next();
 90  0
         commandsByAlias.put(alias, descriptor);
 91  0
         commandNames.add(alias);
 92  
       }
 93  
     }
 94  0
   }
 95  
 
 96  
   /**
 97  
    * Gets the singleton <code>CommandFactory</code>.
 98  
    *
 99  
    * @return The singleton <code>CommandFactory</code> instance.
 100  
    */
 101  
   public static CommandFactory getInstance() throws CommandLoadException {
 102  0
     if (factory == null) {
 103  0
       factory = new CommandFactory();
 104  
     }
 105  0
     return factory;
 106  
   }
 107  
 
 108  
   /**
 109  
    * Retrieves the correct <code>Command</code>-instance, by looking up the implementation class through
 110  
    * <code>commandLine</code>.
 111  
    *
 112  
    * @param commandLineString Command arguments (e.g. <code>select-manifest -m karma-1.0</code>).
 113  
    * @return The implementation of a <code>Command</code> object.
 114  
    * @throws CommandException When a correct command could not be constructed. See
 115  
    *                          {@link CommandException#INVALID_COMMAND}.
 116  
    */
 117  
   public Command getCommand(String commandLineString) throws CommandException {
 118  
 
 119  0
     String commandName = null;
 120  0
     commandLineString = commandLineString.trim();
 121  
 
 122  0
     if (commandLineString.indexOf(' ') > 0) {
 123  0
       commandName = commandLineString.substring(0, commandLineString.indexOf(' '));
 124  
     } else {
 125  0
       commandName = commandLineString;
 126  
     }
 127  
 
 128  0
     char[] class="keyword">chars = commandLineString.substring(commandName.length()).toCharArray();
 129  
 
 130  0
     List commandOptionsList = new ArrayList();
 131  
 
 132  0
     int j = 0;
 133  0
     String part = null;
 134  
 
 135  0
     while (j < chars.length) {
 136  
 
 137  
       // Go to the next part while we are a 'space' (chr(32))
 138  
       //
 139  0
       while (chars[j] == ' ') {
 140  0
         j++;
 141  
       }
 142  
 
 143  0
       part = "";
 144  0
       if (chars[j] != '"') {
 145  
         // Start of options or 'normal' arguments.
 146  
         //
 147  0
         part += chars[j];
 148  0
         j++;
 149  
 
 150  0
         while ((j < chars.length) && (chars[j] != ' ') && (chars[j] != '\"')) {
 151  
           // Continue until a space or \" is reached.
 152  
           //
 153  0
           part += chars[j];
 154  0
           j++;
 155  
         }
 156  
 
 157  0
       } else if (chars[j] == '"') {
 158  
         // Begin van een argument dat bestaat uit een block data, gedemarkeerd door dubbele quotes, escaped dubbel
 159  
         // quote wordt eruit gevist.
 160  
         //
 161  0
         part += chars[j];
 162  0
         j++;
 163  
 
 164  0
         while (j < chars.length) {
 165  
 
 166  0
           if (chars[j] == '"') {
 167  0
             if (chars[j-1] != '\\') {
 168  
               // End of demarkated piece of text.
 169  
               //
 170  0
               j++;
 171  0
               break;
 172  
             }
 173  
           }
 174  
 
 175  
           // doorlopen totdat een '"' is bereikt, behalve \" (escaped).
 176  0
           part += chars[j];
 177  0
           j++;
 178  
         }
 179  
         // We have reached a '"', which must be added.
 180  
         //
 181  0
         part += '"';
 182  0
         j++;
 183  
       }
 184  
 
 185  0
       if (part.startsWith("\"") && part.endsWith("\"")) {
 186  0
         part = part.substring(1, part.length() - 1).trim();
 187  
       }
 188  
 
 189  0
       commandOptionsList.add(part);
 190  
     }
 191  
 
 192  0
     String[] commandOptions = (String[]) commandOptionsList.toArray(new String[commandOptionsList.size()]);
 193  
 
 194  0
     return getCommand(commandName, commandOptions);
 195  
   }
 196  
 
 197  
   public Command getCommand(String commandName, String[] arguments) throws CommandException {
 198  
 
 199  0
     Command cmd = null;
 200  
 
 201  0
     if (isCommand(commandName)) {
 202  
 
 203  0
       CommandDescriptor descriptor = null;
 204  
       try {
 205  0
         descriptor = getCommandDescriptor(commandName);
 206  
 
 207  
         // Construct the command implementation, with the default constructor
 208  
         //
 209  0
         Class implementingClass = null;
 210  
         try {
 211  0
           implementingClass = Class.forName(descriptor.getClassName());
 212  0
         } catch (ClassNotFoundException c) {
 213  0
           throw new CommandException(CommandException.NO_IMPLEMENTING_CLASS, class="keyword">new Object[]{descriptor.getClassName()});
 214  0
         }
 215  
 
 216  0
         Constructor defaultConstructor = implementingClass.getConstructor(new Class[]{CommandDescriptor.class});
 217  0
         cmd = (Command) defaultConstructor.newInstance(new Object[]{descriptor});
 218  
 
 219  
         // Parse the command line options.
 220  
         //
 221  0
         CommandLineParser parser = new PosixParser();
 222  
 
 223  0
         Options parserOptions = descriptor.getOptions();
 224  
 
 225  
 //        if (parserOptions.getOptions().size() == 0 && arguments.length > 0) {
 226  
 //          // The issue is that this is 1. not an exception and 2. no mechanism to propagate this back in a nice way.
 227  
 //          throw new CommandException(CommandException.NO_OPTIONS_REQUIRED);
 228  
 //        }
 229  
 
 230  0
         cmd.setCommandLine(parser.parse(parserOptions, arguments));
 231  
 
 232  0
       } catch (NoSuchMethodException e) {
 233  0
         throw new KarmaRuntimeException(e.getLocalizedMessage(), e);
 234  0
       } catch (SecurityException e) {
 235  0
         throw new KarmaRuntimeException(e.getLocalizedMessage(), e);
 236  0
       } catch (InstantiationException e) {
 237  0
         throw new KarmaRuntimeException(e.getLocalizedMessage(), e);
 238  0
       } catch (IllegalAccessException e) {
 239  0
         throw new KarmaRuntimeException(e.getLocalizedMessage(), e);
 240  0
       } catch (IllegalArgumentException e) {
 241  0
         throw new KarmaRuntimeException(e.getLocalizedMessage(), e);
 242  0
       } catch (InvocationTargetException e) {
 243  0
         throw new KarmaRuntimeException(e.getLocalizedMessage(), e);
 244  0
       } catch (ParseException e) {
 245  0
         if (e instanceof MissingOptionException) {
 246  0
           throw new CommandException(e, CommandException.MISSING_OPTION, class="keyword">new Object[]{e.getMessage()});
 247  
         }
 248  0
         if (e instanceof UnrecognizedOptionException) {
 249  0
           throw new CommandException(e, CommandException.INVALID_OPTION, class="keyword">new Object[]{arguments});
 250  
         }
 251  0
         if (e instanceof MissingArgumentException) {
 252  0
           throw new CommandException(e, CommandException.MISSING_ARGUMENT, class="keyword">new Object[]{e.getMessage()});
 253  
         }
 254  0
       }
 255  0
       return cmd;
 256  
     }
 257  
     // At this point, we have no command
 258  
     //
 259  0
     throw new CommandException(CommandException.UNKNOWN_COMMAND, class="keyword">new Object[]{commandName});
 260  
   }
 261  
 
 262  
   /**
 263  
    * Checks if some string is a command within this context.
 264  
    *
 265  
    * @param name
 266  
    * @return
 267  
    */
 268  
   private boolean isCommand(String name) {
 269  0
     return commandNames.contains(name);
 270  
   }
 271  
 
 272  
   public Collection getCommands() {
 273  0
     return commandsByName.values();
 274  
   }
 275  
 
 276  
   /**
 277  
    * Retrieves the correct command descriptor either by name or by alias (whichever is passed as a
 278  
    * parameter). Returns <code>null</code> if the descriptor could not be found.
 279  
    */
 280  
   public CommandDescriptor getCommandDescriptor(String commandId) {
 281  
 
 282  
     try {
 283  0
       init(); //this fixes the bug where the previous value of an option is returned
 284  0
     } catch (CommandLoadException cle) {
 285  
       //this can not happen, since the init has already been called in the constructor
 286  
       //and it was successful then.
 287  0
       throw new OutOfTheBlueException("Tried to reload the commands, but failed. This is strange because they have been loaded earlier with success");
 288  0
     }
 289  
 
 290  0
     if (commandsByName.containsKey(commandId)) {
 291  0
       return (CommandDescriptor) commandsByName.get(commandId);
 292  
     } else {
 293  0
       if (commandsByAlias.containsKey(commandId)) {
 294  0
         return (CommandDescriptor) commandsByAlias.get(commandId);
 295  
       }
 296  
     }
 297  0
     return null;
 298  
   }
 299  
 
 300  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.