在上面一篇文章 中我们提到了目录结构检查器,现在我们就做下一步动作了,用于检查放置在这些目录下的文件是否有合法的扩展名。

 

需求:

假定我们已经有了一个合法的目录结构,我们必须检查放置这些目录下文件的扩展名。

(1) js目录下的文件必须以.js扩展名结尾,css目录下的文件必须以.css扩展名结尾,p_w_picpath目录下的文件必须以jpg,png,gif等等结尾

(2)这些扩展名都是写在.properties文件中而且是可配置的

(3)这些扩展名都是忽略大小写的,比如a.PNG和a.png都是可以的。

(4)根目录固定,css/js/p_w_picpath,但是他们可以有任意层次结构的子目录,只要最终的文件扩展名合法就可以,比如css子目录下可以有 mycss子目录,然后mycss子目录下在有abc.css,这样是合法的。

 

实现:

 

 
  1. /** 
  2.  
  3. * This class will be responsible for checking the file/folder extension setting 
  4.  
  5. * based on the valid file extension list 
  6.  
  7. * 
  8.  
  9.  * @author cwang58 
  10.  
  11. * @created date: Aug 3, 2012 
  12.  
  13. */ 
  14.  
  15. public class FileExtensionChecker implements IFileExtensionChecker { 
  16.  
  17.   
  18.  
  19.          private final Logger logger = LoggerFactory 
  20.  
  21.                           .getLogger(FileExtensionChecker.class); 
  22.  
  23.   
  24.  
  25.          private static ConfigureUtility configureUtility; 
  26.  
  27.   
  28.  
  29.          private List<String> validHtmlFileExtensionList = new ArrayList<String>(); 
  30.  
  31.          private List<String> validJsFileExtensionList = new ArrayList<String>(); 
  32.  
  33.          private List<String> validCssFileExtensionList = new ArrayList<String>(); 
  34.  
  35.          private List<String> validImageFileExtensionList = new ArrayList<String>(); 
  36.  
  37.   
  38.  
  39.          public FileExtensionChecker() throws Exception { 
  40.  
  41.   
  42.  
  43.                  configureUtility = ConfigureUtility.getInstance(); 
  44.  
  45.   
  46.  
  47.                  try { 
  48.  
  49.   
  50.  
  51.                           setFileExtension(validHtmlFileExtensionList, 
  52.  
  53.                                             configureUtility.getProperty(VALID_HTML_FILE_EXTENSION)); 
  54.  
  55.                           setFileExtension(validJsFileExtensionList, 
  56.  
  57.                                             configureUtility.getProperty(VALID_JS_FILE_EXTENSION)); 
  58.  
  59.                           setFileExtension(validCssFileExtensionList, 
  60.  
  61.                                             configureUtility.getProperty(VALID_CSS_FILE_EXTENSION)); 
  62.  
  63.                           setFileExtension(validImageFileExtensionList, 
  64.  
  65.                                             configureUtility.getProperty(VALID_IMAGE_FILE_EXTENSION)); 
  66.  
  67.   
  68.  
  69.                  } catch (Exception ex) { 
  70.  
  71.   
  72.  
  73.                           if (logger.isErrorEnabled()) { 
  74.  
  75.                                    logger.error("fail when parsing the file extension configuration file"); 
  76.  
  77.   
  78.  
  79.                           } 
  80.  
  81.   
  82.  
  83.                           throw new ConfigureSystemException(CONFIGURATION_ERROR, ex); 
  84.  
  85.                  } 
  86.  
  87.   
  88.  
  89.          } 
  90.  
  91.   
  92.  
  93.          /** 
  94.  
  95.          * to check whether the files has correct extensions ,the logic is as 
  96.  
  97.          * follows: 
  98.  
  99.          * 
  100.  
  101.           * (1) check whether the target folderPath is a folder (2) Invoke the 
  102.  
  103.          * FolderStructureCheck's checkFolderStructure method to see whether this 
  104.  
  105.          * folder has the correct folder structure (3) check root directory to see 
  106.  
  107.          * whether there are only html files (4) traverse all the top sub folder 
  108.  
  109.          * {css/js/p_w_picpath} ,go to the leaf nodes ,to see whether the file extension 
  110.  
  111.          * matches 
  112.  
  113.          * 
  114.  
  115.           * Actually, all the major task of this method is to pass parameter to 
  116.  
  117.          * checkFileExtensionWithPath method 
  118.  
  119.          * 
  120.  
  121.           * @param pathString 
  122.  
  123.          *            the string of the folder path 
  124.  
  125.          * @throws Exception 
  126.  
  127.          */ 
  128.  
  129.          public void checkFileExtensions(String pathString) throws Exception { 
  130.  
  131.                  // TODO Auto-generated method stub 
  132.  
  133.   
  134.  
  135.                  File path = new File(pathString); 
  136.  
  137.   
  138.  
  139.                  // if path doesn't exist ,return false 
  140.  
  141.                  if (path == null || !path.exists()) { 
  142.  
  143.   
  144.  
  145.                           if (logger.isErrorEnabled()) { 
  146.  
  147.                                    logger.error("the path doesn't exist"); 
  148.  
  149.                           } 
  150.  
  151.                           throw new ParameterNullException(FILE_EXTN_ERROR); 
  152.  
  153.                  } 
  154.  
  155.   
  156.  
  157.                  // if path is a file ,that's not what we expected ,we just expect that 
  158.  
  159.                  // it is a folder 
  160.  
  161.                  if (path.isFile()) { 
  162.  
  163.   
  164.  
  165.                           if (logger.isErrorEnabled()) { 
  166.  
  167.                                    logger.error("the path should not be a file"); 
  168.  
  169.                           } 
  170.  
  171.                           throw new ParameterInvalidException(FILE_EXTN_ERROR); 
  172.  
  173.                  } 
  174.  
  175.   
  176.  
  177.                  // now the path is a directory, we check the folder structure 
  178.  
  179.                  FolderStructureChecker fsc = new FolderStructureChecker(); 
  180.  
  181.                  try { 
  182.  
  183.                           fsc.checkFolderStructure(pathString); 
  184.  
  185.                  } catch (Exception ex) { 
  186.  
  187.   
  188.  
  189.                           if (logger.isErrorEnabled()) { 
  190.  
  191.                                    logger.error("this path don't have valid folder structure ,skip the file extension check"); 
  192.  
  193.                           } 
  194.  
  195.                           throw new InvalidFileExtensionException(FILE_EXTN_ERROR, ex); 
  196.  
  197.                  } 
  198.  
  199.   
  200.  
  201.                  // now the path has valid folder structure,we can check it one by one 
  202.  
  203.   
  204.  
  205.                  boolean checkResult = true
  206.  
  207.   
  208.  
  209.                  for (File file : path.listFiles()) { 
  210.  
  211.   
  212.  
  213.                           // if the file is a file ,since only html file is allowed here ,so 
  214.  
  215.                           // we use html rule to check it 
  216.  
  217.                           if (file.isFile()) 
  218.  
  219.                                    checkResult = checkResult 
  220.  
  221.                                                     && checkFileExtensionsWithPath(file, 
  222.  
  223.                                                                       getValidHtmlFileExtensionList()); 
  224.  
  225.   
  226.  
  227.                           // if the file is a directory, since only supports "css" 
  228.  
  229.                           // "js","p_w_picpath" ,so we check one by one 
  230.  
  231.                           else { 
  232.  
  233.   
  234.  
  235.                                    if (file.getName().trim().equals(fsc.getCssFolderName().trim())) 
  236.  
  237.                                             checkResult = checkResult 
  238.  
  239.                                                              && checkFileExtensionsWithPath(file, 
  240.  
  241.                                                                                getValidCssFileExtensionList()); 
  242.  
  243.                                    else if (file.getName().trim() 
  244.  
  245.                                                     .equals(fsc.getJavascriptFolderName().trim())) 
  246.  
  247.                                             checkResult = checkResult 
  248.  
  249.                                                              && checkFileExtensionsWithPath(file, 
  250.  
  251.                                                                                getValidJsFileExtensionList()); 
  252.  
  253.                                    else if (file.getName().trim() 
  254.  
  255.                                                     .equals(fsc.getImageFolderName().trim())) 
  256.  
  257.                                             checkResult = checkResult 
  258.  
  259.                                                              && checkFileExtensionsWithPath(file, 
  260.  
  261.                                                                                getValidImageFileExtensionList()); 
  262.  
  263.                           } 
  264.  
  265.                  } 
  266.  
  267.   
  268.  
  269.                  if (checkResult == false) { 
  270.  
  271.                           throw new InvalidFileExtensionException(FILE_EXTN_ERROR); 
  272.  
  273.                  } 
  274.  
  275.   
  276.  
  277.          } 
  278.  
  279.   
  280.  
  281.          /** 
  282.  
  283.          * this method will recursively check the subfolders util it reaches the end 
  284.  
  285.          * file the recursive rule is as follows: 
  286.  
  287.          * 
  288.  
  289.           * If the path is file ,then check the file's extension with the valid file 
  290.  
  291.          * extension list If the path is a folder ,then recursively traverse all the 
  292.  
  293.          * sub files inside this folder 
  294.  
  295.          * 
  296.  
  297.           * @param path 
  298.  
  299.          *            the path of the folder 
  300.  
  301.          * @param fileExtensionList 
  302.  
  303.          *            the list of all valid file extensions 
  304.  
  305.          * @return whether the check is correct or has invalid file extensions 
  306.  
  307.          */ 
  308.  
  309.          public boolean checkFileExtensionsWithPath(File path, 
  310.  
  311.                           List<String> fileExtensionList) { 
  312.  
  313.   
  314.  
  315.                  // if the fileExtensionList is null ,which means no file extension can 
  316.  
  317.                  // be checked ,returns false 
  318.  
  319.                  if (fileExtensionList == null || fileExtensionList.size() == 0) { 
  320.  
  321.   
  322.  
  323.                           if (logger.isErrorEnabled()) { 
  324.  
  325.                                    logger.error("the file extension check list can't be null"); 
  326.  
  327.                           } 
  328.  
  329.                           return false
  330.  
  331.                  } 
  332.  
  333.   
  334.  
  335.                  // if path doesn't exist ,return false 
  336.  
  337.                  if (path == null || !path.exists()) { 
  338.  
  339.   
  340.  
  341.                           if (logger.isErrorEnabled()) { 
  342.  
  343.                                    logger.error("the path doesn't exist"); 
  344.  
  345.                           } 
  346.  
  347.                           return false
  348.  
  349.                  } 
  350.  
  351.   
  352.  
  353.                  // if the path is a file , 
  354.  
  355.                  // then check whether this file's file name matches the 
  356.  
  357.                  // fileExtensionList provided by the second param 
  358.  
  359.                  if (path.isFile()) { 
  360.  
  361.   
  362.  
  363.                           if (logger.isDebugEnabled()) { 
  364.  
  365.                                    logger.debug("this path is a file"); 
  366.  
  367.                           } 
  368.  
  369.   
  370.  
  371.                           // retrieve the filename 
  372.  
  373.                           String fileName = path.getName(); 
  374.  
  375.                           System.out.println("fileName: " + fileName); 
  376.  
  377.   
  378.  
  379.                           // retrieve the file extension 
  380.  
  381.   
  382.  
  383.                           // if fileName don't have dot(.), which means this file has no file 
  384.  
  385.                           // extension 
  386.  
  387.                           if (fileName.indexOf(DOT) == -1) { 
  388.  
  389.   
  390.  
  391.                                    if (logger.isErrorEnabled()) { 
  392.  
  393.                                             logger.error("This file has no extension"); 
  394.  
  395.                                    } 
  396.  
  397.                                    return false
  398.  
  399.                           } 
  400.  
  401.   
  402.  
  403.                           // otherwise ,get the file extension from the file name 
  404.  
  405.                           String fileExtension = fileName.substring( 
  406.  
  407.                                             fileName.indexOf(".") + 1, fileName.length()); 
  408.  
  409.   
  410.  
  411.                           if (fileExtensionList.contains(fileExtension.toLowerCase())) { 
  412.  
  413.   
  414.  
  415.                                    if (logger.isDebugEnabled()) { 
  416.  
  417.                                             logger.debug("This file  matches file extension list"); 
  418.  
  419.                                    } 
  420.  
  421.                                    return true
  422.  
  423.                           } else { 
  424.  
  425.   
  426.  
  427.                                    if (logger.isErrorEnabled()) { 
  428.  
  429.                                             logger.error("This file doesn't match the file extension"); 
  430.  
  431.                                    } 
  432.  
  433.                                    return false
  434.  
  435.                           } 
  436.  
  437.                  } 
  438.  
  439.   
  440.  
  441.                  // other wise, this file is a folder ,then traverse all the sub folders 
  442.  
  443.                  // and files in it,recursively 
  444.  
  445.                  else { 
  446.  
  447.   
  448.  
  449.                           if (logger.isDebugEnabled()) { 
  450.  
  451.                                    logger.debug("this path is a folder"); 
  452.  
  453.                           } 
  454.  
  455.   
  456.  
  457.                           boolean result = true
  458.  
  459.                           for (File file : path.listFiles()) { 
  460.  
  461.                                    result = result 
  462.  
  463.                                                     && checkFileExtensionsWithPath(file, fileExtensionList); 
  464.  
  465.                           } 
  466.  
  467.   
  468.  
  469.                           return result; 
  470.  
  471.                  } 
  472.  
  473.          } 
  474.  
  475.   
  476.  
  477.          /** 
  478.  
  479.          * this method can convert the comma seperated file extension string to a 
  480.  
  481.          * List object 
  482.  
  483.          * 
  484.  
  485.           * @param fileExtensionList 
  486.  
  487.          *            the list which stores all the file extensions 
  488.  
  489.          * @param fileExtensionCommaSeparated 
  490.  
  491.          *            the comma separated string ,which put every file extension 
  492.  
  493.          *            into this string ,and separate by comma 
  494.  
  495.          */ 
  496.  
  497.          public void setFileExtension(List<String> fileExtensionList, 
  498.  
  499.                           String fileExtensionCommaSeparated) { 
  500.  
  501.                  String[] fileExtensions = fileExtensionCommaSeparated.split(COMMA); 
  502.  
  503.                  for (String fileExtension : fileExtensions) { 
  504.  
  505.                           fileExtensionList.add(fileExtension.trim()); 
  506.  
  507.                  } 
  508.  
  509.          } 
  510.  
  511.   
  512.  
  513.          public List<String> getValidHtmlFileExtensionList() { 
  514.  
  515.                  return validHtmlFileExtensionList; 
  516.  
  517.          } 
  518.  
  519.   
  520.  
  521.          public List<String> getValidJsFileExtensionList() { 
  522.  
  523.                  return validJsFileExtensionList; 
  524.  
  525.          } 
  526.  
  527.   
  528.  
  529.          public List<String> getValidCssFileExtensionList() { 
  530.  
  531.                  return validCssFileExtensionList; 
  532.  
  533.          } 
  534.  
  535.   
  536.  
  537.          public List<String> getValidImageFileExtensionList() { 
  538.  
  539.                  return validImageFileExtensionList; 
  540.  
  541.          } 
  542.  
  543.   
  544.  

 

这个类也很长很长,我们依次来分析:

(1)从477-509行定义了一个辅助方法叫setFileExtension,它有2个参数,第一个参数是扩展名数组,第二个参数是扩展名字符串,它的职责是吧第二个参数的以逗号","分开的扩展名字符串转为第一个参数的扩展名数组,比如说对于图像有好几种扩展名,所以第二个参数为 "jpg,png,gif,tiff",那么通过这个辅助方法,则最终存入第一个参数的扩展名字符串为 {"jpg","png","gif","tiff"}

(2)第39-89行的构造器解决了如何灵活的初始化扩展名检查器的问题。因为允许的扩展名列表都被配置在了属性文件中,所以我们用ConfigureUtility去读取这些属性文件,并且将读来的扩展名字符串用刚才提到的setFileExtension方法正确的转为扩展名数组,然后初始化。

(3)第281-第473行定义了一个递归方法checkFileExtensionsWithPath,它有2个参数,参数1为子目录,参数2为允许扩展名数组,所以它会去检查参数1的子目录下所有文件的扩展名都在参数2数组中。这是一个递归的检查。首先从319-349对入参进行了非空检查。然后第353-437行对于参数1是个文件的情况进行了检查。其中第383-399中排除了某些不含扩展名的文件,因为假定所有的文件都必须含有扩展名(当然了,UNIX系统中经常有没有扩展名的文件,但是这在我们的讨论范畴之外),第403-437行则是从参数1中提取扩展名字符串,然后去判断这个扩展名字符串是否被包含在参数2中声明的扩展名数组中。第441-473行则是对于参数1是个目录的情况进行了检查,因为是目录,所以它会列出这个目录下的所有的文件或目录,然后递归的调用checkFileExtensionsWithPath方法,直到得出结果。

(4)第93-277行的方法checkFileExtensions则是对(3)中的checkFileExtensionsWithPath进行了多次调用。因为我们知道了跟目录的直接子目录只有3个(css,js,p_w_picpath),而且我们在(2)中也从属性文件中获取并初始化了每种情况下的合法扩展名字符串数组,所以我们需要的就是构造多个检查条件,然后调用(3)的方法,最后把这些检查的结果做逻辑与运算,见235-260行,把最终元素结果最为最后的检查结果,很一目了然。