Project Report: fawkez

Packagesummary org.jcoderz.phoenix.report

org.jcoderz.phoenix.report.Syntax

LineHitsNoteSource
1  /*
2   * $Id: Java2Html.java 1238 2008-11-03 12:37:53Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.phoenix.report;
34  
35  import java.io.BufferedReader;
36  import java.io.File;
37  import java.io.FileInputStream;
38  import java.io.IOException;
39  import java.io.InputStreamReader;
40  import java.io.LineNumberReader;
41  import java.io.Reader;
42  import java.io.StringReader;
43  import java.nio.charset.Charset;
44  import java.util.logging.Logger;
45  
46  import javax.swing.text.Segment;
47  
48  import org.gjt.sp.jedit.Mode;
49  import org.gjt.sp.jedit.syntax.DefaultTokenHandler;
50  import org.gjt.sp.jedit.syntax.ModeProvider;
51  import org.gjt.sp.jedit.syntax.ParserRuleSet;
52  import org.gjt.sp.jedit.syntax.Token;
53  import org.gjt.sp.jedit.syntax.TokenMarker;
54  import org.gjt.sp.jedit.syntax.TokenMarker.LineContext;
55  import org.jcoderz.commons.util.Assert;
56  import org.jcoderz.commons.util.IoUtil;
57  
58  
59  /**
60   * Splits an input file into several tokens suitable for syntax 
61   * highlighting.
62   * This class encapsulates the access to the jEdit syntax 
63   * highlighter package. No jEdit related classes should be
64   * passed by interfaces of this class. 
65   * 
66   * @author Andreas Mandel
67   */
68  public class Syntax
69  {
70      private static final int MAX_RATIO_ILLEGAL_CHARACTERS = 10;
71      private static final int MAX_AVERAGE_LINE_LENGTH = 200;
72      private static final int BINARY_TEST_PROBE_CHARACTERS = 1024;
730     private static final String CLASSNAME = Syntax.class.getName();
740     private static final Logger LOGGER = Logger.getLogger(CLASSNAME);
75      
76      private final Charset mSourceCharset;
77      private final int mTabWidth;
78      private final char[] mFileContent;
79      private int mFileContentPos;
80 (1)    // CHECKME: ate tabs in the token counted to the length?
810     private Token mToken = emptyToken();
82      private int mCurrentLineNumber;
83      private int mCurrentLinePos;
84      private Segment mCurrentLine;
85      private int mNumberOfLines;
86  
87      private final TokenMarker mTokenMarker;
880     private final DefaultTokenHandler mTokenHandler
89          = new DefaultTokenHandler();
900     private LineContext mLineContext = null;
91      /** First line of the file. */
92      private String mFirstLine;
93      
94      static
95      {
960         SyntaxModeCatalogHandler.loadModes();
970     }
98  
99      /**
100       * Initializes an Ascii2Html instance.
101       * 
102       * @param in the source file to read.
103       * @param charSet the char set to use when reading the source file.
104       *   If null the platform default char set will be used.  
105       * @param tabWidth the tab width to use when calculating the cursor
106       *   position.
107       * @throws IOException if a error occurs while reading the source file.
108       */
109      public Syntax (File in, Charset charSet, int tabWidth)
110          throws IOException
1110     {
1120         Assert.notNull(in, "in");
1130         mSourceCharset = charSet == null ? Charset.defaultCharset() : charSet;
1140(2)        mTabWidth = tabWidth;
1150         mFileContent = readFile(in).toCharArray();
1160         mFileContentPos = 0;
1170         mCurrentLineNumber = 0;
1180         mCurrentLine = null;
1190(3)        final Mode mode
120              = ModeProvider.instance.getModeForFile(in.getName(), mFirstLine);
1210         if (mode == null)
122          {
1230             if (isBinary(in.getAbsolutePath(), mFileContent))
124              {
1250                 throw new RuntimeException("No html view for binary file '"
126                      + in.getAbsolutePath() + "'.");
127              }
128              
1290             LOGGER.fine("Could not find mode file for '" + in.getName()
130                  + "'. Is the jedit-syntax.jar on the classpath?");
1310             mTokenMarker = new TokenMarker();
1320             mTokenMarker.addRuleSet(new ParserRuleSet("text", "MAIN"));
133          }
134          else
135          {
1360             mTokenMarker = mode.getTokenMarker();
137          }
1380     }
139  
140      /**
141       * Returns the number of lines of the parsed file. 
142       * The value is available after creation of the class.
143       * @return the number of lines of the parsed file.
144       */
145      public int getNumberOfLines ()
146      {
1470         return mNumberOfLines;
148      }
149      
150      /**
151       * The line number of the currently parsed token.
152       * Counting starts with line 1. Nevertheless prior the first call
153       * to {@link #nextToken()} 0 is returned.
154       * @return the line number of the currently parsed token.
155       */
156      public int getCurrentLineNumber ()
157      {
1580         return mCurrentLineNumber;
159      }
160      
161      /**
162       * Returns the cursor position of start of the current token.
163       * @return the cursor position of start of the current token.
164       */
165      public int getCurrentLinePos ()
166      {
1670         return mCurrentLinePos;
168      }
169      
170      /**
171       * Returns the current token type as string. 
172       * To be used as symbolic identifier of the token. Possible
173       * return values can be fount in {@link Token#tokenToString(byte)}.
174       * For the {@link Token#END} null is returned.
175       * @return the current token type as string.
176       */
177      public String getCurrentTokenType ()
178      {
179          final String result;
1800         if (mToken.id == Token.END)
181          {
1820             result = null;
183          }
184          else
185          {
1860             result = Token.tokenToString(mToken.id);
187          }
1880         return result;
189      }
190  
191      /**
192       * Returns the length of the current reported token.
193       * @return the length of the current reported token.
194       */
195      public int getCurrentTokenLength ()
196      {
1970         return mToken.length;
198      }
199  
200      /**
201       * Parses the next token and returns its textual content as string.
202       * @return the textual content of the new token.
203       */
204      public String nextToken ()
205      {
2060         if (mCurrentLine == null
207              || mToken.id == Token.END)
208          {
2090             nextLine();
210          }
211          else
212          {
2130             mCurrentLinePos += mToken.length;
2140             mToken = mToken.next;
215          }
216          final String result;
2170         if (mCurrentLine.count == 0)
218          {
2190             mToken = emptyToken();
2200             result = "";
221          }
222          else
223          {
2240             if (mToken != null)
225              {
2260                 result 
227                      = new String(mFileContent,
228                          mCurrentLine.offset + mToken.offset, mToken.length);
229              }
230              else
231              {
2320                 result = "";
2330                 mToken = emptyToken();
234              }
235          }
2360         return result;
237      }
238      
239      /**
240       * Forward to next line. Takes care for different line ending styles.
241       * Parsing for next line is started.
242       */
243 (4)    private void nextLine ()
244      {
2450         if (mFileContentPos > mFileContent.length)
246          {
2470             mCurrentLine = null; // END OF FILE
2480             mCurrentLineNumber = mNumberOfLines + 1;
249          }
250          else
251          {
2520             int pos = mFileContentPos;
253              while (pos < mFileContent.length
254                  && mFileContent[pos] != '\n'
2550                 && mFileContent[pos] != '\r')
256              {
2570                 pos++;
258              }
2590             final int currentLineEnd = pos;
2600             if (pos < mFileContent.length
261                  && (mFileContent[pos] == '\n'
262                      || mFileContent[pos] == '\r'))
263              {
2640                 pos++;
265              }
2660             if (pos < mFileContent.length
267                  && mFileContent[pos - 1] != mFileContent[pos]
268                  && (mFileContent[pos] == '\n'
269                      || mFileContent[pos] == '\r'))
270              {
2710                 pos++;
272              }
2730             mCurrentLine 
274                  = new Segment(mFileContent,
275                      mFileContentPos, currentLineEnd - mFileContentPos);
2760             mCurrentLineNumber++;
2770             mFileContentPos = pos;
2780             mCurrentLinePos = 1;
279              
2800             if (mCurrentLine.count > 0)
281              {
2820                 mTokenHandler.init();
2830                 mLineContext 
284                      = mTokenMarker.markTokens(
285                          mLineContext, mTokenHandler, mCurrentLine);
2860                 mToken = mTokenHandler.getTokens();
287              }
288              else
289              {
2900                 mToken = emptyToken();
291              }
292          }
2930     }
294      
295      private String readFile (File in)
296          throws IOException
297      {
2980         String result = "";
2990         final FileInputStream fis = new FileInputStream(in);
3000         Reader reader = null;
3010         LineNumberReader lnr = null;
302          try
303          {
3040             reader = new InputStreamReader(fis, mSourceCharset);
3050             lnr = new LineNumberReader(reader);
3060             result = IoUtil.readFully(lnr);
3070             mNumberOfLines = lnr.getLineNumber();
3080             mFirstLine 
309                  = new BufferedReader(new StringReader(result)).readLine();
310          }
311          finally
312          {
3130             IoUtil.close(lnr);
3140             IoUtil.close(reader);
3150             IoUtil.close(fis);
3160         }
3170         return result;
318      }
319      
320      private static Token emptyToken ()
321      {
3220         return new Token(Token.END, 0, 0, null);
323      }
324  
325      static boolean isBinary (String name, char[] fileContent)
326      {
3270         int newLines = 0;
3280         int chars = 0;
3290         int illegal = 0;
330          int i;
3310         for (i = 0; i < fileContent.length
3320             && i < BINARY_TEST_PROBE_CHARACTERS; i++)
333          {
3340             final char c = fileContent[i];
3350             if (c == '\n' || c == '\r')
336              {
3370                 newLines++;
338              }
3390             else if (Character.isWhitespace(c))
340              {
3410                 chars++;
342              }
3430             else if (Character.isISOControl(c))
344              {
3450                 illegal++;
346              }
3470             else if (Character.isDefined(c))
348              {
3490                 chars++;
350              }
351              else
352              {
3530                 illegal++;
354              }
355          }
3560         boolean result = false; // assume a text file
357          // less than a new line per 200 characters
3580         if (((newLines + 1) * MAX_AVERAGE_LINE_LENGTH) < i)
359          {
3600             result = true;
361          }
362          // to many 'illegal' chars
3630         else if (illegal * MAX_RATIO_ILLEGAL_CHARACTERS > chars)
364          {
3650             result = true;
366          }
3670         LOGGER.finest("For file " + name + " tested " + i + " chars with "
368              + newLines + " newlines, " + chars + " legal chars, "
369              + illegal + " illegal chars. -> "
370              + (result ? "isBinary" : "isNotBinary"));
3710         return result;
372      }
373  
374  }

Findings in this File

i (1) 80 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
w (2) 114 : 0 class org.jcoderz.phoenix.report.Syntax defines fields that are used only as locals
w (3) 119 : 0 class org.jcoderz.phoenix.report.Syntax defines fields that are used only as locals
c (4) 243 : 5 Cyclomatic Complexity is 13 (max allowed is 12).