PageRenderTime 39ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Dependencies/boo/lib/antlr-2.7.5/examples/java/linkChecker/LinkChecker.java

https://github.com/w4x/boolangstudio
Java | 266 lines | 202 code | 12 blank | 52 comment | 37 complexity | dc0c827481e59d708f480c58730a7f7f MD5 | raw file
Possible License(s): GPL-2.0
  1. import java.io.*;
  2. import antlr.*;
  3. import java.util.Hashtable;
  4. class LinkChecker implements LinkListener {
  5. /** Which directory is the document in? */
  6. private String directory = "."; // default to current dir
  7. /** Which document are we to process? */
  8. private String document;
  9. /** Record which files we have seen so that we don't get into an
  10. * infinite loop and for efficiency. The absolute path is stored here
  11. * to uniquely identify the files. That is, a file can be arrived
  12. * at from many different locations such as help.html from .
  13. * and ../help.html from a directory below.
  14. *
  15. * This table is shared by all instances of LinkChecker.
  16. */
  17. private static Hashtable visited = new Hashtable(100);
  18. /** A table of the images visited by any document; a cache of correctness */
  19. private static Hashtable imgVisited = new Hashtable(100);
  20. private static int recursionDepth = 0;
  21. private static final String separator = "/"; // not OS sensitive in HTML
  22. private static final String localSeparator =
  23. System.getProperty("file.separator");
  24. public LinkChecker(String document) {
  25. this.document = document;
  26. this.directory = pathMinusFile(document);
  27. }
  28. public boolean checkLinkRules(String fName, int line) {
  29. // Check case of path (check for UNIX compatibility on a PC)!
  30. String offensive = offensivePathMember(directory + separator + fName);
  31. if (offensive != null) {
  32. String file="";
  33. try {
  34. File f = new File(offensive);
  35. file = f.getCanonicalPath();
  36. error("Case mismatch in reference " + fName + ":"+
  37. System.getProperty("line.separator")+"\treal name is "+
  38. fileMinusPathLocal(file)+System.getProperty("line.separator")+
  39. "\treal absolute path is "+file, line);
  40. return false;
  41. }
  42. catch (IOException io) {
  43. error("internal error: cannot get canonical name for "+offensive, line);
  44. }
  45. }
  46. if (new File(fName).isAbsolute()) {
  47. error("Reference to " + fName + " with absolute path", line);
  48. return false;
  49. }
  50. return true;
  51. }
  52. public void doCheck() throws IOException {
  53. if ( !document.endsWith(".html") ) {
  54. return;
  55. }
  56. // prevent infinite recursion to this file
  57. if (visited(document)) {
  58. return;
  59. }
  60. visit(document);
  61. recursionDepth++;
  62. FileReader f = new FileReader(document);
  63. LinkExtractor lexer = new LinkExtractor(f);
  64. lexer.addLinkListener(this);
  65. // this will parse whole file since all tokens are skipped
  66. try {
  67. lexer.nextToken();
  68. }
  69. catch (antlr.TokenStreamException e) {
  70. error("internal error:" + e,1);
  71. }
  72. recursionDepth--;
  73. }
  74. public void error(String err, int line) {
  75. String d="<internal error>";
  76. try {
  77. File f = new File(document);
  78. d = f.getCanonicalPath();
  79. }
  80. catch (IOException io) {
  81. System.err.println("internal error: cannot find file that has error");
  82. System.exit(0);
  83. }
  84. System.err.println(d+":"+line+":"+System.getProperty("line.separator")+"\t"+err);
  85. }
  86. public static boolean fileAbsolute(String path) {
  87. return path.startsWith("/") || path.charAt(1)==':';
  88. }
  89. /** Return file from end of HTML path; i.e., use '/' separator */
  90. public static String fileMinusPath(String f) {
  91. int endOfPath = f.lastIndexOf(separator);
  92. if ( endOfPath == -1 ) {
  93. return f; // no path found
  94. }
  95. return f.substring(endOfPath+1);
  96. }
  97. /** Return file from end of locally correct path; i.e., use '/' or '\' separator */
  98. public static String fileMinusPathLocal(String f) {
  99. int endOfPath = f.lastIndexOf(localSeparator);
  100. if ( endOfPath == -1 ) {
  101. return f; // no path found
  102. }
  103. return f.substring(endOfPath+1);
  104. }
  105. public static boolean fileProtocolURL(String target) {
  106. return target.indexOf("://") == -1 &&
  107. !target.startsWith("mailto:") &&
  108. !target.startsWith("news:");
  109. }
  110. public static String getParent(String path) {
  111. int index = path.lastIndexOf(separator);
  112. if (index < 0) {
  113. return null;
  114. }
  115. if ( !fileAbsolute(path) || path.indexOf(separator) != index ) {
  116. return path.substring(0, index);
  117. }
  118. if (index < path.length() - 1) {
  119. return path.substring(0, index + 1);
  120. }
  121. return null;
  122. }
  123. public void hrefReference(String target, int line) {
  124. // System.out.println(document+":"+line+": href to "+target);
  125. // recursively check the target document unless non-file ref
  126. if (fileProtocolURL(target)) {
  127. // prune off any #name reference on end of file
  128. int pound = target.indexOf('#');
  129. String path = target;
  130. if (pound != -1) {
  131. path = target.substring(0, pound); // rip off #name on end, leave file
  132. if (path.length() == 0) {
  133. return; // ref to name in this file
  134. }
  135. }
  136. // first check existence on disk
  137. File f = new File(directory + separator + path);
  138. if (!f.exists()) {
  139. error("Reference to missing file " + path, line);
  140. return;
  141. }
  142. // check the case
  143. checkLinkRules(path, line);
  144. try {
  145. // Link is ok, now follow the link
  146. LinkChecker chk = new LinkChecker(directory + separator + path);
  147. chk.doCheck();
  148. } catch (IOException io) {
  149. error("Document does not exist: " + target, line);
  150. }
  151. }
  152. }
  153. public static boolean imageLinkIsOk(String file) throws IOException {
  154. File f = new File(file);
  155. file = f.getCanonicalPath();
  156. Boolean b = (Boolean)imgVisited.get(file);
  157. if ( b!=null ) {
  158. return b.booleanValue();
  159. }
  160. return false;
  161. }
  162. public void imageReference(String imageFileName, int line) {
  163. // first check if we have seen this exact file
  164. try {
  165. if (imageLinkIsOk(directory+separator+imageFileName)) {
  166. return;
  167. }
  168. File f = new File(directory + separator + imageFileName);
  169. if (!f.exists()) {
  170. error("Reference to missing file " + imageFileName, line);
  171. return;
  172. }
  173. if (checkLinkRules(imageFileName, line)) {
  174. visitImage(directory+separator+imageFileName);
  175. }
  176. } catch (IOException io) {
  177. if (!(io instanceof FileNotFoundException)) {
  178. System.err.println("internal error: " + io.getMessage());
  179. }
  180. }
  181. }
  182. /** Given a path to a file or dir, is the case of the reference
  183. * the same as the actual path on the disk? This is only
  184. * meaningful on a PC which is case-insensitive (not a real
  185. * file system).
  186. *
  187. * Returns null if there is nothing offensive and the file exists.
  188. * Returns offending file/dir if it does not exist or
  189. * it has there is a case mismatch for it. The last file is checked
  190. * first followed by the parent directory, recursively, all the way
  191. * to the absolute or relative path root in that String; i.e., we parse
  192. * from right to left.
  193. *
  194. * Because the File object won't actually go get the real filename
  195. * from the disk so we can compare, we must get a directory listing
  196. * of the directory and then look for the referenced file or dir.
  197. * For example, for "./images/logo.gif" we would check "./images" dir
  198. * listing for "logo.gif" with the appropriate case and then check
  199. * directory "." for a dir called images with the right case. When
  200. * no parent exists, we can stop looking for case problems.
  201. */
  202. public static String offensivePathMember(String fName) {
  203. // System.out.println("caseMismatch(" + fName + ")");
  204. // have we reached the root? (stopping condition)
  205. if (fName==null || getParent(fName) == null) {
  206. return null;
  207. }
  208. String parent = getParent(fName);
  209. fName = fileMinusPath(fName);
  210. File f = new File(parent);
  211. String[] parentFiles = f.list();
  212. // System.out.println("checking dir " + parent + " for " + fName);
  213. // handle weird stuff like "c:/doc/../foo"; skip this parent dir
  214. if ( fName.equals("..") ) {
  215. return offensivePathMember(getParent(parent));
  216. }
  217. for (int i = 0; i < parentFiles.length; i++) {
  218. // System.out.println("is it " + parentFiles[i] + "?");
  219. if (parentFiles[i].equalsIgnoreCase(fName)) {
  220. if (!parentFiles[i].equals(fName)) {
  221. // System.out.println("case mismatch " + fName + " in " + parent);
  222. return parent + separator + fName;
  223. }
  224. // found a match, verify parent is ok
  225. return offensivePathMember(parent);
  226. }
  227. }
  228. // System.out.println("can't find " + fName + " in " + parent);
  229. return parent + separator + fName;
  230. }
  231. public static String pathMinusFile(String f) {
  232. int endOfPath = f.lastIndexOf(separator);
  233. if ( endOfPath == -1 ) {
  234. return "."; // no path found: use current directory
  235. }
  236. return f.substring(0, endOfPath);
  237. }
  238. public static void visit(String file) throws IOException {
  239. File f = new File(file);
  240. file = f.getCanonicalPath();
  241. visited.put(file, new Boolean(true));
  242. }
  243. public static boolean visited(String file) throws IOException {
  244. File f = new File(file);
  245. file = f.getCanonicalPath();
  246. return visited.get(file) != null;
  247. }
  248. public static void visitImage(String file) throws IOException {
  249. File f = new File(file);
  250. file = f.getCanonicalPath();
  251. // System.out.println("caching image "+file);
  252. imgVisited.put(file, new Boolean(true));
  253. }
  254. }