Coverage report

  %line %branch
nl.toolforge.karma.core.manifest.BaseModule
71% 
94% 

 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.manifest;
 20  
 
 21  
 import net.sf.sillyexceptions.OutOfTheBlueException;
 22  
 import nl.toolforge.core.util.file.MyFileUtils;
 23  
 import nl.toolforge.karma.core.KarmaRuntimeException;
 24  
 import nl.toolforge.karma.core.Version;
 25  
 import nl.toolforge.karma.core.history.ModuleHistory;
 26  
 import nl.toolforge.karma.core.history.ModuleHistoryEvent;
 27  
 import nl.toolforge.karma.core.history.ModuleHistoryException;
 28  
 import nl.toolforge.karma.core.history.ModuleHistoryFactory;
 29  
 import nl.toolforge.karma.core.location.Location;
 30  
 import nl.toolforge.karma.core.manifest.util.ModuleLayoutTemplate;
 31  
 import nl.toolforge.karma.core.module.ModuleDescriptor;
 32  
 import nl.toolforge.karma.core.scm.digester.ModuleDependencyCreationFactory;
 33  
 import nl.toolforge.karma.core.vc.AuthenticationException;
 34  
 import nl.toolforge.karma.core.vc.Authenticator;
 35  
 import nl.toolforge.karma.core.vc.Authenticators;
 36  
 import nl.toolforge.karma.core.vc.DevelopmentLine;
 37  
 import nl.toolforge.karma.core.vc.PatchLine;
 38  
 import nl.toolforge.karma.core.vc.RunnerFactory;
 39  
 import nl.toolforge.karma.core.vc.VersionControlException;
 40  
 import nl.toolforge.karma.core.vc.cvsimpl.CVSRunner;
 41  
 import org.apache.commons.digester.Digester;
 42  
 import org.apache.commons.io.FileUtils;
 43  
 import org.apache.commons.logging.Log;
 44  
 import org.apache.commons.logging.LogFactory;
 45  
 import org.xml.sax.SAXException;
 46  
 
 47  
 import java.io.File;
 48  
 import java.io.IOException;
 49  
 import java.util.Date;
 50  
 import java.util.HashSet;
 51  
 import java.util.Set;
 52  
 import java.util.regex.PatternSyntaxException;
 53  
 
 54  
 /**
 55  
  * The name says it all. This class is the base (template) for a module.
 56  
  *
 57  
  * @author D.A. Smedes
 58  
  * @version $Id: BaseModule.java,v 1.22 2004/11/02 23:57:06 asmedes Exp $
 59  
  */
 60  
 public abstract class BaseModule implements Module {
 61  
 
 62  184
   protected static Log logger = LogFactory.getLog(BaseModule.class);
 63  75
 
 64  798
   private Location location = null;
 65  914
   private String name = null;
 66  350
 
 67  876
   private File baseDir = null;
 68  914
   private File checkoutDir = null;
 69  350
 
 70  876
   private Version version = null;
 71  914
   private boolean patchLine = false;
 72  1070
   private boolean developmentLine = false;
 73  350
 
 74  156
   public BaseModule(String name, Location location, Version version) {
 75  224
     this(name, location);
 76  356
     this.version = version;
 77  512
   }
 78  288
 
 79  876
   public BaseModule(String name, Location location) {
 80  194
 
 81  876
     if (!name.matches(ModuleDigester.NAME_PATTERN_STRING)) {
 82  194
       throw new PatternSyntaxException(
 83  156
           "Pattern mismatch for 'name'. Should match " + ModuleDigester.NAME_PATTERN_STRING, name, -1);
 84  
     }
 85  720
     if (location == null) {
 86  194
       throw new IllegalArgumentException("Location cannot be null.");
 87  156
     }
 88  
 
 89  720
     this.name = name;
 90  914
     this.location = location;
 91  1070
   }
 92  350
 
 93  156
   /**
 94  
    * Gets the modules' name.
 95  
    *
 96  
    * @see Module#getName
 97  
    */
 98  
   public final String getName() {
 99  1000
     return name;
 100  649
   }
 101  786
 
 102  
   /**
 103  
    * Gets the modules' location.
 104  
    *
 105  
    * @return See {@link nl.toolforge.karma.core.location.Location}, and all implementing classes.
 106  
    */
 107  
   public final Location getLocation() {
 108  416
     return location;
 109  400
   }
 110  492
 
 111  
   public boolean equals(Object obj) {
 112  
 
 113  0
     if (obj instanceof BaseModule) {
 114  0
       if (((BaseModule) obj).getName().equals(getName()) &&
 115  
           ((BaseModule) obj).getLocation().equals(getLocation())) {
 116  0
         return true;
 117  
       }
 118  
     }
 119  0
     return false;
 120  
   }
 121  
 
 122  
   public int hashCode() {
 123  0
     return getName().hashCode() + getLocation().hashCode();
 124  20
   }
 125  30
 
 126  
 
 127  
   /**
 128  
    * Future functionality. Not yet supported. Returns <code>false</code>.
 129  
    *
 130  
    * @return <code>false</code>.
 131  
    */
 132  
   public final boolean hasDevelopmentLine() {
 133  0
     return false;
 134  
   }
 135  
 
 136  
   public final void markDevelopmentLine(boolean mark) {
 137  0
     developmentLine = mark;
 138  20
   }
 139  50
 
 140  30
   public final DevelopmentLine getPatchLine() {
 141  16
     return new PatchLine(getVersion());
 142  15
   }
 143  18
 
 144  
   public final void markPatchLine(boolean mark) {
 145  16
     patchLine = true;
 146  26
   }
 147  22
 
 148  12
   public final Version getVersion() {
 149  48
     return version;
 150  75
   }
 151  102
 
 152  
   /**
 153  
    * If the module element in the manifest contains a <code>version</code> attribute, this method will return the
 154  
    * value of that attribute.
 155  
    *
 156  
    * @return The module version, or <code>N/A</code>, when no version number exists.
 157  
    */
 158  
   public final String getVersionAsString() {
 159  16
     return (version == null ? "N/A" : version.getVersionNumber());
 160  10
   }
 161  12
 
 162  
   public final boolean hasVersion() {
 163  88
     return version != null;
 164  35
   }
 165  36
 
 166  
 
 167  
   /**
 168  
    * Checks if this module has been patched (and is thus part of a <code>ReleaseManifest</code>).
 169  
    *
 170  
    * @return <code>true</code> when this module has a <code>PatchLine</code> attached to it, <code>false</code> if it
 171  
    *         hasn't.
 172  
    */
 173  
   public final boolean hasPatchLine() {
 174  8
     return patchLine;
 175  5
   }
 176  6
 
 177  
   /**
 178  
    * When initialized by <code>AbstractManifest</code>, a module is assigned its base directory, relative to the manifest. The
 179  
    * base directory is used internally for base-directory-aware methods.
 180  
    *
 181  
    * @param baseDir
 182  
    */
 183  
   public final void setBaseDir(File baseDir) {
 184  
 
 185  704
     if (baseDir == null) {
 186  192
       throw new IllegalArgumentException("If you use it, initialize it with a valid 'File' instance ...");
 187  156
     }
 188  704
     this.baseDir = baseDir;
 189  896
   }
 190  348
 
 191  156
   public final File getBaseDir() {
 192  
 
 193  1696
     if (baseDir == null) {
 194  498
       throw new KarmaRuntimeException("Basedir not set.");
 195  498
     }
 196  1696
     return baseDir;
 197  498
   }
 198  498
 
 199  
   public abstract ModuleLayoutTemplate getLayoutTemplate();
 200  
 
 201  
   /**
 202  96
    *
 203  144
    * @param createComment
 204  
    * @throws VersionControlException
 205  96
    * @throws AuthenticationException
 206  240
    */
 207  144
   public final void createRemote(Authenticator authenticator, String createComment) throws AuthenticationException, VersionControlException {
 208  
 
 209  
     // Create the layout and return its location.
 210  
     //
 211  32
     File tmpDir = null;
 212  
     try {
 213  32
       tmpDir = MyFileUtils.createTempDirectory();
 214  0
     } catch (IOException e) {
 215  96
       throw new KarmaRuntimeException("Could not create temporary directory.");
 216  176
     }
 217  
 
 218  128
     File moduleDir = new File(tmpDir, getName());
 219  176
     moduleDir.mkdir();
 220  
 
 221  
     // Create the modules' layout
 222  
     //
 223  
     try {
 224  32
       getLayoutTemplate().createLayout(moduleDir);
 225  0
     } catch (IOException e) {
 226  
       // todo
 227  0
       e.printStackTrace();
 228  32
     }
 229  
 
 230  32
     logger.debug("Created layout for module `" + getName() + "`");
 231  
 
 232  
     // Add the module to the version control system
 233  20
     //
 234  56
     setBaseDir(moduleDir);
 235  20
 
 236  56
     ModuleDescriptor descriptor = new ModuleDescriptor(this);
 237  
     try {
 238  52
       descriptor.createFile(moduleDir);
 239  24
     } catch (IOException e) {
 240  20
       // todo
 241  44
       e.printStackTrace();
 242  56
     }
 243  
 
 244  
     // Prepare the module history
 245  
     //
 246  52
     ModuleHistory history = null;
 247  24
     try {
 248  32
       history = ModuleHistoryFactory.getInstance(getBaseDir()).getModuleHistory(this);
 249  0
     } catch (ModuleHistoryException e) {
 250  20
       throw new OutOfTheBlueException("Module history does not yet exist, so this is impossible.");
 251  56
     }
 252  20
 
 253  56
     ModuleHistoryEvent event = new ModuleHistoryEvent();
 254  32
     event.setType(ModuleHistoryEvent.CREATE_MODULE_EVENT);
 255  32
     event.setVersion(Version.INITIAL_VERSION);
 256  48
     event.setDatetime(new Date());
 257  44
 
 258  24
     // Is a requirement.
 259  20
     //
 260  56
     Authenticator a = Authenticators.getAuthenticator(authenticator);
 261  20
 
 262  56
     event.setAuthor(a.getUsername());
 263  32
     event.setComment(createComment);
 264  32
     history.addEvent(event);
 265  20
     try {
 266  56
       history.save();
 267  0
     } catch (ModuleHistoryException mhe) {
 268  0
       logger.error("Troubles when saving the module history.", mhe);
 269  52
     }
 270  24
 
 271  52
     CVSRunner runner = (CVSRunner) RunnerFactory.getRunner(getLocation());
 272  56
     runner.addModule(this, createComment);
 273  
 
 274  20
     try {
 275  56
       FileUtils.deleteDirectory(tmpDir);
 276  20
     } catch (IOException e) {
 277  44
       logger.warn("Could not remove temporary directory. It is probably still locked by the OS.");
 278  76
     }
 279  76
   }
 280  24
 
 281  
   /**
 282  
    * Reads <code>module-descriptor.xml</code>-file from the module base directory. If the base directory does not exist,
 283  20
    * <code>Module.UNKNOWN</code> is returned.
 284  24
    *
 285  20
    * @return The module type.
 286  44
    * @throws ModuleTypeException When <code>module-descriptor</code> is non-existing. This is possible when the
 287  44
    *   module is not locally available.
 288  36
    */
 289  32
   public final Type getType() throws ModuleTypeException {
 290  12
 
 291  36
     try {
 292  64
       getBaseDir();
 293  0
     } catch (KarmaRuntimeException k) {
 294  20
       return Module.UNKNOWN;
 295  64
     }
 296  
 
 297  44
     if (!new File(getBaseDir(), Module.MODULE_DESCRIPTOR).exists()) {
 298  44
       throw new ModuleTypeException(ModuleTypeException.MISSING_MODULE_DESCRIPTOR);
 299  24
     }
 300  
 
 301  40
     Digester digester = new Digester();
 302  8
 
 303  32
     digester.addObjectCreate("module-descriptor", Module.Type.class);
 304  32
     digester.addCallMethod("module-descriptor/type", "setType", 0);
 305  
 
 306  
     try {
 307  32
       return (Type) digester.parse(new File(getBaseDir(), Module.MODULE_DESCRIPTOR).getPath());
 308  0
     } catch (IOException e) {
 309  0
       throw new ModuleTypeException(ModuleTypeException.INVALID_MODULE_DESCRIPTOR);
 310  0
     } catch (SAXException e) {
 311  12
       throw new ModuleTypeException(ModuleTypeException.INVALID_MODULE_DESCRIPTOR);
 312  24
     }
 313  
   }
 314  12
 
 315  32
   /**
 316  12
    * See {@link Module#getDependencies}. This implementation throws a <code>KarmaRuntimeException</code> when the
 317  24
    *  modules' <code>dependencies.xml</code> could not be parsed properly. When no dependencies have been specified, or
 318  8
    * when the file does not exist, the method returns an empty <code>Set</code>.
 319  
    *
 320  20
    * @return A <code>Set</code> containing {@link nl.toolforge.karma.core.scm.ModuleDependency} instances.
 321  24
    */
 322  12
   public final Set getDependencies() {
 323  36
 
 324  32
     Set dependencies = new HashSet();
 325  
 
 326  20
     // Read in the base dependency structure of a Maven project.xml file
 327  32
     //
 328  0
     Digester digester = new Digester();
 329  
 
 330  8
     digester.addObjectCreate("*/dependencies", HashSet.class);
 331  0
     digester.addFactoryCreate("*/dependency", ModuleDependencyCreationFactory.class);
 332  0
     digester.addSetNext("*/dependency", "add");
 333  
 
 334  
     try {
 335  
 
 336  0
       dependencies = (Set) digester.parse(new File(getBaseDir(), "dependencies.xml"));
 337  
 
 338  0
     } catch (IOException e) {
 339  0
       return new HashSet();
 340  0
     } catch (SAXException e) {
 341  0
       throw new KarmaRuntimeException(ManifestException.DEPENDENCY_FILE_LOAD_ERROR, class="keyword">new Object[]{getName()});
 342  0
     }
 343  0
     return dependencies;
 344  
   }
 345  
 
 346  
   /**
 347  
    * Returns the module name.
 348  
    *
 349  
    * @return
 350  
    */
 351  
   public String toString() {
 352  0
     return getName();
 353  
   }
 354  
 
 355  
 }

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