是否有任何Java / JDBC代码分析验证工具?

时间:2015-03-20 08:30:25

标签: java eclipse jdbc

我在非常庞大的旧项目中工作。我的任务是找到未在try块中初始化的所有JDBC连接。此外,我必须找到所有未关闭(或以错误的顺序关闭)结果集,语句和连接。是否有任何代码验证工具来搜索这种不良做法(可能与Eclispe集成,但不是必需的)。

2 个答案:

答案 0 :(得分:1)

您正在寻找静态分析工具。我认为FindBugs可能会对此有所帮助,但也有PMD(在较小程度上Checkstyle)。

特别是两个FingBugs支票可能有用:

答案 1 :(得分:1)

我写了一个小脚本来验证源代码。随意修改/使用:

import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class DbValidator
{

  public static void main(String[] args)
  {
    if (args.length < 0)
    {
      return;
    }

    Path lvRootPath = Paths.get(args[0]);

    findAndParse(lvRootPath);
  }

  private static void findAndParse(Path pmPath)
  {
    File lvDir = pmPath.toFile();

    if (!lvDir.exists())
    {
      return;
    }

    File[] lvFiles = lvDir.listFiles();

    for (File file : lvFiles)
    {
      if (file.isDirectory())
      {
        findAndParse(file.toPath());
      }
      else
      {
        if (file.getName().endsWith(".java"))
          parseFile(file.toPath());
      }
    }
  }

  private static void parseFile(Path pmPath)
  {
    // System.out.println("#Validating file: " + pmPath);
    try
    {
      List<String> lvLines = Files.readAllLines(pmPath,Charset.forName("UTF-8"));
      Map<String, Integer> lvConNames = new HashMap<String, Integer>(); // map var-name : level;
      Map<String, Integer> lvPsNames = new HashMap<String, Integer>();
      Map<String, Integer> lvRsNames = new HashMap<String, Integer>();
      List<Integer> lvTryBlocks = new ArrayList<Integer>(); // opened try blocks
      int lvLevel = 0;
      int lvLineIdx = 1;

      for (String line : lvLines)
      {
        lvLevel = checkLevel(line,lvLevel);
        closeTryBlocks(lvTryBlocks,lvLevel);
        checkIfConectionGetter(lvTryBlocks,line,lvLineIdx,pmPath);

        line = line.trim();

        if (line.startsWith("Connection"))
        {
          String lvName = line.replaceFirst("Connection\\s","").replaceAll("\\s*=\\s*(.)*+","");
          lvConNames.put(lvName,lvLevel);
          lvLineIdx++;
          continue;
        }
        else if (line.startsWith("PreparedStatement"))
        {
          String lvName = line.replaceFirst("PreparedStatement\\s","").replaceAll("\\s=\\s*(.)*+","");
          lvPsNames.put(lvName,lvLevel);
          lvLineIdx++;
          continue;
        }
        else if (line.startsWith("ResultSet"))
        {
          String lvName = line.replaceFirst("ResultSet\\s","").replaceAll("\\s=\\s*(.)*+","");
          lvRsNames.put(lvName,lvLevel);
        }
        else if (line.startsWith("try"))
        {
          lvTryBlocks.add(lvLevel);
          lvLineIdx++;
          continue;
        }
        else if (line.startsWith("StreamUtils.closeQuietly"))
        {
          String[] lvElements = line.replaceAll("StreamUtils.closeQuietly\\(","").replaceAll("\\);","").split(",");

          boolean lvWasPs = false;
          boolean lvWasCon = false;

          for (String element : lvElements)
          {
            element = element.trim();

            if (lvPsNames.get(element) != null)
            {
              lvPsNames.remove(element);
              if (lvWasCon)
              {
                System.out.println("#######################################################################");
                System.out.println("#!!! Warning at file \"" + pmPath + "\" at line: " + lvLineIdx);
                System.out.println("#Wrong closing order");
                System.out.println("#######################################################################");
              }

              lvWasPs = true;
            }
            else if (lvRsNames.get(element) != null)
            {
              lvRsNames.remove(element);

              if (lvWasCon || lvWasPs)
              {
                System.out.println("#######################################################################");
                System.out.println("#!!! Warning at file \"" + pmPath + "\" at line: " + lvLineIdx);
                System.out.println("#Wrong closing order");
                System.out.println("#######################################################################");
              }
            }
            else if (lvConNames.get(element) != null)
            {
              lvConNames.remove(element);
              lvWasCon = true;
            }
          }
        }

        Map<String, Integer> lvConNamesTmp = new HashMap<String, Integer>(lvConNames);
        for (Entry<String, Integer> entry : lvConNamesTmp.entrySet())
        {
          Integer lvValue = entry.getValue();

          if (lvValue > lvLevel)
          {
            System.out.println("#######################################################################");
            System.out.println("#!!! Warning at file \"" + pmPath + "\" at line: " + lvLineIdx);
            System.out.println("#Not closed Connection");
            System.out.println("#######################################################################");
            lvConNames.remove(entry.getKey());
          }
        }

        Map<String, Integer> lvPsNamesTmp = new HashMap<String, Integer>(lvPsNames);
        for (Entry<String, Integer> entry : lvPsNamesTmp.entrySet())
        {
          Integer lvValue = entry.getValue();

          if (lvValue > lvLevel)
          {
            System.out.println("#######################################################################");
            System.out.println("#!!! Warning at file \"" + pmPath + "\" at line: " + lvLineIdx);
            System.out.println("#Not closed PreparedStatement");
            System.out.println("#######################################################################");

            lvPsNamesTmp.remove(entry.getKey());
          }
        }

        Map<String, Integer> lvRsNamesTmp = new HashMap<String, Integer>(lvRsNames);
        for (Entry<String, Integer> entry : lvRsNamesTmp.entrySet())
        {
          Integer lvValue = entry.getValue();

          if (lvValue > lvLevel)
          {
            System.out.println("#######################################################################");
            System.out.println("#!!! Warning at file \"" + pmPath + "\" at line: " + lvLineIdx);
            System.out.println("#Not closed ResultSet");
            System.out.println("#######################################################################");

            lvRsNames.remove(entry.getKey());
          }
        }

        ++lvLineIdx;
      }

    }
    catch (Exception e)
    {
      // System.out.println("#Parsing error at file: " + pmPath);
      // e.printStackTrace();
    }
  }

  private static void checkIfConectionGetter(List<Integer> pmTryBlocks, String pmLine, int pmLineIndex, Path pmPath)
  {
    if (pmLine.indexOf("DbUtils.getConnection") != -1 && pmTryBlocks.isEmpty())
    {
      System.out.println("#######################################################################");
      System.out.println("#!!! Warning at file \"" + pmPath + "\" at line: " + pmLineIndex);
      System.out.println("#!!! Connection initialize outisde of try block");
      System.out.println("#######################################################################");
    }
  }

  private static void closeTryBlocks(List<Integer> pmTryBlocks, int pmLevel)
  {
    int lvIndexOf = pmTryBlocks.indexOf(new Integer(pmLevel));

    if (lvIndexOf != -1)
    {
      pmTryBlocks.remove(lvIndexOf);
    }
  }

  private static int checkLevel(String pmLine, int pmCurrentLevel)
  {
    // check level
    int lvIndexOfStart = -1;
    int lvIndexOfEnd = -1;
    int lvLevel = pmCurrentLevel;

    String lvLineTmp = pmLine;

    do
    {
      if (lvLineTmp.indexOf("}") != -1)
      {
        lvLineTmp = lvLineTmp.replaceFirst("\\}","");
        lvLevel--;
      }
      else if (lvLineTmp.indexOf("{") != -1)
      {
        lvLineTmp = lvLineTmp.replaceFirst("\\{","");
        lvLevel++;
      }
      else
      {
        break;
      }

    }
    while (true);

    return lvLevel;
  }

}