(no commit message)
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Fri, 17 Mar 2006 21:25:29 +0000 (21:25 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Fri, 17 Mar 2006 21:25:29 +0000 (21:25 +0000)
crawler/basic/src/org/wamblee/crawler/AbstractPageRequest.java
crawler/kiss/build.xml
crawler/kiss/src/org/wamblee/crawler/kiss/KissCrawler.java
crawler/kiss/src/org/wamblee/crawler/kiss/Program.java
crawler/kiss/src/org/wamblee/crawler/kiss/SystemProperties.java [new file with mode: 0644]
support/build.xml
support/src/org/wamblee/conditions/AndCondition.java [new file with mode: 0644]
support/src/org/wamblee/conditions/FixedCondition.java [new file with mode: 0644]
support/src/org/wamblee/conditions/PropertyRegexCondition.java [new file with mode: 0644]
support/src/org/wamblee/xml/DOMUtility.java

index fa41a680ec39d2ad0d9583de051bae337e475db8..0c47430bd87b49af267bd82437c3e9dd4c1282ea 100644 (file)
@@ -19,7 +19,6 @@ package org.wamblee.crawler;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.io.PrintStream;
 
 import javax.xml.transform.OutputKeys;
index a2b58b4899949163efeee50ac2ece223e3d63f63..ed756b4b05c29568fa310de4a240e0fd80745e01 100644 (file)
@@ -17,7 +17,7 @@
    &header;
        
        <target name="module.build.deps" 
-         depends="logging.d,mail.d,commons-codec.d,dom4j.d,xerces.d,httpclient.d,jtidy.d,wamblee.support.d,wamblee.crawler.d">
+         depends="logging.d,mail.d,commons-beanutils.d,commons-codec.d,dom4j.d,xerces.d,httpclient.d,jtidy.d,wamblee.support.d,wamblee.crawler.d">
        </target>
        
        <!-- Set libraries to use in addition for test, a library which 
index fc076a5abaf7294e4fc96d747ee39674955d999e..e8687d9d09a5d01f15090592bce528bae1091c65 100644 (file)
@@ -25,6 +25,7 @@ import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.EnumMap;
 import java.util.List;
 import java.util.Properties;
 import java.util.regex.Matcher;
@@ -40,7 +41,6 @@ import javax.mail.internet.MimeMessage;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.dom4j.Element;
 import org.wamblee.conditions.Condition;
 import org.wamblee.crawler.Action;
 import org.wamblee.crawler.Configuration;
@@ -49,9 +49,10 @@ import org.wamblee.crawler.Page;
 import org.wamblee.crawler.PageException;
 import org.wamblee.crawler.impl.ConfigurationParser;
 import org.wamblee.crawler.impl.CrawlerImpl;
+import org.wamblee.crawler.kiss.Program.RecordingResult;
 
 /**
- * The KiSS crawler for automatic recording of interesting TV shows. 
+ * The KiSS crawler for automatic recording of interesting TV shows.
  * 
  */
 public class KissCrawler {
@@ -59,54 +60,63 @@ public class KissCrawler {
     private static final Log LOG = LogFactory.getLog(KissCrawler.class);
 
     /**
-     * Log file name for the crawler. 
+     * Log file name for the crawler.
      */
     private static final String LOG_FILE = "kiss.log";
 
     /**
-     * Start URL of the electronic programme guide. 
+     * Start URL of the electronic programme guide.
      */
     private static final String START_URL = "http://epg.kml.kiss-technology.com/login_core.php";
 
     /**
-     * Crawler configuration file. 
+     * Crawler configuration file.
      */
     private static final String CRAWLER_CONFIG = "config.xml";
 
     /**
-     * Configuration file describing interesting programs. 
+     * Configuration file describing interesting programs.
      */
     private static final String PROGRAM_CONFIG = "programs.xml";
 
     /**
-     * Regular expression for matching time interval strings in the 
-     * retrieved pages. 
+     * Regular expression for matching time interval strings in the retrieved
+     * pages.
      */
     private static final String TIME_REGEX = "([0-9]{2}):([0-9]{2})[^0-9]*([0-9]{2}):([0-9]{2}).*";
 
     /**
-     * Compiled pattern for the time regular expression. 
+     * Compiled pattern for the time regular expression.
      */
     private Pattern _pattern;
 
     /**
-     * Runs the KiSS crawler.  
-     * @param aArgs Arguments, currently all ignored because they are hardcoded.
-     * @throws Exception In case of problems. 
+     * Runs the KiSS crawler.
+     * 
+     * @param aArgs
+     *            Arguments, currently all ignored because they are hardcoded.
+     * @throws Exception
+     *             In case of problems.
      */
     public static void main(String[] aArgs) throws Exception {
         new KissCrawler(START_URL, CRAWLER_CONFIG, PROGRAM_CONFIG);
     }
-    
+
     /**
-     * Constructs the crawler. This retrieves the TV guide by crawling the 
-     * KiSS EPG guide, filters the guide for interesting programs, tries to 
-     * record them, and sends a summary mail to the user. 
-     * @param aStartUrl Start URL of the electronic programme guide. 
-     * @param aCrawlerConfig Configuration file for the  crawler. 
-     * @param aProgramConfig Configuration file describing interesting shows. 
-     * @throws IOException In case of problems reading files. 
-     * @throws MessagingException In case of problems sending a mail notification. 
+     * Constructs the crawler. This retrieves the TV guide by crawling the KiSS
+     * EPG guide, filters the guide for interesting programs, tries to record
+     * them, and sends a summary mail to the user.
+     * 
+     * @param aStartUrl
+     *            Start URL of the electronic programme guide.
+     * @param aCrawlerConfig
+     *            Configuration file for the crawler.
+     * @param aProgramConfig
+     *            Configuration file describing interesting shows.
+     * @throws IOException
+     *             In case of problems reading files.
+     * @throws MessagingException
+     *             In case of problems sending a mail notification.
      */
     public KissCrawler(String aStartUrl, String aCrawlerConfig,
             String aProgramConfig) throws IOException, MessagingException {
@@ -118,7 +128,7 @@ public class KissCrawler {
 
         try {
             HttpClient client = new HttpClient();
-            client.getHostConfiguration().setProxy("127.0.0.1", 3128);
+            // client.getHostConfiguration().setProxy("127.0.0.1", 3128);
 
             Crawler crawler = createCrawler(aCrawlerConfig, os, client);
 
@@ -140,57 +150,65 @@ public class KissCrawler {
     }
 
     /**
-     * Records interesting shows. 
-     * @param aProgramCondition Condition determining which shows are interesting. 
-     * @param aGuide Television guide. 
-     * @throws MessagingException In case of problems sending a summary mail. 
+     * Records interesting shows.
+     * 
+     * @param aProgramCondition
+     *            Condition determining which shows are interesting.
+     * @param aGuide
+     *            Television guide.
+     * @throws MessagingException
+     *             In case of problems sending a summary mail.
      */
     private void recordInterestingShows(Condition<Program> aProgramCondition,
             TVGuide aGuide) throws MessagingException {
         MatchVisitor matcher = new MatchVisitor(aProgramCondition);
         aGuide.accept(matcher);
         List<Program> programs = matcher.getMatches();
-        String recorded = "";
-        String notRecorded = "";
-        String failures = "";
+        EnumMap<RecordingResult, List<Program>> messages = new EnumMap<RecordingResult, List<Program>>(
+                RecordingResult.class);
+        for (RecordingResult result: RecordingResult.values()) {
+            messages.put(result, new ArrayList<Program>());
+        }
         for (Program program : programs) {
             try {
-                boolean result = program.record();
-                if (result) {
-                    recorded += "\n" + program;
-                } else {
-                    notRecorded += "\n" + program;
-                }
+                Program.RecordingResult result = program.record();
+                messages.get(result).add(program);
             } catch (PageException e) {
                 LOG.info("Attempt to record " + program + " failed.");
-                failures += "\n" + program.toString() + ": " + e.getMessage();
+                messages.get(RecordingResult.ERROR).add(program);
             }
         }
         String msg = "Summary of KiSS crawler: \n\n\n";
-
-        if (recorded.length() > 0) {
-            msg += "Recorded programs:\n\n" + recorded + "\n\n";
-        }
-        if (notRecorded.length() > 0) {
-            msg += "Not recorded programs:\n\n" + notRecorded + "\n\n";
-        }
-        if (recorded.length() == 0 && notRecorded.length() == 0) {
-            msg += "No suitable programs found";
+        
+       
+        for (RecordingResult result: RecordingResult.values()) { 
+            if ( messages.get(result).size() > 0 ) { 
+                msg += result.getDescription() + "\n\n"; 
+                for (Program program: messages.get(result)) { 
+                    msg += program + "\n";
+                }
+            }
         }
-        if (failures.length() > 0) {
-            msg += "Failures:\n\n" + failures;
+        if ( programs.size() == 0 ) { 
+            msg += "No suitable programs found"; 
         }
+        
         System.out.println(msg);
         sendMail(msg);
     }
 
     /**
-     * Creates the crawler. 
-     * @param aCrawlerConfig Crawler configuration file. 
-     * @param aOs Logging output stream for the crawler. 
-     * @param aClient HTTP Client to use. 
-     * @return Crawler. 
-     * @throws FileNotFoundException In case configuration files cannot be found. 
+     * Creates the crawler.
+     * 
+     * @param aCrawlerConfig
+     *            Crawler configuration file.
+     * @param aOs
+     *            Logging output stream for the crawler.
+     * @param aClient
+     *            HTTP Client to use.
+     * @return Crawler.
+     * @throws FileNotFoundException
+     *             In case configuration files cannot be found.
      */
     private Crawler createCrawler(String aCrawlerConfig, PrintStream aOs,
             HttpClient aClient) throws FileNotFoundException {
@@ -203,11 +221,14 @@ public class KissCrawler {
     }
 
     /**
-     * Gets the start page of the electronic programme guide. This involves login and
-     * navigation to a suitable start page after logging in. 
-     * @param aStartUrl URL of the electronic programme guide. 
-     * @param aCrawler Crawler to use. 
-     * @return Starting page. 
+     * Gets the start page of the electronic programme guide. This involves
+     * login and navigation to a suitable start page after logging in.
+     * 
+     * @param aStartUrl
+     *            URL of the electronic programme guide.
+     * @param aCrawler
+     *            Crawler to use.
+     * @return Starting page.
      */
     private Page getStartPage(String aStartUrl, Crawler aCrawler) {
         try {
@@ -220,9 +241,11 @@ public class KissCrawler {
     }
 
     /**
-     * Creates the TV guide by web crawling. 
-     * @param aPage Starting page. 
-     * @return TV guide. 
+     * Creates the TV guide by web crawling.
+     * 
+     * @param aPage
+     *            Starting page.
+     * @return TV guide.
      */
     private TVGuide createGuide(Page aPage) {
         LOG.info("Obtaining full TV guide");
@@ -234,6 +257,9 @@ public class KissCrawler {
                 Channel channel = createChannel(action.getName(), action
                         .execute().getAction("right-now").execute());
                 channels.add(channel);
+                if ( SystemProperties.isDebugMode() ) { 
+                    break; // Only one channel is crawled. 
+                }
             } catch (PageException e) {
                 LOG.error("Could not create channel information for '"
                         + action.getName() + "'", e);
@@ -243,10 +269,13 @@ public class KissCrawler {
     }
 
     /**
-     * Create channel information for a specific channel. 
-     * @param aChannel Channel name. 
-     * @param aPage Starting page for the channel. 
-     * @return Channel. 
+     * Create channel information for a specific channel.
+     * 
+     * @param aChannel
+     *            Channel name.
+     * @param aPage
+     *            Starting page for the channel.
+     * @return Channel.
      */
     private Channel createChannel(String aChannel, Page aPage) {
         LOG.info("Obtaining program for " + aChannel);
@@ -261,13 +290,21 @@ public class KissCrawler {
                 Time end = new Time(Integer.parseInt(matcher.group(3)), Integer
                         .parseInt(matcher.group(4)));
                 TimeInterval interval = new TimeInterval(begin, end);
-                // Page programInfo = action.execute();
-                // String description =
-                // programInfo.getContent().element("description").getText().trim();
-                // String keywords =
-                // programInfo.getContent().element("keywords").getText().trim();
                 String description = "";
                 String keywords = "";
+                if (!SystemProperties.isNoProgramDetailsRequired()) {
+                    try {
+                        Page programInfo = action.execute();
+                        description = programInfo.getContent().element(
+                                "description").getText().trim();
+                        keywords = programInfo.getContent().element("keywords")
+                                .getText().trim();
+                    } catch (PageException e) {
+                        LOG
+                                .warn("Program details coul dnot be determined for '"
+                                        + action.getName() + "'");
+                    }
+                }
                 Program program = new Program(aChannel, action.getName(),
                         description, keywords, interval, action);
 
@@ -279,9 +316,12 @@ public class KissCrawler {
     }
 
     /**
-     * Sends a summary mail to the user. 
-     * @param aText Text of the mail. 
-     * @throws MessagingException In case of problems sending mail. 
+     * Sends a summary mail to the user.
+     * 
+     * @param aText
+     *            Text of the mail.
+     * @throws MessagingException
+     *             In case of problems sending mail.
      */
     private void sendMail(String aText) throws MessagingException {
         Properties props = new Properties();
@@ -300,4 +340,5 @@ public class KissCrawler {
         message.setText(aText);
         Transport.send(message);
     }
+
 }
index 12f51db9e8b657689a2e08105cd3d5df62c0cfd6..f28246adf2f29528ad18bd9504a206b5a886930b 100644 (file)
@@ -17,6 +17,7 @@
 package org.wamblee.crawler.kiss;
 
 import org.wamblee.crawler.Action;
+import org.wamblee.crawler.Page;
 import org.wamblee.crawler.PageException;
 
 /**
@@ -28,6 +29,26 @@ public class Program {
      * Name of the record action on the program details page. 
      */
     private static final String RECORD_ACTION = "record";
+    
+    private static final String RESULT_ELEM = "result";
+    
+    public enum RecordingResult {
+            OK("Successfully recorded programs"), 
+            DUPLICATE("Already recorded programs"), 
+            CONFLICT("Programs in conflict with another recorded program"), 
+            OLDSHOW("Programs that occured in the past"), 
+            ERROR("Programs that could not be recorded for technical reasons");
+            
+            private String _description; 
+            
+            private RecordingResult(String aDescription) { 
+                _description = aDescription;     
+            }
+            
+            public String getDescription() { 
+                return _description; 
+            }
+    };
 
     /**
      * Indent string to use for pretty printing. 
@@ -129,13 +150,13 @@ public class Program {
      * @return True iff an attempt could be made to record the page. 
      * @throws PageException In case of problems recording the page.
      */
-    public boolean record() throws PageException {
+    public RecordingResult record() throws PageException {
         Action record = _programInfo.execute().getAction(RECORD_ACTION);
         if (record == null) {
-            return false;
+            return RecordingResult.OLDSHOW;
         }
-        record.execute();
-        return true;
+        Page result = record.execute();
+        return RecordingResult.valueOf(result.getContent().getText());    
     }
 
     /**
diff --git a/crawler/kiss/src/org/wamblee/crawler/kiss/SystemProperties.java b/crawler/kiss/src/org/wamblee/crawler/kiss/SystemProperties.java
new file mode 100644 (file)
index 0000000..60bafa1
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.wamblee.crawler.kiss;
+
+/**
+ * Access to system properties for the crawler.  
+ */
+public final class SystemProperties {
+    
+    private static final String DEBUG_PROPERTY = "kiss.debug";
+    private static final String NO_PROGRAM_DETAILS = "kiss.nodetails";
+    
+    /**
+     * Disabled constructor. 
+     *
+     */
+    private SystemProperties() { 
+        // Empty. 
+    }
+
+    /**
+     * Determines if the system is run in debug mode. When in debug mode, less extensive crawling is done. 
+     * @return True iff we are running in debug mode. 
+     */
+    public static boolean isDebugMode() { 
+        return System.getProperties().getProperty(DEBUG_PROPERTY) != null; 
+    }
+  
+    /**
+     * Determines if no program details are required. 
+     * @return True iff no program details are required. 
+     */
+    public static boolean isNoProgramDetailsRequired() { 
+        return System.getProperties().getProperty(NO_PROGRAM_DETAILS) != null; 
+    }
+}
index 54ac0f1149915a4db19be73bee6223852dfaab82..9850fdd039a66650f265eb876cd2e1706f877976 100644 (file)
@@ -17,7 +17,7 @@
    &header;
        
        <target name="module.build.deps" 
-         depends="logging.d,dom4j.d,xerces.d,spring.d">
+         depends="logging.d,commons-beanutils.d,dom4j.d,xerces.d,spring.d">
        </target>
        
        <!-- Set libraries to use in addition for test, a library which 
diff --git a/support/src/org/wamblee/conditions/AndCondition.java b/support/src/org/wamblee/conditions/AndCondition.java
new file mode 100644 (file)
index 0000000..fb77c80
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wamblee.conditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a logical and of different boolean conditions.
+ */
+public class AndCondition<T> implements Condition<T> {
+
+    private List<Condition<T>> _conditions;
+
+    /**
+     * Constructs the condition.
+     * 
+     * @param aCondition1
+     *            First condition.
+     * @param aCondition2
+     *            Second condition.
+     */
+    public AndCondition(Condition<T> aCondition1, Condition<T> aCondition2) {
+        _conditions = new ArrayList<Condition<T>>();
+        _conditions.add(aCondition1);
+        _conditions.add(aCondition2);
+    }
+
+    /**
+     * Constructs the and condition.
+     * 
+     * @param aConditions
+     *            List of conditions to use in the logical and.
+     */
+    public AndCondition(List<Condition<T>> aConditions) {
+        _conditions = aConditions;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.wamblee.crawler.kiss.ProgramMatcher#matches(org.wamblee.crawler.kiss.Program)
+     */
+    public boolean matches(T aObject) {
+        for (Condition<T> condition : _conditions) {
+            if (!condition.matches(aObject)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+}
diff --git a/support/src/org/wamblee/conditions/FixedCondition.java b/support/src/org/wamblee/conditions/FixedCondition.java
new file mode 100644 (file)
index 0000000..0626731
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.wamblee.conditions;
+
+/**
+ * Condition which always returns a fixed value. 
+ */
+public class FixedCondition<T> implements Condition<T> {
+    
+    private boolean _value; 
+    
+    /**
+     * Constructs the condition. 
+     * @param aValue Fixed value of the condition. 
+     */
+    public FixedCondition(boolean aValue) { 
+        _value = aValue; 
+    }
+
+    /* (non-Javadoc)
+     * @see org.wamblee.conditions.Condition#matches(T)
+     */
+    public boolean matches(T aObject) {
+        return _value; 
+    }
+
+}
diff --git a/support/src/org/wamblee/conditions/PropertyRegexCondition.java b/support/src/org/wamblee/conditions/PropertyRegexCondition.java
new file mode 100644 (file)
index 0000000..48df799
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.wamblee.conditions;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * Condition to check whether a given property value matches a certain 
+ * regular expression.
+ */
+public class PropertyRegexCondition<T> implements Condition<T> {
+    
+    /**
+     * Property name. 
+     */
+    private String _property;
+    
+    /**
+     * Regular expression. 
+     */
+    private Pattern _regex;
+    
+    /**
+     * Constructs the condition. 
+     * @param aProperty Name of the property to examine. 
+     * @param aRegex Regular expression to use. 
+     */
+    public PropertyRegexCondition(String aProperty, String aRegex) {
+        _property = aProperty;
+        _regex = Pattern.compile(aRegex);
+    }
+
+    /* (non-Javadoc)
+     * @see org.wamblee.conditions.Condition#matches(T)
+     */
+    public boolean matches(T aObject) {
+        try {
+            String value = PropertyUtils.getProperty(aObject, _property) + "";
+            Matcher matcher = _regex.matcher(value); 
+            return matcher.matches(); 
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+}
index 0efcc9732e58f678e112f031340bf94f11867e16..6a7a5af75e6a4174a0a5f41b21adc9d82355c042 100644 (file)
@@ -11,8 +11,6 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import sun.security.krb5.internal.ktab.l;
-
 /**
  * Utility class for performing various operations on DOM trees. 
  */