Coverage Report - com.jcabi.heroku.maven.plugin.DeployMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
DeployMojo
17%
7/40
6%
1/16
5.75
 
 1  
 /**
 2  
  * Copyright (c) 2012-2014, jcabi.com
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met: 1) Redistributions of source code must retain the above
 8  
  * copyright notice, this list of conditions and the following
 9  
  * disclaimer. 2) Redistributions in binary form must reproduce the above
 10  
  * copyright notice, this list of conditions and the following
 11  
  * disclaimer in the documentation and/or other materials provided
 12  
  * with the distribution. 3) Neither the name of the jcabi.com nor
 13  
  * the names of its contributors may be used to endorse or promote
 14  
  * products derived from this software without specific prior written
 15  
  * permission.
 16  
  *
 17  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 19  
  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 20  
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 21  
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 22  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23  
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 24  
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 25  
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 26  
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 28  
  * OF THE POSSIBILITY OF SUCH DAMAGE.
 29  
  */
 30  
 package com.jcabi.heroku.maven.plugin;
 31  
 
 32  
 import com.jcabi.log.Logger;
 33  
 import com.jcabi.velocity.VelocityPage;
 34  
 import java.io.File;
 35  
 import java.util.ArrayList;
 36  
 import java.util.List;
 37  
 import org.apache.maven.artifact.Artifact;
 38  
 import org.apache.maven.artifact.DefaultArtifact;
 39  
 import org.apache.maven.plugin.AbstractMojo;
 40  
 import org.apache.maven.plugin.MojoFailureException;
 41  
 import org.apache.maven.project.MavenProject;
 42  
 import org.apache.maven.settings.Server;
 43  
 import org.apache.maven.settings.Settings;
 44  
 import org.jfrog.maven.annomojo.annotations.MojoGoal;
 45  
 import org.jfrog.maven.annomojo.annotations.MojoParameter;
 46  
 import org.jfrog.maven.annomojo.annotations.MojoPhase;
 47  
 import org.slf4j.impl.StaticLoggerBinder;
 48  
 
 49  
 /**
 50  
  * Deploys JAR/WAR artifact to Heroku.
 51  
  *
 52  
  * @author Yegor Bugayenko (yegor@tpc2.com)
 53  
  * @version $Id$
 54  
  * @since 0.4
 55  
  */
 56  
 @MojoGoal("deploy")
 57  
 @MojoPhase("deploy")
 58  1
 public final class DeployMojo extends AbstractMojo {
 59  
 
 60  
     /**
 61  
      * Maven project.
 62  
      */
 63  
     @MojoParameter(
 64  
         expression = "${project}",
 65  
         required = true,
 66  
         readonly = true,
 67  
         description = "Maven project"
 68  
     )
 69  
     private transient MavenProject project;
 70  
 
 71  
     /**
 72  
      * Setting.xml.
 73  
      */
 74  
     @MojoParameter(
 75  
         expression = "${settings}",
 76  
         required = true,
 77  
         readonly = true,
 78  
         description = "Maven settings.xml reference"
 79  
     )
 80  
     private transient Settings settings;
 81  
 
 82  
     /**
 83  
      * Shall we skip execution?
 84  
      */
 85  
     @MojoParameter(
 86  
         defaultValue = "false",
 87  
         required = false,
 88  
         description = "Skips execution"
 89  
     )
 90  
     private transient boolean skip;
 91  
 
 92  
     /**
 93  
      * Server ID from settings.xml.
 94  
      */
 95  
     @MojoParameter(
 96  
         defaultValue = "heroku.com",
 97  
         required = false,
 98  
         description = "Server ID from settings.xml"
 99  
     )
 100  
     private transient String server;
 101  
 
 102  
     /**
 103  
      * Application name.
 104  
      */
 105  
     @MojoParameter(
 106  
         required = true,
 107  
         description = "Heroku application name"
 108  
     )
 109  
     private transient String name;
 110  
 
 111  
     /**
 112  
      * Content of {@code Procfile}.
 113  
      */
 114  
     @MojoParameter(
 115  
         required = true,
 116  
         description = "Content of Procfile"
 117  
     )
 118  
     private transient String procfile;
 119  
 
 120  
     /**
 121  
      * List of artifacts to download.
 122  
      */
 123  
     @MojoParameter(
 124  
         required = true,
 125  
         description = "Artifacts to download during deployment"
 126  
     )
 127  
     private transient String[] artifacts;
 128  
 
 129  
     /**
 130  
      * Set skip option.
 131  
      * @param skp Shall we skip execution?
 132  
      */
 133  
     public void setSkip(final boolean skp) {
 134  1
         this.skip = skp;
 135  1
     }
 136  
 
 137  
     @Override
 138  
     @SuppressWarnings("PMD.PrematureDeclaration")
 139  
     public void execute() throws MojoFailureException {
 140  1
         StaticLoggerBinder.getSingleton().setMavenLog(this.getLog());
 141  1
         if (this.skip) {
 142  1
             Logger.info(this, "execution skipped because of 'skip' option");
 143  1
             return;
 144  
         }
 145  0
         final long start = System.currentTimeMillis();
 146  0
         final Heroku heroku = new Heroku(this.git(), this.name);
 147  0
         final Repo repo = heroku.clone(
 148  
             new File(new File(this.project.getBuild().getDirectory()), "heroku")
 149  
         );
 150  
         try {
 151  0
             repo.add(
 152  
                 "settings.xml",
 153  
                 new VelocityPage(
 154  
                     "com/jcabi/heroku/maven/plugin/settings.xml.vm"
 155  
                 ).set("settings", this.settings).toString()
 156  
             );
 157  0
             repo.add(
 158  
                 "pom.xml",
 159  
                 new VelocityPage(
 160  
                     "com/jcabi/heroku/maven/plugin/pom.xml.vm"
 161  
                 ).set("project", this.project)
 162  
                     .set("deps", this.deps())
 163  
                     .set("timestamp", System.currentTimeMillis())
 164  
                     .toString()
 165  
             );
 166  0
             repo.add("Procfile", this.procfile.trim());
 167  0
         } catch (final java.io.IOException ex) {
 168  0
             throw new MojoFailureException("failed to save files", ex);
 169  0
         }
 170  0
         repo.commit();
 171  0
         Logger.info(this, "Done in %[ms]s", System.currentTimeMillis() - start);
 172  0
     }
 173  
 
 174  
     /**
 175  
      * Get git engine.
 176  
      * @return The engine
 177  
      * @throws MojoFailureException If somethings goes wrong
 178  
      */
 179  
     private Git git() throws MojoFailureException {
 180  0
         final Server srv = this.settings.getServer(this.server);
 181  0
         if (srv == null) {
 182  0
             throw new MojoFailureException(
 183  
                 String.format(
 184  
                     "Server '%s' not found in settings.xml",
 185  
                     this.server
 186  
                 )
 187  
             );
 188  
         }
 189  0
         final String location = srv.getPrivateKey();
 190  0
         if (location == null || location.isEmpty()) {
 191  0
             throw new MojoFailureException(
 192  
                 String.format(
 193  
                     "privateKey is not defined for '%s' server in settings.xml",
 194  
                     srv.getId()
 195  
                 )
 196  
             );
 197  
         }
 198  0
         final File file = new File(location);
 199  0
         if (!file.exists()) {
 200  0
             throw new MojoFailureException(
 201  
                 String.format("SSH key file '%s' doesn't exist", file)
 202  
             );
 203  
         }
 204  
         try {
 205  0
             return new Git(
 206  
                 file,
 207  
                 new File(this.project.getBuild().getDirectory())
 208  
             );
 209  0
         } catch (final java.io.IOException ex) {
 210  0
             throw new MojoFailureException("failed to initialize git", ex);
 211  
         }
 212  
     }
 213  
 
 214  
     /**
 215  
      * Create a collection of artifacts.
 216  
      *
 217  
      * <p>Coordinates should be formatted as
 218  
      * {@code groupId:artifactId:packaging:classifier:version}.
 219  
      *
 220  
      * @return List of them
 221  
      * @throws MojoFailureException If somethings goes wrong
 222  
      * @see <a href="http://maven.apache.org/pom.html#Maven_Coordinates">Maven coordinates</a>
 223  
      */
 224  
     @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
 225  
     private List<Artifact> deps() throws MojoFailureException {
 226  0
         if (this.artifacts.length == 0) {
 227  0
             throw new MojoFailureException(
 228  
                 "At least one artifact should be configured"
 229  
             );
 230  
         }
 231  0
         final List<Artifact> deps = new ArrayList<Artifact>(
 232  
             this.artifacts.length
 233  
         );
 234  0
         for (final String coordinates : this.artifacts) {
 235  0
             final String[] parts = coordinates.split(":");
 236  
             // @checkstyle MagicNumber (1 line)
 237  0
             if (parts.length != 5) {
 238  0
                 throw new MojoFailureException(
 239  
                     String.format(
 240  
                         "Maven artifact coordinates '%s' is not absolute",
 241  
                         coordinates
 242  
                     )
 243  
                 );
 244  
             }
 245  0
             deps.add(
 246  
                 // @checkstyle MagicNumber (10 lines)
 247  
                 new DefaultArtifact(
 248  
                     parts[0],
 249  
                     parts[1],
 250  
                     parts[4],
 251  
                     "runtime",
 252  
                     parts[2],
 253  
                     parts[3],
 254  
                     null
 255  
                 )
 256  
             );
 257  
         }
 258  0
         return deps;
 259  
     }
 260  
 
 261  
 }