Package cn.bran.japid.util

Source Code of cn.bran.japid.util.DirUtil

package cn.bran.japid.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.bran.japid.classmeta.AbstractTemplateClassMetaData;
import cn.bran.japid.template.JapidRenderer;


public class DirUtil {
  public static final String OF = ", ";
  public static final String LINE_MARKER = "// line ";
  static final String DOT_SUB = "_d_";

  private static final String[] ALL_EXTS = new String[] { ".java", ".html", ".js", ".txt", ".css", ".json", ".xml" };
  private static final String[] TEMPLATE_EXTS = new String[]{".html", ".js", ".txt", ".css", ".xml", ".json"};
 
  public static Set<File> findOrphanJava(File src, File target) {
    if (target == null)
      target = src;
    String[] allSrc = getAllFileNames(src, ALL_EXTS);
    Set<String> javas = new HashSet<String>();
    Set<String> srcFiles = new HashSet<String>();

    for (String s : allSrc) {
      if (s.endsWith(".java")) {
        javas.add(s);
      } else /*if (s.endsWith(".html"))*/ {
        srcFiles.add(mapSrcToJava(s));
      }
    }

    javas.removeAll(srcFiles);
    Set<File> re = new HashSet<File>();
    for (String j : javas) {
      re.add(new File(j));
    }
    return re;
  }

 
  /**
   *
   */
  public static String[] getAllFileNames(File dir, String[] exts) {
    List<String> files = new ArrayList<String>();
    getAllFileNames("", dir, files, exts);
    String[] ret = new String[files.size()];
    return files.toArray(ret);
  }
 
  public static List<String> getAllTemplateHtmlFiles(File dir) {
    List<String> files = new ArrayList<String>();
    getAllFileNames("", dir, files, new String[] {".html"});
    keepJapidFiles(files);
    return files;
  }


  private static void keepJapidFiles(List<String> files) {
    for (Iterator<String> it = files.iterator(); it.hasNext();) {
      if (!it.next().startsWith(JAPIDVIEWS_ROOT)) {
        it.remove();
      }
    }
  }
 
  public static List<String> getAllTemplateFiles(File dir) {
    List<String> files = new ArrayList<String>();
    getAllFileNames("", dir, files, TEMPLATE_EXTS);
    keepJapidFiles(files);
    return files;
  }
 
  public static List<String> getAllTemplateFilesJavaFiles(File dir) {
    List<String> files = new ArrayList<String>();
    getAllFileNames("", dir, files, ALL_EXTS);
    keepJapidFiles(files);
    return files;
  }
 
 

  /**
   * collect all files with one of the extensions from the directory.
   * @param dir
   * @param exts
   * @param fs
   * @return the files match. Note the files path starts with the source dir.
   */
  public static Set<File> getAllFiles(File dir, String[] exts, Set<File> fs) {
    Set<File> scanFiles = scanFiles(dir, exts, fs);
    return scanFiles;
  }

  /**
   * @param dir
   * @param exts
   * @param fs
   * @return
   */
  private static Set<File> scanFiles(File dir, String[] exts, Set<File> fs) {
    File[] flist = dir.listFiles();
    for (File f : flist) {
      if (f.isDirectory())
        getAllFiles(f, exts, fs);
      else {
        if (match(f, exts))
          fs.add(f);
      }
    }
    return fs;
  }
 
  private static void getAllFileNames(final String leadingPath, final File dir, final List<String> files, final String[] exts) {
    if (!dir.exists())
      return;
//      throw new RuntimeException("directory exists? " +  dir.getPath());
   
    File[] flist = dir.listFiles();
    for (File f : flist) {
      if (f.isDirectory())
        getAllFileNames(leadingPath + f.getName() + File.separatorChar, f, files, exts);
      else {
        if (match(f, exts))
          files.add(leadingPath + f.getName());
      }
    }
  }

  static boolean match(File f, String[] exts) {
    for (String ext : exts) {
      if (f.getName().endsWith(ext))
        if (fileNameIsValidClassName(f))
          return true;
    }
    return false;
  }

//  private static boolean firstTimeDetectingChanges = true;
 
  static private Set<File> versionCheckedDirs  = new HashSet<File>();
 
  public static List<File> findChangedSrcFiles(File srcDir) {
//    if (target == null)
//      target = src;
//    String srcPath = src.getPath();
    Set<File> allSrc  = new HashSet<File>();
    allSrc = getAllFiles(srcDir, ALL_EXTS, allSrc);
   
    // <name, last modified time>
    Map<String, Long> javaFiles = new HashMap<String, Long>();
    Map<String, Long> scriptFiles = new HashMap<String, Long>();
   
    long now = System.currentTimeMillis();
    boolean hasFutureTimestamp = false;
    for (File f : allSrc) {
      String path = f.getPath();
      long modi = f.lastModified();
//      System.out.println("file: " + path + ":" + modi);
      if (path.endsWith(".java")) {
        if (modi > now) {
          // for some reason(e.g., copies from other file system), the last modified time is in the future
          // let's reset it.
          hasFutureTimestamp = true;
          f.setLastModified(now - 1);
        }
        javaFiles.put(path, modi);
      } else  {
        // validate file name to filter out dubious files such as temporary files
        if (fileNameIsValidClassName(f)) {
          if (modi > now) {
            // for some reason(e.g., copies from other file system), the last modified time is in the future
            // let's reset it.
            hasFutureTimestamp = true;
            f.setLastModified(now);
          }
          scriptFiles.put(path, modi);
        }
      }
    }

    if (hasFutureTimestamp) {
      JapidFlags.warn("Some of the Japid files have a timestamp in the future. It could have been caused by out-of-synch system time.");
    }
   
    List<File> changedScripts = new ArrayList<File>();
   
    boolean japidVersionChecked = versionCheckedDirs.contains(srcDir);
   
    for (String script : scriptFiles.keySet()) {
      String javaFileName = mapSrcToJava(script);
      File javaFile = new File(javaFileName);
      Long javaTimestamp = javaFiles.get(javaFileName);
     
      if (javaTimestamp == null) {
        // how can this happen?
//        javaFile.delete();
        changedScripts.add(new File(script));
      }
      else {
        Long srcStamp = scriptFiles.get(script);
        if (srcStamp.compareTo(javaTimestamp) > 0) {
//          javaFile.delete();
          changedScripts.add(new File(script));
        }
        else {
//          if (firstTimeDetectingChanges) {
          if (!japidVersionChecked) {
            // check the japid version that the java code was generated by
            if (javaFile.exists()) {
              String firstLine = JapidRenderer.readFirstLine(javaFile);
              if (firstLine.startsWith(AbstractTemplateClassMetaData.VERSION_HEADER)) {
                firstLine = firstLine.substring(AbstractTemplateClassMetaData.VERSION_HEADER.length()).trim();
                if (!JapidRenderer.VERSION.equals(firstLine)) {
                  JapidFlags.debug("japid version mismatch. to refresh " + javaFileName);
//                  javaFile.delete();
                  changedScripts.add(new File(script));
                }
              }
              else {
                JapidFlags.debug("japid version mismatch. to refresh " + javaFileName);
//                javaFile.delete();
                changedScripts.add(new File(script));
              }
            }
          }
        }
      }
    }
    versionCheckedDirs.add(srcDir);
//    firstTimeDetectingChanges = false;
    return changedScripts;
  }

  /**
   * @author Bing Ran (bing.ran@hotmail.com)
   * @param f
   * @return
   */
  private static boolean fileNameIsValidClassName(File f) {
    String fname = f.getName();
    if (fname.startsWith("."))
      return false;
    fname = fname.substring(0, fname.lastIndexOf(".")).replace('.', '_');
    return isClassname(fname);
  }

  /**
   * map template source file name to the generated java file name
   * @param k
   * @return
   */
  public static String mapSrcToJava(String k) {
    if (k.endsWith(".java"))
        return k;
    if (k.endsWith(".txt")) {
      return getRoot(k) + "_txt" + ".java";
    }
    else if (k.endsWith(".xml")) {
      return getRoot(k) + "_xml" + ".java";
    }
    else if (k.endsWith(".json")) {
      return getRoot(k) + "_json" + ".java";
    }
    else if (k.endsWith(".css")) {
      return getRoot(k) + "_css" + ".java";
    }
    else if (k.endsWith(".js")) {
      return getRoot(k) + "_js" + ".java";
    }
    else { // including html
      return getRoot(k) + ".java";
    }
  }
 
  /**
   *
   * map java source file name to the template file name
   * @param k
   * @return
   */
  public static String mapJavaToSrc(String k) {
    return rawConvert(k);//.replaceAll(DOT_SUB, ".");
  }

  private static String rawConvert(String k) {
    if (k.endsWith(".java"))
      k = k.substring(0, k.lastIndexOf(".java"));
   
    if (k.endsWith("_txt")) {
      return k.substring(0, k.lastIndexOf("_txt")) + ".txt";
    }
    else if (k.endsWith("_xml")) {
      return k.substring(0, k.lastIndexOf("_xml")) + ".xml";
    }
    else if (k.endsWith("_json")) {
      return k.substring(0, k.lastIndexOf("_json")) + ".json";
    }
    else if (k.endsWith("_css")) {
      return k.substring(0, k.lastIndexOf("_css")) + ".css";
    }
    else if (k.endsWith("_js")) {
      return k.substring(0, k.lastIndexOf("_js")) + ".js";
    }
    else { // including html
      return  k + ".html";
    }
  }
  private static String getRoot(String k) {
    for (String ext : TEMPLATE_EXTS) {
      if (k.endsWith(ext)) {
        String sub = k.substring(0, k.lastIndexOf(ext));
//        String first = "";
//        if (sub.startsWith(".")) { // keep the first dot, which means current dir
//          first = ".";
//          sub = sub.substring(1);
//        }
//        return first + sub.replaceAll("\\.", DOT_SUB);
        return sub;
      }
    }
    return k;
  }

  public static void writeStringToFile(File file, String content) throws IOException {
    Writer fw = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
    BufferedWriter bw = new BufferedWriter(fw);
    bw.append(content);
    bw.close();
  }

  public static void touch(File newer) throws IOException {
    writeStringToFile(newer, "");
  }

  public static boolean containsTemplateFiles(String root, String dirName) {
    String sep = File.separator;
    String japidViews = root + sep + JAPIDVIEWS_ROOT + sep;
    String dir = japidViews + dirName;
    return containsTemplatesInDir(dir);
  }

  public static boolean containsTemplatesInDir(String dirName) {
    File dir = new File(dirName);
   
    if (dir.exists()) {
      String[] temps = getAllFileNames(dir, TEMPLATE_EXTS);
      if (temps.length > 0)
        return true;
      else
        return false;
    }
    else
      return false;
  }

  public static boolean hasTags(String root) {
    String dirName = DirUtil.TAGSDIR;
    return containsTemplateFiles(root, dirName);
  }

  public static boolean hasJavaTags(String root) {
    String dirName = DirUtil.JAVATAGS;
    return containsTemplateFiles(root, dirName);
  }

  public static boolean hasLayouts(String root) {
    String dirName = DirUtil.LAYOUTDIR;
    return containsTemplateFiles(root, dirName);
  }
 
   public static boolean isClassname( String classname ) {
        if (classname == null || classname.length() ==0) return false;

          CharacterIterator iter = new StringCharacterIterator(classname);
          // Check first character (there should at least be one character for each part) ...
          char c = iter.first();
          if (c == CharacterIterator.DONE) return false;
          if (!Character.isJavaIdentifierStart(c) && !Character.isIdentifierIgnorable(c)) return false;
          c = iter.next();
          // Check the remaining characters, if there are any ...
          while (c != CharacterIterator.DONE) {
              if (!Character.isJavaIdentifierPart(c) && !Character.isIdentifierIgnorable(c)) return false;
              c = iter.next();
          }
        return true;
    }

  public static final String JAVATAGS = "_javatags";
  public static final String LAYOUTDIR = "_layouts";
  public static final String TAGSDIR = "_tags";
  public static final String JAPIDVIEWS_ROOT = "japidviews";
  public static List<String> scanJavaTags(String root) {
    String sep = File.separator;
    String japidViews = root + sep + JAPIDVIEWS_ROOT + sep;
    File javatags = new File(japidViews + JAVATAGS);
    if (!javatags.exists()) {
      boolean mkdirs = javatags.mkdirs();
      assert mkdirs == true;
      JapidFlags.info("created: " + japidViews + JAVATAGS);
    }
 
    File[] javafiles = javatags.listFiles(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        if (name.endsWith(".java"))
          return true;
        return false;
      }
    });
   
    List<String> files = new ArrayList<String>();
    for (File f : javafiles) {
      String fname = f.getName();
      files.add(JAPIDVIEWS_ROOT + "." + JAVATAGS + "." + fname.substring(0, fname.lastIndexOf(".java")));
    }
    return files;
  }

  /**
   * @author Bing Ran (bing.ran@hotmail.com)
   * @param f the java file
   * @return the original template file
   */
  public static File mapJavatoSrc(File f) {
    File parent = f.getParentFile();
    String fname = mapJavaToSrc(f.getName());
    return new File(parent, fname);
  }
 
  /**
   *
   * @author Bing Ran (bing.ran@hotmail.com)
   * @param sourceCode
   * @param lineNum 1-based line number in Java file
   * @return 1-based line number in the original source template
   */
  public static int mapJavaLineToSrcLine(String sourceCode, int lineNum) {
    String[] codeLines = sourceCode.split("\n");
    String line = codeLines[lineNum - 1];
 
    int lineMarker = line.lastIndexOf(LINE_MARKER);
    if (lineMarker < 1) {
      return -1;
    }
    String linenum = line.substring(lineMarker + LINE_MARKER.length()).trim();
    int indexOf = linenum.indexOf(OF);
    if (indexOf > 0) {
      linenum = linenum.substring(0, indexOf);
    }
    return Integer.parseInt(linenum);
  }


  /**
     * create the basic layout: app/japidviews/_javatags app/japidviews/_layouts
     * app/japidviews/_tags
     *
     * then create a dir for each controller. //TODO
     *
     * @throws IOException
     *
     */
    public static List<File> mkdir(String root) throws IOException {
      String sep = File.separator;
      String japidViews = root + sep + JAPIDVIEWS_ROOT + sep;
      File javatags = new File(japidViews + JAVATAGS);
      if (!javatags.exists()) {
        boolean mkdirs = javatags.mkdirs();
        assert mkdirs;
        JapidFlags.info("created: " + japidViews + JAVATAGS);
      }
 
  //    File webutil = new File(javatags, "JapidWebUtil.java");
  //    if (!webutil.exists()) {
  //      DirUtil.writeStringToFile(webutil, JapidWebUtil);
  //      JapidFlags.log("created JapidWebUtil.java.");
  //    }
      // add the place-holder for utility class for use in templates
 
      File layouts = new File(japidViews + LAYOUTDIR);
      if (!layouts.exists()) {
        boolean mkdirs = layouts.mkdirs();
        assert mkdirs;
        JapidFlags.info("created: " + japidViews + LAYOUTDIR);
      }
 
      File tags = new File(japidViews + TAGSDIR);
      if (!tags.exists()) {
        boolean mkdirs = tags.mkdirs();
        assert mkdirs;
        JapidFlags.info("created: " + japidViews + TAGSDIR);
      }
     
      // email notifiers
      File notifiers = new File(japidViews + "_notifiers");
      if (!notifiers.exists()) {
        boolean mkdirs = notifiers.mkdirs();
        assert mkdirs;
        JapidFlags.info("created: " + japidViews + "_notifiers");
      }
     
     
      File[] dirs = new File[] { javatags, layouts, tags };
      List<File> res = new ArrayList<File>();
      res.addAll(Arrays.asList(dirs));
 
      // create dirs for controllers
 
  //    JapidFlags.log("JapidCommands: check default template packages for controllers.");
      try {
        String controllerPath = root + sep + "controllers";
        File controllerPathFile = new File(controllerPath);
        if (controllerPathFile.exists()) {
          String[] controllers = DirUtil.getAllJavaFilesInDir(controllerPathFile);
          for (String f : controllers) {
            String cp = japidViews + f;
            File ff = new File(cp);
            if (!ff.exists()) {
              boolean mkdirs = ff.mkdirs();
              assert mkdirs == true;
              res.add(ff);
              JapidFlags.info("created: " + cp);
            }
          }
        }
      } catch (Exception e) {
        JapidFlags.error(e.toString());
      }
 
  //    JapidFlags.log("JapidCommands:  check default template packages for email notifiers.");
      try {
        String notifiersDir = root + sep + "notifiers";
        File notifiersDirFile = new File(notifiersDir);
        if (!notifiersDirFile.exists()) {
          if (notifiersDirFile.mkdir()) {
            JapidFlags.info("created the email notifiers directory. ");
          }
          else {
            JapidFlags.info("email notifiers directory did not exist and could not be created for unknow reason. ");
          }
        }
       
        String[] controllers = DirUtil.getAllJavaFilesInDir(notifiersDirFile);
        for (String f : controllers) {
          // note: we keep the notifiers dir to differentiate those from the controller
          // however this means we cannot have a controller with package like "controllers.notifiers"
          // so we now use "_notifiers"
          String cp = japidViews + "_notifiers" + sep + f;
          File ff = new File(cp);
          if (!ff.exists()) {
            boolean mkdirs = ff.mkdirs();
            assert mkdirs == true;
            res.add(ff);
            JapidFlags.info("created: " + cp);
          }
        }
      } catch (Exception e) {
        JapidFlags.error(e.toString());
      }
      return res;
    }


  /**
   * get all the java files in a dir with the "java" removed
   *
   * @return
   */
  public static String[] getAllJavaFilesInDir(File root) {
    // from source files only
    String[] allFiles = getAllFileNames(root, new String[] { ".java" });
    for (int i=0; i< allFiles.length; i++) {
      allFiles[i] = allFiles[i].replace(".java", "");
    }
    return allFiles;
  }

  /**
   * a utility method.
   *
   * @param srcDir
   * @param cf
   * @throws IOException
   */
  public static String getRelativePath(File child, File parent) throws IOException {
    String curPath = parent.getCanonicalPath();
    String childPath = child.getCanonicalPath();
    assert (childPath.startsWith(curPath));
    String srcRelative = childPath.substring(curPath.length());
    if (srcRelative.startsWith(File.separator)) {
      srcRelative = srcRelative.substring(File.separator.length());
    }
    return srcRelative;
  }

 
  // this method is entirely safe ???
  static public String readFileAsString(String filePath) throws Exception {
    byte[] buffer = new byte[(int) new File(filePath).length()];
    BufferedInputStream f = new BufferedInputStream(new FileInputStream(filePath));
    f.read(buffer);
    f.close();
    return new String(buffer, "UTF-8");
  }


  public static File writeToFile(String jsrc, String realTargetFile) throws FileNotFoundException, IOException,
      UnsupportedEncodingException {
    File f = new File(realTargetFile);
    if (!f.exists()) {
      String parent = f.getParent();
      new File(parent).mkdirs();
    }
    BufferedOutputStream bf = new BufferedOutputStream(new FileOutputStream(f));
    bf.write(jsrc.getBytes("UTF-8"));
    bf.close();
    return f;
  }

}
TOP

Related Classes of cn.bran.japid.util.DirUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.