home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 December / PCO1297.ISO / FilesBBS / FREI / CLS.ARJ / CLS.ZIP / ClientSearchGenerator.java < prev    next >
Encoding:
Java Source  |  1997-11-02  |  12.9 KB  |  410 lines

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