home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 December / PCO1297.ISO / FilesBBS / FREI / JAVA3.ARJ / JAVA3.ZIP / JAVA / ClientSearchGenerator.java < prev    next >
Encoding:
Java Source  |  1997-11-06  |  14.8 KB  |  461 lines

  1. // ClientSearchGenerator Version 1.0
  2. // Die Suchmaschine fⁿr Jedermann, Generator
  3. // Autor: Gerhard Schild, 1997
  4. // Fⁿr: PC-ONLiNE
  5.  
  6. import java.applet.*;
  7. import java.awt.*;
  8. import java.util.*;
  9. import java.io.*;
  10. import java.net.*;
  11. import java.util.zip.*;
  12.  
  13. // Dokumenten-Auswerter
  14. class DocumentParser {
  15.   SearchEngineSpider spider;
  16.   InputStream in;
  17.   SearchEngineGenerator g;
  18.   String section;
  19.   URL url;
  20.   int pos, unget;
  21.  
  22.   // Auswertung mit Spider
  23.   public DocumentParser(SearchEngineGenerator g, InputStream in, SearchEngineSpider s, URL url) {
  24.     this.g=g;
  25.     this.in=in;
  26.     this.spider=s;
  27.     this.url=url;
  28.     unget=-1;
  29.   }
  30.   // Auswertung ohne Spider
  31.   public DocumentParser(SearchEngineGenerator g, InputStream in) {
  32.     this.g=g;
  33.     this.in=in;
  34.     this.url=null;
  35.     this.spider=null;
  36.     unget=-1;
  37.   }
  38.   // NΣchstes Zeichen aus dem Eingabestream holen
  39.   int get() throws IOException {
  40.     int r;
  41.     if(unget>=0) {
  42.       r=unget; unget=-1;
  43.     }
  44.     else
  45.       r=in.read();
  46.     return r;
  47.   }
  48.   // Zeichen analysieren
  49.   static boolean isWS(int c) { return c==' ' || c=='\t' || c=='\r' || c=='\n'; }
  50.   static boolean isAlpha(int c) { return Character.isLetterOrDigit((char)c); }
  51.   // Text-Abschnitt holen:
  52.   // Liefert entweder einen Tag oder einen Textbereich zwischen zwei Tags
  53.   // Whitespace wird dabei auf je ein Leerzeichen reduziert
  54.   String getSection() throws IOException {
  55.     StringBuffer b=new StringBuffer();
  56.     pos=0;
  57.     int c;
  58.     boolean tag, quote=false, ws=false;
  59.  
  60.     while( (c=get())>=0 && isWS(c) );         // Fⁿhrenden WS ⁿberspringen
  61.     tag=c=='<';
  62.     if(c>=0) {
  63.       unget=c;
  64.       while( (c=get())>=0 ) {
  65.         if(tag) {
  66.           if(quote) {                         // "..."?
  67.             b.append((char)c);
  68.             if(c=='\"') quote=ws=false;
  69.             continue;
  70.           }
  71.           if(c=='\"') { b.append('\"'); quote=true; continue; }
  72.           if(c=='>') { b.append('>'); break; }
  73.         }
  74.         else {
  75.           if(c=='<') { unget=c; break; }
  76.         }
  77.         if(isWS(c)) {           // Leerraum verkⁿrzen
  78.           if(!ws) { b.append(' '); ws=true; }
  79.           continue;
  80.         }
  81.         ws=false;
  82.         b.append((char)c);
  83.       }
  84.     }
  85.     return section=HTMLcvt.fromHTML(b.toString());
  86.   }
  87.   // NΣchstes Zeichen aus dem Textabschnitt holen
  88.   int getChar() {
  89.     if(pos>=section.length()) return -1;
  90.     int c=section.charAt(pos++);
  91.     return c;
  92.   }
  93.   // Extrahiert das nΣchste Wort aus dem aktuellen Textabschnitt
  94.   String getWord() {
  95.     StringBuffer w=new StringBuffer();
  96.     int c;
  97.     while( (c=getChar())>=0 )
  98.       if(isAlpha(c))
  99.         break;
  100.     if(c>=0) {
  101.       for(;;) {
  102.         w.append((char)c);
  103.         if((c=getChar())<0) break;
  104.         if(!isAlpha(c)) break;
  105.       }
  106.     }
  107.     return w.toString();
  108.   }
  109.   // Spider: Link verfolgen
  110.   // <A href="..."> oder "<FRAME SRC="..."> oder "<AREA href="..."> auswerten
  111.   void spiderFollow(String prefix, String tag, String uptag) {
  112.     int n=uptag.indexOf(prefix);
  113.     if(n<0) return;
  114.     n+=prefix.length();
  115.     try {
  116.       if(tag.charAt(n)==' ') ++n;       // Evtl. Whitespace
  117.       if(tag.charAt(n++)!='=') return;  // "=" fehlt
  118.       if(tag.charAt(n)==' ') ++n;       // Evtl. Whitespace
  119.       StringBuffer link=new StringBuffer();
  120.       if(tag.charAt(n)=='\"') {         // Link in Anfⁿhrungszeichen?
  121.         while(tag.charAt(++n)!='\"')
  122.           link.append((char)tag.charAt(n));
  123.       }
  124.       else {
  125.         for(;;) {
  126.           int ch=tag.charAt(n++);
  127.           if(ch==' ' || ch=='>') break;
  128.           link.append((char)ch);
  129.         }
  130.       }
  131.       spider.follow(url, link.toString());
  132.     }
  133.     catch(Exception e) {
  134.     }
  135.   }
  136.   // Dokument-Auswertung starten
  137.   public void parse(String document) throws IOException {
  138.     int doc=g.addDocument(document, "");
  139.     int words=0, back=0;
  140.     boolean inTitle=false, init=true;
  141.     StringBuffer title=new StringBuffer();
  142.     String titleString=null;
  143.  
  144.     for(String s; (s=getSection()).length()>0; ) {
  145.       if(init) {
  146.         System.out.print("\r * "+(titleString==null ? "" : titleString+": ")+g.getDocs()+"/");
  147.         back=0;
  148.         init=false;
  149.       }
  150.       if(s.startsWith("<")) {                   // TAG?
  151.         String tag=s.toUpperCase();
  152.         if(tag.startsWith("<TITLE")) inTitle=true;
  153.         if(tag.startsWith("</TITLE")) {
  154.           inTitle=false;
  155.           titleString=title.toString();
  156.           init=true;
  157.         }
  158.         if(tag.startsWith("<A ")) {            // <A href="...">
  159.           if(spider!=null) spiderFollow("HREF", s, tag);
  160.         }
  161.         if(tag.startsWith("<FRAME ")) {        // <FRAME src="...">
  162.           if(spider!=null) spiderFollow("SRC", s, tag);
  163.         }
  164.         if(tag.startsWith("<AREA ")) {         // <AREA href="...">
  165.           if(spider!=null) spiderFollow("HREF", s, tag);
  166.         }
  167.       }
  168.       else {
  169.         if(inTitle) {
  170.           if(title.length()>0) title.append(' ');
  171.           title.append(section);
  172.         }
  173.         for(String t; (t=getWord()).length()>0; ) {
  174.           g.addWord(doc, t.toUpperCase());
  175.           String s2=""+(++words)+"/"+g.getSize();
  176.           while(back-->0) System.out.print('\b');
  177.           System.out.print(s2);
  178.           back=s2.length();
  179.         }
  180.       }
  181.     }
  182.     if(titleString!=null) g.addDocument(document, titleString);
  183.     System.out.println("");
  184.   }
  185. }
  186.  
  187. // Spider (verfolgt alle Links)
  188. class SearchEngineSpider {
  189.   URL home;               // Basisadresse
  190.   String homes;           // dto. als String
  191.   Properties done, todo;  // Dokumentenlisten
  192.   SearchEngineSpider(URL home, String doc) {
  193.     this.home=home;
  194.     done=new Properties();
  195.     todo=new Properties();
  196.     homes=home.toString();
  197.     follow(home, doc);
  198.   }
  199.   // Link verfolgen
  200.   public void follow(URL current, String doc) {
  201.     int n=doc.lastIndexOf('#');                  // Marke?
  202.     if(n>=0) doc=doc.substring(0, n);
  203.     try {
  204.       URL newURL=new URL(current, doc);
  205.       String newdoc=newURL.toString();
  206.       if(done.get(newdoc)==null)                 // Noch nicht erledigt?
  207.         todo.put(newdoc, "");                    // Dann vormerken
  208.     } catch(Exception e) {
  209.     }
  210.   }
  211.   // Spider starten
  212.   void run(SearchEngineGenerator g) {
  213.     Enumeration n;
  214.     // NΣchsten Eintrag aus der todo-Liste holen
  215.     while( (n=todo.keys()).hasMoreElements() ) {
  216.       String key=(String)n.nextElement();
  217.       todo.remove(key);
  218.       done.put(key, "");
  219.       // Links ignorieren, die nicht unterhalb der Basis-URL liegen
  220.       try {
  221.         URL doc=new URL(key);
  222.         String docs=doc.toString(), updocs=docs.toUpperCase();
  223.         if(!docs.startsWith(homes)) {
  224.           System.out.println("Ignoriere externen Link "+docs);
  225.         }
  226.         else if(! (updocs.endsWith("/") || updocs.endsWith(".HTM") || updocs.endsWith(".TXT")
  227.                   || updocs.endsWith(".HTML") || updocs.endsWith(".SHTML")) ) {
  228.           System.out.println("Ignoriere Link mit unbekannter Erweiterung: "+docs);
  229.         }
  230.         else {
  231.           System.out.println("Indiziere "+docs);
  232.           DocumentParser p=new DocumentParser(g, doc.openStream(), this, doc);
  233.           p.parse(key.substring(homes.length()));
  234.         }
  235.       } catch(Exception e) {
  236.         System.err.println("Exception: "+e.getMessage());
  237.       }
  238.     }
  239.   }
  240. }
  241.  
  242. // Generator fⁿr den Suchindex
  243. class SearchEngineGenerator {
  244.   Properties tab;           // Tabelle der Schlⁿsselworte
  245.   Hashtable docs;           // Tabelle der Dokumente
  246.   Properties exclude;       // Ausschlu▀liste
  247.   int nextDoc;
  248.  
  249.   SearchEngineGenerator() {
  250.     nextDoc=0;
  251.     tab=new Properties();
  252.     docs=new Hashtable();
  253.     exclude=new Properties();
  254.     // Ausschlu▀liste laden
  255.     try {
  256.       InputStream in=new FileInputStream("exclude.dat");
  257.       exclude.load(in);
  258.       in.close();
  259.     } catch(IOException e) {
  260.       System.err.println("Ausschlussliste exclude.dat konnte nicht geladen werden");
  261.     }
  262.   }
  263.   void clear() { tab.clear(); docs.clear(); nextDoc=0; }
  264.   // Tabelle speichern
  265.   void save(OutputStream out) throws IOException {
  266.     tab.save(out, "SearchEngine");
  267.     out.close();
  268.   }
  269.   void saveZIP(OutputStream out) throws IOException {
  270.     save(new DeflaterOutputStream(out, new Deflater(Deflater.BEST_COMPRESSION)));
  271.   }
  272.   // Tabelle laden
  273.   void load(InputStream in) throws IOException {
  274.     clear();
  275.     tab.load(in);
  276.     in.close();
  277.     for(;;) {
  278.       String s=tab.getProperty("."+IntToString(nextDoc));
  279.       if(s==null) break;
  280.       SearchEngineResult r=new SearchEngineResult(s);
  281.       addDocument(r.document, r.caption);
  282.     }
  283.   }
  284.   void loadZIP(InputStream in) throws IOException {
  285.     load(new InflaterInputStream(in));
  286.   }
  287.   public int getSize() { return tab.size(); }
  288.   public int getDocs() { return docs.size(); }
  289.   public String getStatus() { return ""+getDocs()+" Dokumente/"+getSize()+" Woerter"; }
  290.   // Dokument speichern. Liefert Dokumenten-Index zurⁿck
  291.   public int addDocument(String document, String caption) {
  292.     Integer b=(Integer)docs.get(document);
  293.     if(b==null) b=new Integer(nextDoc++);
  294.     docs.put(document, b);
  295.     tab.put("."+IntToString(b.intValue()), document+","+HTMLcvt.toHTML(caption));
  296.     return b.intValue();
  297.   }
  298.   // Dokumentenindex (de-)kodieren
  299.   static final String encoding="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  300.   static final int enclen=62;
  301.   static public char IntToChar(int i) { return encoding.charAt(i); }
  302.   static public int CharToInt(char c) { return encoding.indexOf((int)c); }
  303.   public static int StringToInt(String s, int index) {
  304.     return CharToInt(s.charAt(index))*enclen+CharToInt(s.charAt(index+1));
  305.   }
  306.   public static String IntToString(int i) {
  307.     return ""+IntToChar(i/enclen)+IntToChar(i%enclen);
  308.   }
  309.   // Word im Suchindex speichern
  310.   public void addWord(int document, String word) {
  311.     if(exclude!=null && exclude.getProperty(word)!=null) return;
  312.     if(word.length()<2) return;
  313.     // Eintrag fⁿr das Wort suchen
  314.     String t=tab.getProperty(word);
  315.     if(t==null) {
  316.       // Neues Wort
  317.       tab.put(word, IntToString(document));
  318.     }
  319.     else {
  320.       // Wort schon da: Testen, ob das Dokument schon vorhanden ist
  321.       boolean found=false;
  322.       for(int i=0; i<t.length(); i+=2) {
  323.         if(document==StringToInt(t, i))
  324.           found=true;
  325.       }
  326.       if(!found) {
  327.         tab.put(word, t+IntToString(document));
  328.       }
  329.     }
  330.   }
  331. }
  332.  
  333. // Generator-Hauptprogramm
  334. public class ClientSearchGenerator {
  335.   static SearchEngineGenerator g;
  336.   static boolean zipAvailable=false;
  337.   static void usage() {
  338.     System.out.println("Gueltige Argumente:");
  339.     System.out.println("  CLEAR                     Suchindex loeschen");
  340.     System.out.println("  ADD    home file [url]    Datei indizieren");
  341.     System.out.println("  ADDW   home file          Mehrere Dateien indiziern (mit Wildcards)");
  342.     System.out.println("  ADDWS  home file          Mehrere Dateien indiziern (mit Wildcards ");
  343.     System.out.println("                            und Unterverzeichnissen)");
  344.     System.out.println("  SPIDER home file          Dokument und alle Verweise indizieren");
  345.     System.exit(1);
  346.   }
  347.   // Tabelle laden
  348.   static void load() {
  349.     // Aktuellen Stand laden
  350.     System.out.println("Lade "+ClientSearch.rawfile);
  351.     try {
  352.       InputStream in=new FileInputStream(ClientSearch.rawfile);
  353.       g.load(in);
  354.       in.close();
  355.     } catch(Exception e) {
  356.       System.err.println("Exception: "+e.getMessage());
  357.     }
  358.     System.out.println(g.getStatus());
  359.   }
  360.   // Tabelle speichern
  361.   static void save() {
  362.     try {
  363.       System.out.println("Speichere "+ClientSearch.rawfile);
  364.       g.save(new FileOutputStream(ClientSearch.rawfile));
  365.     } catch(Exception e) {
  366.       System.err.println("Exception: "+e.getMessage());
  367.     }
  368.     if(zipAvailable) {
  369.       try {
  370.         System.out.println("Speichere "+ClientSearch.zipfile);
  371.         g.saveZIP(new FileOutputStream(ClientSearch.zipfile));
  372.       } catch(Exception e) {
  373.         System.err.println("Exception: "+e.getMessage());
  374.       }
  375.     }
  376.     else
  377.       System.err.println("WARNUNG: ZIP-Kompression nicht verfuegbar. "+
  378.                          ClientSearch.zipfile+" wurde nicht erzeugt.");
  379.     System.out.println(g.getStatus());
  380.   }
  381.   // Verzeichnis indizieren (rekursiv)
  382.   static void addDir(File dir, String prefix, FilenameFilter filter, boolean sub) {
  383.     System.out.println("Durchsuche "+dir.toString());
  384.     String[] files=dir.list(filter);
  385.     if(files!=null)
  386.       for(int i=0; i<files.length; ++i) {
  387.         System.out.println("Indiziere "+prefix+files[i]);
  388.         try {
  389.           File file=new File(dir, files[i]);
  390.           FileInputStream in=new FileInputStream(file);
  391.           DocumentParser p=new DocumentParser(g, in);
  392.           p.parse(prefix+files[i]);
  393.         } catch(Exception e) {
  394.           System.err.println("Exception: "+e.getMessage());
  395.         }
  396.       }
  397.     // Unterverzeichnisse durchsuchen
  398.     if(sub) {
  399.       files=dir.list();
  400.       if(files!=null)
  401.         for(int i=0; i<files.length; ++i) {
  402.           File subdir=new File(dir, files[i]);
  403.           if(subdir.isDirectory())
  404.             addDir(subdir, prefix+files[i]+File.separator, filter, sub);
  405.         }
  406.      }
  407.   }
  408.   // Programmeintritt: Argumente auswerten
  409.   public static void main(String args[]) {
  410.     if(args.length<1) usage();
  411.     g=new SearchEngineGenerator();
  412.     try {
  413.       Class c1=Class.forName("java.util.zip.InflaterInputStream");
  414.       Class c2=Class.forName("java.util.zip.DeflaterOutputStream");
  415.       zipAvailable=true;
  416.     } catch(Exception e) {
  417.     }
  418.     if(args[0].equalsIgnoreCase("CLEAR")) {
  419.       save();
  420.     }
  421.     else if(args[0].equalsIgnoreCase("ADD")) {
  422.       if(args.length<3||args.length>4) usage();
  423.       load();
  424.       try {
  425.         URL home=new URL(args[1]);
  426.         URL doc=new URL(home, args[2]);
  427.         System.out.println("Indiziere "+doc.toString());
  428.         DocumentParser p=new DocumentParser(g, doc.openStream());
  429.         p.parse(args.length>=4 ? args[3] : args[2]);
  430.       } catch(Exception e) {
  431.         System.err.println("Exception: "+e.getMessage());
  432.       }
  433.       save();
  434.     }
  435.     else if(args[0].equalsIgnoreCase("ADDW")
  436.           ||args[0].equalsIgnoreCase("ADDWS")) {
  437.       boolean sub=args[0].equalsIgnoreCase("ADDWS");
  438.       if(args.length!=3) usage();
  439.       load();
  440.       addDir(new File(args[1]), new String(""), new WildcardFilter(args[2]), sub);
  441.       save();
  442.     }
  443.     else if(args[0].equalsIgnoreCase("SPIDER")) {
  444.       if(args.length!=3) usage();
  445.       load();
  446.       try {
  447.         URL home=new URL(args[1]);
  448.         SearchEngineSpider spider=new SearchEngineSpider(home, args[2]);
  449.         spider.run(g);
  450.       } catch(Exception e) {
  451.         System.err.println("Exception: "+e.getMessage());
  452.       }
  453.       save();
  454.     }
  455.     else
  456.       usage();
  457.   }
  458. }
  459.  
  460.  
  461.