View Javadoc
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.beanstalk.maven.plugin;
31  
32  import com.google.common.base.Joiner;
33  import com.google.common.io.CharStreams;
34  import com.google.common.io.Closeables;
35  import com.jcabi.log.Logger;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.io.InputStreamReader;
39  import java.util.Enumeration;
40  import java.util.zip.ZipEntry;
41  import java.util.zip.ZipFile;
42  import org.apache.commons.lang3.NotImplementedException;
43  import org.apache.maven.plugin.MojoFailureException;
44  
45  /**
46   * Represents a WAR file with .ebextensions directory.
47   * @author Dmitri Pisarenko (dp@altruix.co)
48   * @version $Id$
49   * @since 1.0
50   * @checkstyle DesignForExtensionCheck
51   */
52  @SuppressWarnings("PMD.UnusedFormalParameter")
53  public final class WarFile {
54      /**
55       * Location of the WAR file.
56       */
57      private final transient ZipFile war;
58  
59      /**
60       * Creates an instance of WarFile.
61       * @param file The location of the WAR file.
62       */
63      public WarFile(final ZipFile file) {
64          this.war = file;
65      }
66      /**
67       * Verifies that the .ebextensions contains valid configuration file or
68       * files.
69       * @throws org.apache.maven.plugin.MojoFailureException Thrown, if the
70       *  .ebextensions does not exist in the WAR file, is empty or one of its
71       *  files is neither valid JSON, nor valid YAML.
72       */
73      public void checkEbextensionsValidity() throws MojoFailureException {
74          final ZipEntry ebextdir = this.war.getEntry(".ebextensions");
75          if (ebextdir == null) {
76              throw new MojoFailureException(
77                  ".ebextensions directory does not exist in the WAR file"
78              );
79          }
80          final Enumeration<? extends ZipEntry> entries = this.war.entries();
81          int files = 0;
82          while (entries.hasMoreElements()) {
83              final ZipEntry entry = entries.nextElement();
84              if (entry.getName().startsWith(".ebextensions/")
85                  && !entry.isDirectory()) {
86                  files += 1;
87                  final String text = this.readFile(this.war, entry);
88                  if (!(this.validJson(text) || this.validYaml(text))) {
89                      throw new MojoFailureException(
90                          Joiner.on("").join(
91                              "File '",
92                              entry.getName(),
93                              "' in .ebextensions is neither valid JSON,",
94                              " nor valid YAML"
95                          )
96                      );
97                  }
98              }
99          }
100         if (files < 1) {
101             throw new MojoFailureException(
102                 ".ebextensions contains no config files."
103             );
104         }
105     }
106 
107     /**
108      * Reads text from a ZIP file.
109      * @param warfile ZIP file, which contains entry.
110      * @param entry ZIP entry (compressed file) to read from.
111      * @return Text content of entry.
112      */
113     private String readFile(final ZipFile warfile, final ZipEntry entry) {
114         String text = null;
115         InputStream inputStream = null;
116         InputStreamReader reader = null;
117         try {
118             inputStream = warfile.getInputStream(entry);
119             reader = new InputStreamReader(inputStream);
120             text = CharStreams.toString(reader);
121         } catch (final IOException exception) {
122             Logger.error(this, exception.getMessage());
123         } finally {
124             Closeables.closeQuietly(inputStream);
125             Closeables.closeQuietly(reader);
126         }
127         return text;
128     }
129 
130     /**
131      * Validates a YAML string.
132      * @param text Text to validate
133      * @return True, if text is a valid YAML string.
134      * @todo #2:30min Implement validation of YAML inside the method
135      *  AbstractBeanstalkMojo.validYaml. Remember to unit test your solution.
136      */
137     private boolean validYaml(final String text) {
138         throw new NotImplementedException(
139             "com.jcabi.beanstalk.maven.plugin.AbstractBeanstalkMojo.validYaml"
140         );
141     }
142 
143     /**
144      * Validates a JSON string.
145      * @param text Text to validate
146      * @return True, if text is a valid JSON string.
147      * @todo #2:30min Implement validation of JSON inside the method
148      *  AbstractBeanstalkMojo.validJson(). Remember to unit test your solution.
149      */
150     private boolean validJson(final String text) {
151         throw new NotImplementedException(
152             "com.jcabi.beanstalk.maven.plugin.AbstractBeanstalkMojo.validJson"
153         );
154     }
155 
156 }