View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.creadur.whisker.out.velocity;
20  
21  import java.io.Writer;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  
26  import org.apache.commons.io.IOUtils;
27  import org.apache.commons.logging.Log;
28  import org.apache.creadur.whisker.app.Configuration;
29  import org.apache.creadur.whisker.app.ResultWriterFactory;
30  import org.apache.creadur.whisker.app.analysis.LicenseAnalyst;
31  import org.apache.creadur.whisker.model.Descriptor;
32  import org.apache.creadur.whisker.scan.Directory;
33  import org.apache.velocity.VelocityContext;
34  import org.apache.velocity.app.VelocityEngine;
35  import org.apache.velocity.runtime.RuntimeServices;
36  import org.apache.velocity.runtime.log.LogChute;
37  
38  /**
39   * Wraps velocity engine.
40   */
41  public class VelocityReports implements LogChute {
42      /** XML generation template. */
43      private static final Product[] PRODUCTS_THAT_GENERATE_TEMPLATES
44          = {Product.XML_TEMPLATE};
45      /** Missing license report. */
46      private static final Product[] PRODUCTS_THAT_VALIDATE
47          = {Product.MISSING_LICENSE_REPORT_TEMPLATE};
48      /** Directories report. */
49      private static final Product[] PRODUCTS_THAT_REPORT_ON_DIRECTORIES
50          = {Product.DIRECTORIES_REPORT_TEMPLATE};
51      /** Legal documents. */
52      private static final Product[] PRODUCTS_THAT_GENERATE_LICENSING_MATERIALS
53          = {Product.LICENSE, Product.NOTICE};
54  
55      /** Makes writes, not null. */
56      private final ResultWriterFactory writerFactory;
57      /** Merges templates, not null. */
58      private final VelocityEngine engine;
59      /** Logs messages, not null. */
60      private final Log log;
61  
62      /**
63       * Constructs a reporter using Apache Velocity.
64       * @param writerFactory not null
65       * @param log not null
66       */
67      public VelocityReports(
68              final ResultWriterFactory writerFactory, final Log log) {
69          this.writerFactory = writerFactory;
70          this.log = log;
71          engine = new VelocityEngine();
72          engine.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM, this);
73          engine.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
74          engine.setProperty("classpath.resource.loader.class",
75              "org.apache.velocity.runtime.resource.loader."
76                  + "ClasspathResourceLoader");
77          engine.init();
78      }
79  
80      /**
81       * Unused.
82       * @param services unused
83       * @see LogChute#init(RuntimeServices)
84       */
85      public final void init(final RuntimeServices services) { }
86  
87      /**
88       * Indicates whether logging is enabled.
89       * @param level at this level
90       * @return true when log level is enabled, false otherwise
91       * @see LogChute#isLevelEnabled(int)
92       */
93      public final boolean isLevelEnabled(final int level) {
94          switch (level) {
95              case DEBUG_ID:
96                  return log.isDebugEnabled();
97              case TRACE_ID:
98                  return log.isTraceEnabled();
99              case INFO_ID:
100                 return log.isInfoEnabled();
101             case WARN_ID:
102                 return log.isWarnEnabled();
103             case ERROR_ID:
104                 return log.isErrorEnabled();
105             default:
106                 return false;
107         }
108     }
109 
110     /**
111      * Logs a message.
112      * @param level at level
113      * @param message possibly null
114      * @see LogChute#log(int, String)
115      */
116     public final void log(final int level, final String message) {
117         switch (level) {
118             case DEBUG_ID:
119                 log.debug(message);
120                 break;
121             case TRACE_ID:
122                 log.trace(message);
123                 break;
124             case INFO_ID:
125                 log.info(message);
126                 break;
127             case WARN_ID:
128                 log.warn(message);
129                 break;
130             case ERROR_ID:
131                 log.error(message);
132                 break;
133             default:
134                 log.trace(message);
135         }
136     }
137 
138     /**
139      * Logs a message from Velocity.
140      * @param level log level
141      * @param message possibly null
142      * @param throwable possibly null
143      * @see LogChute#log(int, String, Throwable)
144      */
145     public final void log(final int level,
146             final String message, final Throwable throwable) {
147         switch (level) {
148             case DEBUG_ID:
149                 log.debug(message, throwable);
150                 break;
151             case TRACE_ID:
152                 log.trace(message, throwable);
153                 break;
154             case INFO_ID:
155                 log.info(message, throwable);
156                 break;
157             case WARN_ID:
158                 log.warn(message, throwable);
159                 break;
160             case ERROR_ID:
161                 log.error(message, throwable);
162                 break;
163             default:
164                 log.trace(message, throwable);
165         }
166     }
167 
168     /**
169      * Reports on work.
170      * @param work not null
171      * @param configuration not null
172      * @throws Exception when generation fails
173      */
174     public final void generate(final Descriptor work,
175             final Configuration configuration) throws Exception {
176         final List<Product> products = new ArrayList<Product>();
177         for (Product product: PRODUCTS_THAT_GENERATE_LICENSING_MATERIALS) {
178             switch (product) {
179                 case NOTICE:
180                     if (!work.isNoticeRequired()) {
181                         break;
182                     }
183                 default:
184                     products.add(product);
185             }
186 
187 
188         }
189         final Product[] pruductArray = new Product[products.size()];
190         merge(products.toArray(pruductArray), context(work, configuration));
191     }
192 
193     /**
194      * Merges context with product templates, and writes results.
195      * @param products not null
196      * @param context not null
197      * @throws Exception when merger fails
198      */
199     private void merge(final Product[] products,
200             final VelocityContext context) throws Exception {
201         for (final Product product : products) {
202             merge(product, context);
203         }
204     }
205 
206     /**
207      * Merges context with product template, and writes results.
208      * @param product not null
209      * @param context not null
210      * @throws Exception when generate fails
211      */
212     private void merge(
213             final Product product, final VelocityContext context)
214                 throws Exception {
215         final Writer writer = product.writerFrom(writerFactory);
216         engine.getTemplate(
217                 template(product.getTemplate())).merge(context, writer);
218         IOUtils.closeQuietly(writer);
219     }
220 
221     /**
222      * Creates a context, and loads it for descriptor work.
223      * @param work not null
224      * @param configuration not null
225      * @return not null
226      */
227     private VelocityContext context(final Descriptor work,
228             final Configuration configuration) {
229         final VelocityContext context = new VelocityContext();
230         context.put("work", work);
231         context.put("indent", new Indentation());
232         context.put("helper", new RenderingHelper(work, configuration));
233         return context;
234     }
235 
236 
237     /**
238      * Returns the full template path.
239      * @param name not null
240      * @return not null
241      */
242     private String template(final String name) {
243         return "org/apache/creadur/whisker/template/velocity/"
244                 + name.toLowerCase() + ".vm";
245     }
246 
247     /**
248      * Generates a directory report.
249      * @param directories not null
250      * @throws Exception when reporting fails
251      */
252     public final void report(
253             final Collection<Directory> directories) throws Exception {
254         merge(PRODUCTS_THAT_REPORT_ON_DIRECTORIES, context(directories));
255     }
256 
257     /**
258      * Creates a content, and loads it with the directories.
259      * @param directories not null
260      * @return not null
261      */
262     private VelocityContext context(
263             final Collection<Directory> directories) {
264         final VelocityContext context = new VelocityContext();
265         context.put("dirs", directories);
266         return context;
267     }
268 
269     /**
270      * Reports on analysis.
271      * @param analyst not null
272      * @throws Exception when validation fails
273      */
274     public final void validate(
275             final LicenseAnalyst analyst) throws Exception {
276         merge(PRODUCTS_THAT_VALIDATE, context(analyst));
277     }
278 
279     /**
280      * Creates a context, and loads it with the analyst.
281      * @param analyst not null
282      * @return not null
283      */
284     private VelocityContext context(final LicenseAnalyst analyst) {
285         final VelocityContext context = new VelocityContext();
286         context.put("analyst", analyst);
287         return context;
288     }
289 
290     /**
291      * Generates template.
292      * @param withBase not null
293      * @throws Exception when generation fails
294      */
295     public final void generateTemplate(
296             final Collection<Directory> withBase) throws Exception {
297         merge(PRODUCTS_THAT_GENERATE_TEMPLATES, context(withBase));
298     }
299 }