001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.java.ast;
021    
022    import java.io.File;
023    import java.util.*;
024    
025    import com.google.common.collect.Maps;
026    import org.slf4j.Logger;
027    import org.slf4j.LoggerFactory;
028    import org.sonar.api.resources.InputFile;
029    import org.sonar.java.ast.visitor.JavaAstVisitor;
030    import org.sonar.java.recognizer.JavaFootprint;
031    import org.sonar.java.squid.JavaSquidConfiguration;
032    import org.sonar.squid.recognizer.CodeRecognizer;
033    import org.sonar.squid.text.Source;
034    
035    import com.puppycrawl.tools.checkstyle.api.Check;
036    import com.puppycrawl.tools.checkstyle.api.DetailAST;
037    
038    public class CheckstyleSquidBridge extends Check {
039    
040      private static Logger logger = LoggerFactory.getLogger(CheckstyleSquidBridge.class);
041      private static JavaAstVisitor[] visitors;
042      private static int[] allTokens;
043      private static CodeRecognizer codeRecognizer;
044      private static Map<java.io.File,InputFile> inputFilesByPath = Maps.newHashMap();
045    
046      static void setASTVisitors(List<JavaAstVisitor> visitors) {
047        CheckstyleSquidBridge.visitors = visitors.toArray(new JavaAstVisitor[visitors.size()]);
048        SortedSet<Integer> sorter = new TreeSet<Integer>();
049        for (JavaAstVisitor visitor : visitors) {
050          sorter.addAll(visitor.getWantedTokens());
051          allTokens = new int[sorter.size()];
052          int i = 0;
053          for (Integer itSorted : sorter) {
054            allTokens[i++] = itSorted;
055          }
056        }
057      }
058    
059      static void setSquidConfiguration(JavaSquidConfiguration conf) {
060        codeRecognizer = new CodeRecognizer(conf.getCommentedCodeThreshold(), new JavaFootprint());
061      }
062    
063      @Override
064      public int[] getDefaultTokens() {
065        return allTokens; //NOSONAR returning directly the array is not a security flaw here
066      }
067    
068      public static InputFile getInputFile(File path) {
069        return inputFilesByPath.get(path);
070      }
071    
072      public static void setInputFiles(Collection<InputFile> inputFiles) {
073        inputFilesByPath.clear();
074        for (InputFile inputFile : inputFiles) {
075          inputFilesByPath.put(inputFile.getFile().getAbsoluteFile(), inputFile);
076        }
077      }
078    
079      @Override
080      public void beginTree(DetailAST ast) {
081        try {
082          Source source = createSource();
083          for (JavaAstVisitor visitor : visitors) {
084            visitor.setFileContents(getFileContents());
085            visitor.setSource(source);
086            visitor.setInputFile(getInputFile(new java.io.File(getFileContents().getFilename())));
087            visitor.visitFile(ast);
088          }
089        } catch (RuntimeException e) {
090          logAndThrowException(e);
091        }
092      }
093    
094      private Source createSource() {
095        return new Source(getFileContents().getLines(), codeRecognizer);
096      }
097    
098      @Override
099      public void visitToken(DetailAST ast) {
100        try {
101          for (JavaAstVisitor visitor : visitors) {
102            if (visitor.getWantedTokens().contains(ast.getType())) {
103              visitor.visitToken(ast);
104            }
105          }
106        } catch (RuntimeException e) {
107          logAndThrowException(e);
108        }
109      }
110    
111      @Override
112      public void leaveToken(DetailAST ast) {
113        try {
114          for (int i = visitors.length - 1; i >= 0; i--) {
115            JavaAstVisitor visitor = visitors[i];
116            if (visitor.getWantedTokens().contains(ast.getType())) {
117              visitor.leaveToken(ast);
118            }
119          }
120        } catch (RuntimeException e) {
121          logAndThrowException(e);
122        }
123      }
124    
125      @Override
126      public void finishTree(DetailAST ast) {
127        try {
128          for (int i = visitors.length - 1; i >= 0; i--) {
129            JavaAstVisitor visitor = visitors[i];
130            visitor.leaveFile(ast);
131          }
132        } catch (RuntimeException e) {
133          logAndThrowException(e);
134        }
135      }
136    
137      private void logAndThrowException(RuntimeException e) {
138        logger.error("Squid Error occurs when analysing :" + getFileContents().getFilename(), e);
139        throw e;
140      }
141    
142    }