View Javadoc
1   package org.codehaus.mojo.javancss;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.BufferedReader;
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.StringReader;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import javancss.Javancss;
30  import javancss.parser.ParseException;
31  
32  import org.apache.maven.reporting.MavenReportException;
33  import org.codehaus.plexus.util.IOUtil;
34  
35  /**
36   * The NcssExecuter is able to call JavaNCSS to produce a code analysis.<br>
37   * The results are produced into a raw xml file.
38   *
39   * @author <a href="jeanlaurent@gmail.com">Jean-Laurent de Morlhon</a>
40   * @version $Id$
41   */
42  public class NcssExecuter
43  {
44      private static final int ARG_SIZE = 8;
45  
46      // the full path to the directory holding the sources to point JavaNCSS to.
47      // Or the location of a file holding the path towards all files. (javancss style *sigh* :)
48      private File sourceLocation;
49  
50      // JavaNCSS will write an xml output into this file.
51      private String outputFilename;
52  
53      private String[] fileList;
54  
55      private String encoding = null;
56  
57      /**
58       * Construct a NcssExecuter with no arguments.<br>
59       * Used for testing.
60       */
61      /* package */NcssExecuter()
62      {
63          this.sourceLocation = null;
64          this.outputFilename = null;
65          this.fileList = null;
66      }
67  
68      /**
69       * Construct a NcssExecuter.
70       *
71       * @param sourceDirectory the directory where the source to analyze are.
72       * @param outputFilename the output file where the result will be written.
73       */
74      public NcssExecuter( File sourceDirectory, String outputFilename )
75      {
76          this.sourceLocation = sourceDirectory;
77          this.outputFilename = outputFilename;
78          this.fileList = null;
79      }
80  
81      public NcssExecuter( String[] fileList, String outputFilename )
82      {
83          this.sourceLocation = null;
84          this.fileList = fileList;
85          this.outputFilename = outputFilename;
86      }
87  
88      public void setEncoding( String encoding )
89      {
90          this.encoding = encoding;
91      }
92  
93      public String getEncoding()
94      {
95          return encoding;
96      }
97  
98      /**
99       * Call the JavaNCSS code analysis tool to produce the result to a temporary file.
100      *
101      * @throws MavenReportException if something goes bad during the execution
102      */
103     public void execute()
104         throws MavenReportException
105     {
106         try
107         {
108             Javancss javancss = new Javancss( getCommandLineArgument() );
109             Throwable ncssThrow = javancss.getLastError();
110             if ( ncssThrow != null )
111             {
112                 String lastErrorMessage = limit( javancss.getLastErrorMessage(), 3 );
113 
114                 if ( ncssThrow instanceof ParseException )
115                 {
116                     throw new MavenReportException( "Parsing error while executing JavaNCSS " + getJavaNCSSVersion()
117                         + " " + lastErrorMessage, (Exception) ncssThrow );
118                 }
119 
120                 Exception e = ( ncssThrow instanceof Exception ) ? (Exception) ncssThrow : new Exception( ncssThrow );
121                 throw new MavenReportException( "Unexpected error while executing JavaNCSS " + getJavaNCSSVersion()
122                     + " " + lastErrorMessage, e );
123             }
124         }
125         catch ( IOException ioe )
126         {
127             throw new MavenReportException( "IO Error while executing JavaNCSS " + getJavaNCSSVersion(), ioe );
128         }
129     }
130 
131     private String limit( String source, int lines )
132     {
133         BufferedReader reader = new BufferedReader( new StringReader( source ) );
134         StringBuilder sb = new StringBuilder();
135         try
136         {
137             for ( int i = 0; i < lines; i++ )
138             {
139                 String line = reader.readLine();
140 
141                 if ( line != null )
142                 {
143                     if ( sb.length() > 0 )
144                     {
145                         sb.append( "\n" );
146                     }
147                     sb.append( line );
148                 }
149             }
150         }
151         catch ( IOException ioe )
152         {
153             // cannot happen: in-memory StringReader
154         }
155         finally
156         {
157             IOUtil.close( reader );
158         }
159         return sb.toString();
160     }
161 
162     private String[] getCommandLineArgument()
163     {
164         List<String> argumentList = new ArrayList<String>( ARG_SIZE );
165         argumentList.add( "-package" );
166         argumentList.add( "-object" );
167         argumentList.add( "-function" );
168         argumentList.add( "-xml" );
169         argumentList.add( "-recursive" );
170         argumentList.add( "-out" );
171         argumentList.add( outputFilename );
172 
173         if ( encoding != null )
174         {
175             argumentList.add( "-encoding" );
176             argumentList.add( encoding );
177         }
178 
179         // If the source location is a directory, it means we can pass it straight to
180         // javancss. If it's a file, we assume it's containing the file list to parse
181         // so we pass it to javancss the way it expects it.
182         // (check javancss cmd line doc for more information)
183         if ( ( sourceLocation != null ) && ( sourceLocation.isDirectory() ) )
184         {
185             argumentList.add( sourceLocation.getAbsolutePath() );
186         }
187         else
188         {
189             for ( int i = 0; i < fileList.length; i++ )
190             {
191                 argumentList.add( fileList[i] );
192             }
193         }
194         return (String[]) argumentList.toArray( new String[argumentList.size()] );
195     }
196 
197     public static String getJavaNCSSVersion()
198     {
199         Package p = Javancss.class.getPackage();
200         String version = ( p == null ) ? null : p.getSpecificationVersion();
201         if ( version == null )
202         {
203             version = "unknown";
204         }
205         return version;
206     }
207 }