View Javadoc

1   package com.tapina.robe.runtime;
2   
3   import com.tapina.robe.swi.OS;
4   
5   import java.io.File;
6   import java.util.regex.Matcher;
7   import java.util.regex.Pattern;
8   
9   /***
10   * Convert between Acorn and native-style paths.
11   * Assumed Unix native paths for now.
12   */
13  public final class FilenameUtils {
14      public static String acornToNative(String fsp) {
15          if (fsp.equals("$")) {
16              return String.valueOf(File.separatorChar);
17          }
18          final int pathPrefixLength = fsp.indexOf(':');
19          if (pathPrefixLength > 0) {
20              final String pathName = fsp.substring(0, pathPrefixLength);
21              final String pathRelative = fsp.substring(pathPrefixLength + 1);
22              final String result = expandPath(pathName, pathRelative);
23              if (result != null) {
24                  return result;
25              }
26              // Otherwise continue with just the relative portion of the path.
27              fsp = pathRelative;
28          }
29          fsp = substituteVariables(fsp);
30          StringBuffer out = new StringBuffer(fsp.length() + 1);
31          if (fsp.startsWith("$.")) {
32              out.append(File.separatorChar);
33              fsp = fsp.substring(2);
34          }
35          int space = fsp.indexOf(' ');
36          if (space != -1) {
37              fsp = fsp.substring(0, space);
38          }
39          // Acorn '/' need to become '.'; acorn '.' need to become the native separator
40          out.append(fsp.replace('/', '*').replace('.', File.separatorChar).replace('*', '.'));
41          return out.toString();
42      }
43  
44      private static String substituteVariables(String fsp) {
45          Pattern variable = Pattern.compile("<.*>");
46          Matcher matcher = variable.matcher(fsp);
47          StringBuffer sb = new StringBuffer();
48          while (matcher.find()) {
49              String varName = matcher.group();
50              varName = varName.substring(1, varName.length() - 1);
51              final String varValue = OS.getInstance().readVarVal(varName);
52              // The replaceAll() below makes sure that $'s are quoted when used in the replacement string
53              matcher.appendReplacement(sb, varValue.replaceAll("//$", "//////$"));
54          }
55          matcher.appendTail(sb);
56          fsp = sb.toString();
57          return fsp;
58      }
59  
60      private static String expandPath(final String pathName, String pathRelative) {
61          if (pathRelative.endsWith(".")) {
62              // This is a directory spec, so trim the final "."
63              pathRelative = pathRelative.substring(0, pathRelative.length() - 1);
64          }
65          // Expand the path and recurse
66          final String[] pathValues = OS.getInstance().readVarVal(pathName + "$Path").split(",");
67          return findNative(pathValues, pathRelative);
68      }
69  
70      private static String findNative(final String[] pathValues, String pathRelative) {
71          for (int i = 0; i < pathValues.length; i++) {
72              final String pathValue = pathValues[i];
73              // This forms a mutually recursive function with acornToNative(), as path values may themselves be paths!
74              final String nativeFsp = acornToNative(pathValue.concat(pathRelative));
75              if (new File(nativeFsp).exists()) {
76                  return nativeFsp;
77              }
78          }
79          return null;
80      }
81  
82      public static String nativeToAcorn(String fsp) {
83          StringBuffer out = new StringBuffer(fsp.length() + 1);
84          if (fsp.charAt(0) == File.separatorChar) {
85              out.append("$.");
86              fsp = fsp.substring(1);
87          }
88          // Native '.' need to become '/'; native separator need to become '.'
89          out.append(fsp.replace(File.separatorChar, '*').replace('.', '/').replace('*', '.'));
90          return out.toString();
91      }
92  }