HtmlLinksExtractor.java
001 /*
002  *  HtmlLinkExtractor.java
003  *
004  *  Copyright (c) 1995-2012, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Cristian URSU,  16/Nov/2001
013  *
014  *  $Id: HtmlLinksExtractor.java 17640 2014-03-12 14:13:54Z markagreenwood $
015  */
016 
017 package gate.util;
018 
019 import java.io.*;
020 import java.util.*;
021 
022 import javax.swing.text.BadLocationException;
023 import javax.swing.text.MutableAttributeSet;
024 import javax.swing.text.html.HTML;
025 import javax.swing.text.html.HTMLEditorKit;
026 import javax.swing.text.html.HTMLEditorKit.ParserCallback;
027 import javax.swing.text.html.parser.ParserDelegator;
028 
029 /**
030  * This class extracts links from HTML files.
031  <B>It has been hacked</B> to build the contents of
032  * <A HREF="http://gate.ac.uk/sitemap.html">http://gate.ac.uk/sitemap.html</A>;
033  * you <B>probably don't want to use it</B> for anything else!
034  <P>
035  * Implements the behaviour of the HTML reader.
036  * Methods of an object of this class are called by the HTML parser when
037  * events will appear.
038  */
039 public class HtmlLinksExtractor extends ParserCallback {
040 
041   /** Debug flag */
042   private static final boolean DEBUG = false;
043 
044   /** The tag currently being processed */
045   private HTML.Tag currentTag = null;
046 
047   /** whether we've done a title before */
048   static boolean firstTitle = true;
049 
050   /** will contain &lt;/UL&gt; after first title */
051   static String endUl = "";
052 
053   /** Name of the file we're currently processing */
054   static String currFile = "";
055 
056   /** Path to the file we're currently processing */
057   static String currPath = "";
058 
059   /** This method is called when the HTML parser encounts the beginning
060     * of a tag that means that the tag is paired by an end tag and it's
061     * not an empty one.
062     */
063   @Override
064   public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
065 
066     currentTag = t;
067     if (HTML.Tag.A == t){
068       Out.pr("<LI><" + t);
069       Enumeration<?> e = a.getAttributeNames();
070       while(e.hasMoreElements()) {
071         HTML.Attribute name = (HTML.Attributee.nextElement();
072         String value = (Stringa.getAttribute(name);
073 
074         if(name == HTML.Attribute.HREF) {
075           if(
076             value.startsWith("http:"|| value.startsWith("HTTP:"||
077             value.startsWith("file:"|| value.startsWith("FILE:"||
078             value.startsWith("mailto:"|| value.startsWith("MAILTO:"||
079             value.startsWith("ftp:"|| value.startsWith("FTP:")
080           )
081             Out.pr(" HREF=\"" + value + "\"");
082           else // if it is a relative path....
083             Out.pr(" HREF=\"" + currPath + "/" + value + "\"");
084           }
085         }
086       // while
087 
088       Out.pr(">");
089     }// End if
090 
091     if (HTML.Tag.TITLE == t){
092       Out.pr(endUl + "<H3>");
093       if(firstTitle) { firstTitle = false; endUl = "</UL>"}
094     }// End if
095 
096   }//handleStartTag
097 
098   private void printAttributes(MutableAttributeSet a){
099     if (a == nullreturn;
100     // Take all the attributes an put them into the feature map
101     if (!= a.getAttributeCount()){
102       Enumeration<?> enumeration = a.getAttributeNames();
103       while (enumeration.hasMoreElements()){
104         Object attribute = enumeration.nextElement();
105         Out.pr(" "+ attribute.toString() "=\"" +
106                                   a.getAttribute(attribute).toString()+"\"");
107       }// End while
108     }// End if
109   }// printAttributes();
110 
111    /** This method is called when the HTML parser encounts the end of a tag
112      * that means that the tag is paired by a beginning tag
113      */
114   @Override
115   public void handleEndTag(HTML.Tag t, int pos){
116     currentTag = null;
117 
118     if (HTML.Tag.A == t)
119       Out.pr("</"+t+">\n");
120     if (HTML.Tag.TITLE == t)
121       Out.pr(
122         "</H3></A>\n\n<P>Links in: <A HREF=\"" + currFile +
123         "\">" + currFile + "</A>:\n<UL>\n"
124       );
125 
126   }//handleEndTag
127 
128   /** This method is called when the HTML parser encounts an empty tag
129     */
130   @Override
131   public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos){
132     if (HTML.Tag.A == t){
133       Out.pr("<"+t);
134       printAttributes(a);
135       Out.pr("/>\n");
136     }// End if
137 
138     if (HTML.Tag.TITLE == t){
139       Out.pr("<"+t);
140       printAttributes(a);
141       Out.pr("/>\n");
142     }// End if
143   // handleSimpleTag
144 
145   /** This method is called when the HTML parser encounts text (PCDATA)*/
146   @Override
147   public void handleText(char[] text, int pos){
148 
149     if(HTML.Tag.A == currentTag){
150       //text of tag A
151       String tagText = new String(text);
152       Out.pr(tagText);
153     }// End if
154 
155     if(HTML.Tag.TITLE == currentTag){
156       //text of tag A
157       String tagText = new String(text);
158       Out.pr(tagText);
159     }// End if
160 
161   }// end handleText();
162 
163   /**
164     * This method is called when the HTML parser encounts an error
165     * it depends on the programmer if he wants to deal with that error
166     */
167   @Override
168   public void handleError(String errorMsg, int pos) {
169     //Out.println ("ERROR CALLED : " + errorMsg);
170   }
171 
172   /** This method is called once, when the HTML parser reaches the end
173     * of its input streamin order to notify the parserCallback that there
174     * is nothing more to parse.
175     */
176   @Override
177   public void flush() throws BadLocationException{
178   }// flush
179 
180   /** This method is called when the HTML parser encounts a comment
181     */
182   @Override
183   public void handleComment(char[] text, int pos) {
184   }
185 
186   /**
187    * Given a certain folder it lists recursively all the files contained
188    * in that folder. It returns a list of strings representing the file
189    * names
190    */
191   private static List<String> listAllFiles(File aFile, Set<String> foldersToIgnore){
192     List<String> sgmlFileNames = new ArrayList<String>();
193     List<File> foldersToExplore = new ArrayList<File>();
194     if (!aFile.isDirectory()){
195       // add the file to the file list
196       sgmlFileNames.add(aFile.getPath());
197       return sgmlFileNames;
198     }// End if
199     listFilesRec(aFile,sgmlFileNames,foldersToExplore, foldersToIgnore);
200     return sgmlFileNames;
201   // listAllFiles();
202 
203   /** Helper method for listAllFiles */
204   private static void listFilesRec(File aFile,
205                                   List<String> fileNames,
206                                   List<File> foldersToExplore,
207                                   Set<String> foldersToIgnore){
208 
209     String[] fileList = aFile.list();
210     for (int i=0; i< fileList.length; i++){
211       File tmpFile = new File(aFile.getPath()+"\\"+fileList[i]);
212       if (tmpFile.isDirectory()){
213         // If the file is not included
214         if (!foldersToIgnore.contains(tmpFile.getName())) {  //fileList[i])) {
215           if(DEBUG) {
216             Err.prln("adding dir: " + tmpFile);
217             Err.prln("  name: " + tmpFile.getName());
218           }
219           foldersToExplore.add(tmpFile);
220         }
221       }else{
222         // only process .html files
223         if(
224           fileList[i].toLowerCase().endsWith(".html") ) ||
225           fileList[i].toLowerCase().endsWith(".htm") )
226         fileNames.add(tmpFile.getPath());
227       }// End if
228     }// End for
229 
230     while(!foldersToExplore.isEmpty()){
231       File folder = foldersToExplore.get(0);
232       foldersToExplore.remove(0);
233       listFilesRec(folder,fileNames,foldersToExplore,foldersToIgnore);
234     }//End while
235 
236   // listFilesRec();
237 
238   /** Extract links from all .html files below a directory */
239   public static void main(String[] args){
240     HTMLEditorKit.Parser  parser = new ParserDelegator();
241     // create a new Htmldocument handler
242     HtmlLinksExtractor htmlDocHandler = new HtmlLinksExtractor();
243 
244     if (args.length == 0){
245       Out.prln(
246         "Eg: java HtmlLinksExtractor g:\\tmp\\relative javadoc img > results.txt"
247       );
248       return;
249     }
250     // Create a folder file File
251     File htmlFolder = new File(args[0]);
252     Set<String> foldersToIgnore = new HashSet<String>();
253     for(int i = 1; i<args.length; i++)
254       foldersToIgnore.add(args[i]);
255 
256     List<String> htmlFileNames = listAllFiles(htmlFolder,foldersToIgnore);
257     //Collections.sort(htmlFileNames);
258     while (!htmlFileNames.isEmpty()){
259       try{
260         String htmlFileName = htmlFileNames.get(0);
261         currFile = htmlFileName;
262         currPath = new File(currFile).getParent().toString();
263         htmlFileNames.remove(0);
264 
265         Out.prln("\n\n<A HREF=\"file://" + htmlFileName + "\">");
266         Reader reader = new FileReader(htmlFileName);
267         // parse the HTML document
268         parser.parse(reader, htmlDocHandler, true);
269       catch (IOException e){
270         e.printStackTrace(System.out);
271       }// End try
272     }// End while
273     System.err.println("done.");
274   }// main
275 
276 }//End class HtmlLinksExtractor
277 
278