You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nutch.apache.org by th...@apache.org on 2016/07/05 22:49:49 UTC

[65/69] [abbrv] nutch git commit: Moved test sources to maven standard directory

http://git-wip-us.apache.org/repos/asf/nutch/blob/20d28406/nutch-plugins/index-replace/src/test/java/org/apache/nutch/indexer/replace/TestIndexReplace.java
----------------------------------------------------------------------
diff --git a/nutch-plugins/index-replace/src/test/java/org/apache/nutch/indexer/replace/TestIndexReplace.java b/nutch-plugins/index-replace/src/test/java/org/apache/nutch/indexer/replace/TestIndexReplace.java
new file mode 100644
index 0000000..ca90ca3
--- /dev/null
+++ b/nutch-plugins/index-replace/src/test/java/org/apache/nutch/indexer/replace/TestIndexReplace.java
@@ -0,0 +1,456 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.nutch.indexer.replace;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.io.Text;
+import org.apache.nutch.crawl.CrawlDatum;
+import org.apache.nutch.crawl.Inlinks;
+import org.apache.nutch.indexer.NutchDocument;
+import org.apache.nutch.indexer.basic.BasicIndexingFilter;
+import org.apache.nutch.indexer.metadata.MetadataIndexer;
+import org.apache.nutch.parse.Parse;
+import org.apache.nutch.parse.ParseUtil;
+import org.apache.nutch.protocol.Content;
+import org.apache.nutch.protocol.Protocol;
+import org.apache.nutch.protocol.ProtocolFactory;
+import org.apache.nutch.util.NutchConfiguration;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * JUnit tests for the <code>index-replace</code> plugin.
+ * 
+ * In these tests, the sample file has some meta tags added to the Nutch
+ * document by the <code>index-metadata</code> plugin. The
+ * <code>index-replace</code> plugin is then used to either change (or not
+ * change) the fields depending on the various values of
+ * <code>index.replace.regexp</code> property being provided to Nutch.
+ * 
+ * 
+ * @author Peter Ciuffetti
+ *
+ */
+public class TestIndexReplace {
+
+  private static final String INDEX_REPLACE_PROPERTY = "index.replace.regexp";
+
+  private String fileSeparator = System.getProperty("file.separator");
+  private String sampleDir = System.getProperty("test.data", ".");
+  private String sampleFile = "testIndexReplace.html";
+
+  /**
+   * Run a test file through the Nutch parser and index filters.
+   * 
+   * @param fileName
+   * @param conf
+   * @return the Nutch document with the replace indexer applied
+   */
+  public NutchDocument parseAndFilterFile(String fileName, Configuration conf) {
+    NutchDocument doc = new NutchDocument();
+
+    BasicIndexingFilter basicIndexer = new BasicIndexingFilter();
+    basicIndexer.setConf(conf);
+    Assert.assertNotNull(basicIndexer);
+
+    MetadataIndexer metaIndexer = new MetadataIndexer();
+    metaIndexer.setConf(conf);
+    Assert.assertNotNull(basicIndexer);
+
+    ReplaceIndexer replaceIndexer = new ReplaceIndexer();
+    replaceIndexer.setConf(conf);
+    Assert.assertNotNull(replaceIndexer);
+
+    try {
+      String urlString = "file:" + sampleDir + fileSeparator + fileName;
+      Text text = new Text(urlString);
+      CrawlDatum crawlDatum = new CrawlDatum();
+      Protocol protocol = new ProtocolFactory(conf).getProtocol(urlString);
+      Content content = protocol.getProtocolOutput(text, crawlDatum)
+          .getContent();
+      Parse parse = new ParseUtil(conf).parse(content).get(content.getUrl());
+      crawlDatum.setFetchTime(100L);
+
+      Inlinks inlinks = new Inlinks();
+      doc = basicIndexer.filter(doc, parse, text, crawlDatum, inlinks);
+      doc = metaIndexer.filter(doc, parse, text, crawlDatum, inlinks);
+      doc = replaceIndexer.filter(doc, parse, text, crawlDatum, inlinks);
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.toString());
+    }
+
+    return doc;
+  }
+
+  /**
+   * Test property parsing.
+   * 
+   * The filter does not expose details of the parse. So all we are checking is
+   * that the parse does not throw a runtime exception and that the value
+   * provided is the value returned.
+   */
+  @Test
+  public void testPropertyParse() {
+    Configuration conf = NutchConfiguration.create();
+    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this awesome plugin/2\n"
+        + "  metatag.keywords=/\\,/\\!/\n"
+        + "  hostmatch=.*.com\n"
+        + "  metatag.keywords=/\\,/\\?/\n"
+        + "  metatag.author:dc_author=/\\s+/ David /\n"
+        + "  urlmatch=.*.html\n"
+        + "  metatag.keywords=/\\,/\\./\n" + "  metatag.author=/\\s+/ D. /\n";
+
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+
+    ReplaceIndexer rp = new ReplaceIndexer();
+    try {
+      rp.setConf(conf);
+    } catch (RuntimeException ohno) {
+      Assert.fail("Unable to parse a valid index.replace.regexp property! "
+          + ohno.getMessage());
+    }
+
+    Configuration parsedConf = rp.getConf();
+
+    // Does the getter equal the setter? Too easy!
+    Assert.assertEquals(indexReplaceProperty,
+        parsedConf.get(INDEX_REPLACE_PROPERTY));
+  }
+
+  /**
+   * Test metatag value replacement using global replacement settings.
+   * 
+   * The index.replace.regexp property does not use hostmatch or urlmatch, so
+   * all patterns are global.
+   */
+  @Test
+  public void testGlobalReplacement() {
+    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String expectedKeywords = "Breathtaking! Riveting! Two Thumbs Up!";
+    String expectedAuthor = "Peter D. Ciuffetti";
+    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this awesome plugin/\n"
+        + "  metatag.keywords=/\\,/\\!/\n" + "  metatag.author=/\\s+/ D. /\n";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    Assert
+        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
+    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
+  }
+
+  /**
+   * Test that invalid property settings are handled and ignored.
+   * 
+   * This test provides an invalid property setting that will fail property
+   * parsing and Pattern.compile. The expected outcome is that the patterns will
+   * not cause failure and the targeted fields will not be modified by the
+   * filter.
+   */
+  @Test
+  public void testInvalidPatterns() {
+    String expectedDescription = "With this plugin, I control the description! Bwuhuhuhaha!";
+    String expectedKeywords = "Breathtaking, Riveting, Two Thumbs Up!";
+    String expectedAuthor = "Peter Ciuffetti";
+    // Contains: invalid pattern, invalid flags, incomplete property
+    String indexReplaceProperty = "  metatag.description=/this\\s+**plugin/this awesome plugin/\n"
+        + "  metatag.keywords=/\\,/\\!/what\n" + " metatag.author=#notcomplete";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Assert that our metatags have not changed.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    Assert
+        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
+    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
+
+  }
+
+  /**
+   * Test URL pattern matching
+   */
+  @Test
+  public void testUrlMatchesPattern() {
+    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String expectedKeywords = "Breathtaking! Riveting! Two Thumbs Up!";
+    String expectedAuthor = "Peter D. Ciuffetti";
+    String indexReplaceProperty = " urlmatch=.*.html\n"
+        + "  metatag.description=/this(.*)plugin/this awesome plugin/\n"
+        + "  metatag.keywords=/\\,/\\!/\n" + "  metatag.author=/\\s+/ D. /\n";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Assert that our metatags have changed.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    Assert
+        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
+    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
+
+  }
+
+  /**
+   * Test URL pattern not matching.
+   * 
+   * Expected result is that the filter does not change the fields.
+   */
+  @Test
+  public void testUrlNotMatchesPattern() {
+    String expectedDescription = "With this plugin, I control the description! Bwuhuhuhaha!";
+    String expectedKeywords = "Breathtaking, Riveting, Two Thumbs Up!";
+    String expectedAuthor = "Peter Ciuffetti";
+    String indexReplaceProperty = " urlmatch=.*.xml\n"
+        + "  metatag.description=/this(.*)plugin/this awesome plugin/\n"
+        + "  metatag.keywords=/\\,/\\!/\n" + "  metatag.author=/\\s+/ D. /\n";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Assert that our metatags have not changed.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    Assert
+        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
+    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
+
+  }
+
+  /**
+   * Test a global pattern match for description and URL pattern match for
+   * keywords and author.
+   * 
+   * All three should be triggered. It also tests replacement groups.
+   */
+  @Test
+  public void testGlobalAndUrlMatchesPattern() {
+    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String expectedKeywords = "Breathtaking! Riveting! Two Thumbs Up!";
+    String expectedAuthor = "Peter D. Ciuffetti";
+    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this$1awesome$1plugin/\n"
+        + "  urlmatch=.*.html\n"
+        + "  metatag.keywords=/\\,/\\!/\n"
+        + "  metatag.author=/\\s+/ D. /\n";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Assert that our metatags have changed.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    Assert
+        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
+    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
+
+  }
+
+  /**
+   * Test a global pattern match for description and URL pattern match for
+   * keywords and author.
+   * 
+   * Only the global match should be triggered.
+   */
+  @Test
+  public void testGlobalAndUrlNotMatchesPattern() {
+    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String expectedKeywords = "Breathtaking, Riveting, Two Thumbs Up!";
+    String expectedAuthor = "Peter Ciuffetti";
+    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this$1awesome$1plugin/\n"
+        + "  urlmatch=.*.xml\n"
+        + "  metatag.keywords=/\\,/\\!/\n"
+        + "  metatag.author=/\\s+/ D. /\n";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Assert that description has changed and the others have not changed.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    Assert
+        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
+    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
+  }
+
+  /**
+   * Test order-specific replacement settings.
+   * 
+   * This makes multiple replacements on the same field and will produce the
+   * expected value only if the replacements are run in the order specified.
+   */
+  @Test
+  public void testReplacementsRunInSpecifedOrder() {
+    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String indexReplaceProperty = "  metatag.description=/this plugin/this amazing plugin/\n"
+        + "  metatag.description=/this amazing plugin/this valuable plugin/\n"
+        + "  metatag.description=/this valuable plugin/this cool plugin/\n"
+        + "  metatag.description=/this cool plugin/this wicked plugin/\n"
+        + "  metatag.description=/this wicked plugin/this awesome plugin/\n";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Check that the value produced by the last replacement has worked.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+  }
+
+  /**
+   * Test a replacement pattern that uses the flags feature.
+   * 
+   * A 2 is Pattern.CASE_INSENSITIVE. We look for upper case and expect to match
+   * any case.
+   */
+  @Test
+  public void testReplacementsWithFlags() {
+    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String indexReplaceProperty = "  metatag.description=/THIS PLUGIN/this awesome plugin/2";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Check that the value produced by the case-insensitive replacement has
+    // worked.
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+  }
+
+  /**
+   * Test a replacement pattern that uses the target field feature.
+   * Check that the input is not modifid and that the taret field is added.
+   */
+  @Test
+  public void testReplacementsDifferentTarget() {
+    String expectedDescription = "With this plugin, I control the description! Bwuhuhuhaha!";
+    String expectedTargetDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
+    String indexReplaceProperty = "  metatag.description:new=/this plugin/this awesome plugin/";
+
+    Configuration conf = NutchConfiguration.create();
+    conf.set(
+        "plugin.includes",
+        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
+    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
+    conf.set("metatags.names", "author,description,keywords");
+    conf.set("index.parse.md",
+        "metatag.author,metatag.description,metatag.keywords");
+    // Not necessary but helpful when debugging the filter.
+    conf.set("http.timeout", "99999999999");
+
+    // Run the document through the parser and index filters.
+    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
+
+    // Check that the input field has not been modified
+    Assert.assertEquals(expectedDescription,
+        doc.getFieldValue("metatag.description"));
+    // Check that the output field has created
+    Assert.assertEquals(expectedTargetDescription,
+        doc.getFieldValue("new"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/nutch/blob/20d28406/nutch-plugins/index-replace/src/test/org/apache/nutch/indexer/replace/TestIndexReplace.java
----------------------------------------------------------------------
diff --git a/nutch-plugins/index-replace/src/test/org/apache/nutch/indexer/replace/TestIndexReplace.java b/nutch-plugins/index-replace/src/test/org/apache/nutch/indexer/replace/TestIndexReplace.java
deleted file mode 100644
index ca90ca3..0000000
--- a/nutch-plugins/index-replace/src/test/org/apache/nutch/indexer/replace/TestIndexReplace.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.nutch.indexer.replace;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.io.Text;
-import org.apache.nutch.crawl.CrawlDatum;
-import org.apache.nutch.crawl.Inlinks;
-import org.apache.nutch.indexer.NutchDocument;
-import org.apache.nutch.indexer.basic.BasicIndexingFilter;
-import org.apache.nutch.indexer.metadata.MetadataIndexer;
-import org.apache.nutch.parse.Parse;
-import org.apache.nutch.parse.ParseUtil;
-import org.apache.nutch.protocol.Content;
-import org.apache.nutch.protocol.Protocol;
-import org.apache.nutch.protocol.ProtocolFactory;
-import org.apache.nutch.util.NutchConfiguration;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * JUnit tests for the <code>index-replace</code> plugin.
- * 
- * In these tests, the sample file has some meta tags added to the Nutch
- * document by the <code>index-metadata</code> plugin. The
- * <code>index-replace</code> plugin is then used to either change (or not
- * change) the fields depending on the various values of
- * <code>index.replace.regexp</code> property being provided to Nutch.
- * 
- * 
- * @author Peter Ciuffetti
- *
- */
-public class TestIndexReplace {
-
-  private static final String INDEX_REPLACE_PROPERTY = "index.replace.regexp";
-
-  private String fileSeparator = System.getProperty("file.separator");
-  private String sampleDir = System.getProperty("test.data", ".");
-  private String sampleFile = "testIndexReplace.html";
-
-  /**
-   * Run a test file through the Nutch parser and index filters.
-   * 
-   * @param fileName
-   * @param conf
-   * @return the Nutch document with the replace indexer applied
-   */
-  public NutchDocument parseAndFilterFile(String fileName, Configuration conf) {
-    NutchDocument doc = new NutchDocument();
-
-    BasicIndexingFilter basicIndexer = new BasicIndexingFilter();
-    basicIndexer.setConf(conf);
-    Assert.assertNotNull(basicIndexer);
-
-    MetadataIndexer metaIndexer = new MetadataIndexer();
-    metaIndexer.setConf(conf);
-    Assert.assertNotNull(basicIndexer);
-
-    ReplaceIndexer replaceIndexer = new ReplaceIndexer();
-    replaceIndexer.setConf(conf);
-    Assert.assertNotNull(replaceIndexer);
-
-    try {
-      String urlString = "file:" + sampleDir + fileSeparator + fileName;
-      Text text = new Text(urlString);
-      CrawlDatum crawlDatum = new CrawlDatum();
-      Protocol protocol = new ProtocolFactory(conf).getProtocol(urlString);
-      Content content = protocol.getProtocolOutput(text, crawlDatum)
-          .getContent();
-      Parse parse = new ParseUtil(conf).parse(content).get(content.getUrl());
-      crawlDatum.setFetchTime(100L);
-
-      Inlinks inlinks = new Inlinks();
-      doc = basicIndexer.filter(doc, parse, text, crawlDatum, inlinks);
-      doc = metaIndexer.filter(doc, parse, text, crawlDatum, inlinks);
-      doc = replaceIndexer.filter(doc, parse, text, crawlDatum, inlinks);
-    } catch (Exception e) {
-      e.printStackTrace();
-      Assert.fail(e.toString());
-    }
-
-    return doc;
-  }
-
-  /**
-   * Test property parsing.
-   * 
-   * The filter does not expose details of the parse. So all we are checking is
-   * that the parse does not throw a runtime exception and that the value
-   * provided is the value returned.
-   */
-  @Test
-  public void testPropertyParse() {
-    Configuration conf = NutchConfiguration.create();
-    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this awesome plugin/2\n"
-        + "  metatag.keywords=/\\,/\\!/\n"
-        + "  hostmatch=.*.com\n"
-        + "  metatag.keywords=/\\,/\\?/\n"
-        + "  metatag.author:dc_author=/\\s+/ David /\n"
-        + "  urlmatch=.*.html\n"
-        + "  metatag.keywords=/\\,/\\./\n" + "  metatag.author=/\\s+/ D. /\n";
-
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-
-    ReplaceIndexer rp = new ReplaceIndexer();
-    try {
-      rp.setConf(conf);
-    } catch (RuntimeException ohno) {
-      Assert.fail("Unable to parse a valid index.replace.regexp property! "
-          + ohno.getMessage());
-    }
-
-    Configuration parsedConf = rp.getConf();
-
-    // Does the getter equal the setter? Too easy!
-    Assert.assertEquals(indexReplaceProperty,
-        parsedConf.get(INDEX_REPLACE_PROPERTY));
-  }
-
-  /**
-   * Test metatag value replacement using global replacement settings.
-   * 
-   * The index.replace.regexp property does not use hostmatch or urlmatch, so
-   * all patterns are global.
-   */
-  @Test
-  public void testGlobalReplacement() {
-    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String expectedKeywords = "Breathtaking! Riveting! Two Thumbs Up!";
-    String expectedAuthor = "Peter D. Ciuffetti";
-    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this awesome plugin/\n"
-        + "  metatag.keywords=/\\,/\\!/\n" + "  metatag.author=/\\s+/ D. /\n";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    Assert
-        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
-    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
-  }
-
-  /**
-   * Test that invalid property settings are handled and ignored.
-   * 
-   * This test provides an invalid property setting that will fail property
-   * parsing and Pattern.compile. The expected outcome is that the patterns will
-   * not cause failure and the targeted fields will not be modified by the
-   * filter.
-   */
-  @Test
-  public void testInvalidPatterns() {
-    String expectedDescription = "With this plugin, I control the description! Bwuhuhuhaha!";
-    String expectedKeywords = "Breathtaking, Riveting, Two Thumbs Up!";
-    String expectedAuthor = "Peter Ciuffetti";
-    // Contains: invalid pattern, invalid flags, incomplete property
-    String indexReplaceProperty = "  metatag.description=/this\\s+**plugin/this awesome plugin/\n"
-        + "  metatag.keywords=/\\,/\\!/what\n" + " metatag.author=#notcomplete";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Assert that our metatags have not changed.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    Assert
-        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
-    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
-
-  }
-
-  /**
-   * Test URL pattern matching
-   */
-  @Test
-  public void testUrlMatchesPattern() {
-    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String expectedKeywords = "Breathtaking! Riveting! Two Thumbs Up!";
-    String expectedAuthor = "Peter D. Ciuffetti";
-    String indexReplaceProperty = " urlmatch=.*.html\n"
-        + "  metatag.description=/this(.*)plugin/this awesome plugin/\n"
-        + "  metatag.keywords=/\\,/\\!/\n" + "  metatag.author=/\\s+/ D. /\n";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Assert that our metatags have changed.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    Assert
-        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
-    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
-
-  }
-
-  /**
-   * Test URL pattern not matching.
-   * 
-   * Expected result is that the filter does not change the fields.
-   */
-  @Test
-  public void testUrlNotMatchesPattern() {
-    String expectedDescription = "With this plugin, I control the description! Bwuhuhuhaha!";
-    String expectedKeywords = "Breathtaking, Riveting, Two Thumbs Up!";
-    String expectedAuthor = "Peter Ciuffetti";
-    String indexReplaceProperty = " urlmatch=.*.xml\n"
-        + "  metatag.description=/this(.*)plugin/this awesome plugin/\n"
-        + "  metatag.keywords=/\\,/\\!/\n" + "  metatag.author=/\\s+/ D. /\n";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Assert that our metatags have not changed.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    Assert
-        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
-    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
-
-  }
-
-  /**
-   * Test a global pattern match for description and URL pattern match for
-   * keywords and author.
-   * 
-   * All three should be triggered. It also tests replacement groups.
-   */
-  @Test
-  public void testGlobalAndUrlMatchesPattern() {
-    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String expectedKeywords = "Breathtaking! Riveting! Two Thumbs Up!";
-    String expectedAuthor = "Peter D. Ciuffetti";
-    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this$1awesome$1plugin/\n"
-        + "  urlmatch=.*.html\n"
-        + "  metatag.keywords=/\\,/\\!/\n"
-        + "  metatag.author=/\\s+/ D. /\n";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Assert that our metatags have changed.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    Assert
-        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
-    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
-
-  }
-
-  /**
-   * Test a global pattern match for description and URL pattern match for
-   * keywords and author.
-   * 
-   * Only the global match should be triggered.
-   */
-  @Test
-  public void testGlobalAndUrlNotMatchesPattern() {
-    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String expectedKeywords = "Breathtaking, Riveting, Two Thumbs Up!";
-    String expectedAuthor = "Peter Ciuffetti";
-    String indexReplaceProperty = "  metatag.description=/this(.*)plugin/this$1awesome$1plugin/\n"
-        + "  urlmatch=.*.xml\n"
-        + "  metatag.keywords=/\\,/\\!/\n"
-        + "  metatag.author=/\\s+/ D. /\n";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Assert that description has changed and the others have not changed.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    Assert
-        .assertEquals(expectedKeywords, doc.getFieldValue("metatag.keywords"));
-    Assert.assertEquals(expectedAuthor, doc.getFieldValue("metatag.author"));
-  }
-
-  /**
-   * Test order-specific replacement settings.
-   * 
-   * This makes multiple replacements on the same field and will produce the
-   * expected value only if the replacements are run in the order specified.
-   */
-  @Test
-  public void testReplacementsRunInSpecifedOrder() {
-    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String indexReplaceProperty = "  metatag.description=/this plugin/this amazing plugin/\n"
-        + "  metatag.description=/this amazing plugin/this valuable plugin/\n"
-        + "  metatag.description=/this valuable plugin/this cool plugin/\n"
-        + "  metatag.description=/this cool plugin/this wicked plugin/\n"
-        + "  metatag.description=/this wicked plugin/this awesome plugin/\n";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Check that the value produced by the last replacement has worked.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-  }
-
-  /**
-   * Test a replacement pattern that uses the flags feature.
-   * 
-   * A 2 is Pattern.CASE_INSENSITIVE. We look for upper case and expect to match
-   * any case.
-   */
-  @Test
-  public void testReplacementsWithFlags() {
-    String expectedDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String indexReplaceProperty = "  metatag.description=/THIS PLUGIN/this awesome plugin/2";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Check that the value produced by the case-insensitive replacement has
-    // worked.
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-  }
-
-  /**
-   * Test a replacement pattern that uses the target field feature.
-   * Check that the input is not modifid and that the taret field is added.
-   */
-  @Test
-  public void testReplacementsDifferentTarget() {
-    String expectedDescription = "With this plugin, I control the description! Bwuhuhuhaha!";
-    String expectedTargetDescription = "With this awesome plugin, I control the description! Bwuhuhuhaha!";
-    String indexReplaceProperty = "  metatag.description:new=/this plugin/this awesome plugin/";
-
-    Configuration conf = NutchConfiguration.create();
-    conf.set(
-        "plugin.includes",
-        "protocol-file|urlfilter-regex|parse-(html|metatags)|index-(basic|anchor|metadata|static|replace)|urlnormalizer-(pass|regex|basic)");
-    conf.set(INDEX_REPLACE_PROPERTY, indexReplaceProperty);
-    conf.set("metatags.names", "author,description,keywords");
-    conf.set("index.parse.md",
-        "metatag.author,metatag.description,metatag.keywords");
-    // Not necessary but helpful when debugging the filter.
-    conf.set("http.timeout", "99999999999");
-
-    // Run the document through the parser and index filters.
-    NutchDocument doc = parseAndFilterFile(sampleFile, conf);
-
-    // Check that the input field has not been modified
-    Assert.assertEquals(expectedDescription,
-        doc.getFieldValue("metatag.description"));
-    // Check that the output field has created
-    Assert.assertEquals(expectedTargetDescription,
-        doc.getFieldValue("new"));
-  }
-}

http://git-wip-us.apache.org/repos/asf/nutch/blob/20d28406/nutch-plugins/index-static/src/test/java/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java
----------------------------------------------------------------------
diff --git a/nutch-plugins/index-static/src/test/java/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java b/nutch-plugins/index-static/src/test/java/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java
new file mode 100644
index 0000000..42cd46d
--- /dev/null
+++ b/nutch-plugins/index-static/src/test/java/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.nutch.indexer.staticfield;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.io.Text;
+import org.apache.nutch.crawl.CrawlDatum;
+import org.apache.nutch.crawl.Inlinks;
+import org.apache.nutch.indexer.NutchDocument;
+import org.apache.nutch.parse.ParseImpl;
+import org.apache.nutch.util.NutchConfiguration;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * JUnit test case which tests 1. that static data fields are added to a
+ * document 2. that empty {@code index.static} does not add anything to the
+ * document 3. that valid field:value pairs are added to the document 4. that
+ * fields and values added to the document are trimmed
+ * 
+ * @author tejasp
+ */
+
+public class TestStaticFieldIndexerTest {
+
+  Configuration conf;
+
+  Inlinks inlinks;
+  ParseImpl parse;
+  CrawlDatum crawlDatum;
+  Text url;
+  StaticFieldIndexer filter;
+
+  @Before
+  public void setUp() throws Exception {
+    conf = NutchConfiguration.create();
+    parse = new ParseImpl();
+    url = new Text("http://nutch.apache.org/index.html");
+    crawlDatum = new CrawlDatum();
+    inlinks = new Inlinks();
+    filter = new StaticFieldIndexer();
+  }
+
+  /**
+   * Test that empty {@code index.static} does not add anything to the document
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void testEmptyIndexStatic() throws Exception {
+
+    Assert.assertNotNull(filter);
+    filter.setConf(conf);
+
+    NutchDocument doc = new NutchDocument();
+
+    try {
+      filter.filter(doc, parse, url, crawlDatum, inlinks);
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+
+    Assert.assertNotNull(doc);
+    Assert.assertTrue("tests if no field is set for empty index.static", doc
+        .getFieldNames().isEmpty());
+  }
+
+  /**
+   * Test that valid field:value pairs are added to the document
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void testNormalScenario() throws Exception {
+
+    conf.set("index.static",
+        "field1:val1, field2    :      val2 val3     , field3, field4 :val4 , ");
+    Assert.assertNotNull(filter);
+    filter.setConf(conf);
+
+    NutchDocument doc = new NutchDocument();
+
+    try {
+      filter.filter(doc, parse, url, crawlDatum, inlinks);
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+
+    Assert.assertNotNull(doc);
+    Assert.assertFalse("test if doc is not empty", doc.getFieldNames()
+        .isEmpty());
+    Assert.assertEquals("test if doc has 3 fields", 3, doc.getFieldNames()
+        .size());
+    Assert.assertTrue("test if doc has field1", doc.getField("field1")
+        .getValues().contains("val1"));
+    Assert.assertTrue("test if doc has field2", doc.getField("field2")
+        .getValues().contains("val2"));
+    Assert.assertTrue("test if doc has field4", doc.getField("field4")
+        .getValues().contains("val4"));
+  }
+
+  /**
+   * Test for NUTCH-2052 custom delimiters in index.static.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testCustomDelimiters() throws Exception {
+
+    conf.set("index.static.fieldsep", ">");
+    conf.set("index.static.keysep", "=");
+    conf.set("index.static.valuesep", "|");
+    conf.set("index.static",
+        "field1=val1>field2    =      val2|val3     >field3>field4 =val4 > ");
+    Assert.assertNotNull(filter);
+    filter.setConf(conf);
+
+    NutchDocument doc = new NutchDocument();
+
+    try {
+      filter.filter(doc, parse, url, crawlDatum, inlinks);
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+
+    Assert.assertNotNull(doc);
+    Assert.assertFalse("test if doc is not empty", doc.getFieldNames()
+        .isEmpty());
+    Assert.assertEquals("test if doc has 3 fields", 3, doc.getFieldNames()
+        .size());
+    Assert.assertTrue("test if doc has field1", doc.getField("field1")
+        .getValues().contains("val1"));
+    Assert.assertTrue("test if doc has field2", doc.getField("field2")
+        .getValues().contains("val2"));
+    Assert.assertTrue("test if doc has field4", doc.getField("field4")
+        .getValues().contains("val4"));
+  }
+
+  /**
+   * Test for NUTCH-2052 custom delimiters in index.static.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testCustomMulticharacterDelimiters() throws Exception {
+
+    conf.set("index.static.fieldsep", "\n\n");
+    conf.set("index.static.keysep", "\t\t");
+    conf.set("index.static.valuesep", "***");
+    conf.set("index.static", "field1\t\tval1\n\n" + "field2\t\tval2***val3\n\n"
+        + "field3\n\n" + "field4\t\tval4\n\n\n\n");
+    Assert.assertNotNull(filter);
+    filter.setConf(conf);
+
+    NutchDocument doc = new NutchDocument();
+
+    try {
+      filter.filter(doc, parse, url, crawlDatum, inlinks);
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+
+    Assert.assertNotNull(doc);
+    Assert.assertFalse("test if doc is not empty", doc.getFieldNames()
+        .isEmpty());
+    Assert.assertEquals("test if doc has 3 fields", 3, doc.getFieldNames()
+        .size());
+    Assert.assertTrue("test if doc has field1", doc.getField("field1")
+        .getValues().contains("val1"));
+    Assert.assertTrue("test if doc has field2", doc.getField("field2")
+        .getValues().contains("val2"));
+    Assert.assertTrue("test if doc has field4", doc.getField("field4")
+        .getValues().contains("val4"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/nutch/blob/20d28406/nutch-plugins/index-static/src/test/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java
----------------------------------------------------------------------
diff --git a/nutch-plugins/index-static/src/test/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java b/nutch-plugins/index-static/src/test/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java
deleted file mode 100644
index 42cd46d..0000000
--- a/nutch-plugins/index-static/src/test/org/apache/nutch/indexer/staticfield/TestStaticFieldIndexerTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.nutch.indexer.staticfield;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.io.Text;
-import org.apache.nutch.crawl.CrawlDatum;
-import org.apache.nutch.crawl.Inlinks;
-import org.apache.nutch.indexer.NutchDocument;
-import org.apache.nutch.parse.ParseImpl;
-import org.apache.nutch.util.NutchConfiguration;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * JUnit test case which tests 1. that static data fields are added to a
- * document 2. that empty {@code index.static} does not add anything to the
- * document 3. that valid field:value pairs are added to the document 4. that
- * fields and values added to the document are trimmed
- * 
- * @author tejasp
- */
-
-public class TestStaticFieldIndexerTest {
-
-  Configuration conf;
-
-  Inlinks inlinks;
-  ParseImpl parse;
-  CrawlDatum crawlDatum;
-  Text url;
-  StaticFieldIndexer filter;
-
-  @Before
-  public void setUp() throws Exception {
-    conf = NutchConfiguration.create();
-    parse = new ParseImpl();
-    url = new Text("http://nutch.apache.org/index.html");
-    crawlDatum = new CrawlDatum();
-    inlinks = new Inlinks();
-    filter = new StaticFieldIndexer();
-  }
-
-  /**
-   * Test that empty {@code index.static} does not add anything to the document
-   * 
-   * @throws Exception
-   */
-  @Test
-  public void testEmptyIndexStatic() throws Exception {
-
-    Assert.assertNotNull(filter);
-    filter.setConf(conf);
-
-    NutchDocument doc = new NutchDocument();
-
-    try {
-      filter.filter(doc, parse, url, crawlDatum, inlinks);
-    } catch (Exception e) {
-      e.printStackTrace();
-      Assert.fail(e.getMessage());
-    }
-
-    Assert.assertNotNull(doc);
-    Assert.assertTrue("tests if no field is set for empty index.static", doc
-        .getFieldNames().isEmpty());
-  }
-
-  /**
-   * Test that valid field:value pairs are added to the document
-   * 
-   * @throws Exception
-   */
-  @Test
-  public void testNormalScenario() throws Exception {
-
-    conf.set("index.static",
-        "field1:val1, field2    :      val2 val3     , field3, field4 :val4 , ");
-    Assert.assertNotNull(filter);
-    filter.setConf(conf);
-
-    NutchDocument doc = new NutchDocument();
-
-    try {
-      filter.filter(doc, parse, url, crawlDatum, inlinks);
-    } catch (Exception e) {
-      e.printStackTrace();
-      Assert.fail(e.getMessage());
-    }
-
-    Assert.assertNotNull(doc);
-    Assert.assertFalse("test if doc is not empty", doc.getFieldNames()
-        .isEmpty());
-    Assert.assertEquals("test if doc has 3 fields", 3, doc.getFieldNames()
-        .size());
-    Assert.assertTrue("test if doc has field1", doc.getField("field1")
-        .getValues().contains("val1"));
-    Assert.assertTrue("test if doc has field2", doc.getField("field2")
-        .getValues().contains("val2"));
-    Assert.assertTrue("test if doc has field4", doc.getField("field4")
-        .getValues().contains("val4"));
-  }
-
-  /**
-   * Test for NUTCH-2052 custom delimiters in index.static.
-   *
-   * @throws Exception
-   */
-  @Test
-  public void testCustomDelimiters() throws Exception {
-
-    conf.set("index.static.fieldsep", ">");
-    conf.set("index.static.keysep", "=");
-    conf.set("index.static.valuesep", "|");
-    conf.set("index.static",
-        "field1=val1>field2    =      val2|val3     >field3>field4 =val4 > ");
-    Assert.assertNotNull(filter);
-    filter.setConf(conf);
-
-    NutchDocument doc = new NutchDocument();
-
-    try {
-      filter.filter(doc, parse, url, crawlDatum, inlinks);
-    } catch (Exception e) {
-      e.printStackTrace();
-      Assert.fail(e.getMessage());
-    }
-
-    Assert.assertNotNull(doc);
-    Assert.assertFalse("test if doc is not empty", doc.getFieldNames()
-        .isEmpty());
-    Assert.assertEquals("test if doc has 3 fields", 3, doc.getFieldNames()
-        .size());
-    Assert.assertTrue("test if doc has field1", doc.getField("field1")
-        .getValues().contains("val1"));
-    Assert.assertTrue("test if doc has field2", doc.getField("field2")
-        .getValues().contains("val2"));
-    Assert.assertTrue("test if doc has field4", doc.getField("field4")
-        .getValues().contains("val4"));
-  }
-
-  /**
-   * Test for NUTCH-2052 custom delimiters in index.static.
-   *
-   * @throws Exception
-   */
-  @Test
-  public void testCustomMulticharacterDelimiters() throws Exception {
-
-    conf.set("index.static.fieldsep", "\n\n");
-    conf.set("index.static.keysep", "\t\t");
-    conf.set("index.static.valuesep", "***");
-    conf.set("index.static", "field1\t\tval1\n\n" + "field2\t\tval2***val3\n\n"
-        + "field3\n\n" + "field4\t\tval4\n\n\n\n");
-    Assert.assertNotNull(filter);
-    filter.setConf(conf);
-
-    NutchDocument doc = new NutchDocument();
-
-    try {
-      filter.filter(doc, parse, url, crawlDatum, inlinks);
-    } catch (Exception e) {
-      e.printStackTrace();
-      Assert.fail(e.getMessage());
-    }
-
-    Assert.assertNotNull(doc);
-    Assert.assertFalse("test if doc is not empty", doc.getFieldNames()
-        .isEmpty());
-    Assert.assertEquals("test if doc has 3 fields", 3, doc.getFieldNames()
-        .size());
-    Assert.assertTrue("test if doc has field1", doc.getField("field1")
-        .getValues().contains("val1"));
-    Assert.assertTrue("test if doc has field2", doc.getField("field2")
-        .getValues().contains("val2"));
-    Assert.assertTrue("test if doc has field4", doc.getField("field4")
-        .getValues().contains("val4"));
-  }
-}

http://git-wip-us.apache.org/repos/asf/nutch/blob/20d28406/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java
----------------------------------------------------------------------
diff --git a/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java b/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java
new file mode 100644
index 0000000..8245151
--- /dev/null
+++ b/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java
@@ -0,0 +1,149 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.nutch.analysis.lang;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+// Nutch imports
+import org.apache.nutch.metadata.Metadata;
+import org.apache.nutch.parse.Parse;
+import org.apache.nutch.parse.ParseUtil;
+import org.apache.nutch.protocol.Content;
+import org.apache.nutch.util.NutchConfiguration;
+import org.apache.tika.language.LanguageIdentifier;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestHTMLLanguageParser {
+
+  private static String URL = "http://foo.bar/";
+
+  private static String BASE = "http://foo.bar/";
+
+  String docs[] = {
+      "<html lang=\"fi\"><head>document 1 title</head><body>jotain suomeksi</body></html>",
+      "<html><head><meta http-equiv=\"content-language\" content=\"en\"><title>document 2 title</head><body>this is english</body></html>",
+      "<html><head><meta name=\"dc.language\" content=\"en\"><title>document 3 title</head><body>this is english</body></html>" };
+
+  // Tika does not return "fi" but null
+  String metalanguages[] = { "fi", "en", "en" };
+
+  /**
+   * Test parsing of language identifiers from html
+   **/
+  @Test
+  public void testMetaHTMLParsing() {
+
+    try {
+      ParseUtil parser = new ParseUtil(NutchConfiguration.create());
+      /* loop through the test documents and validate result */
+      for (int t = 0; t < docs.length; t++) {
+        Content content = getContent(docs[t]);
+        Parse parse = parser.parse(content).get(content.getUrl());
+        Assert.assertEquals(metalanguages[t], (String) parse.getData()
+            .getParseMeta().get(Metadata.LANGUAGE));
+      }
+    } catch (Exception e) {
+      e.printStackTrace(System.out);
+      Assert.fail(e.toString());
+    }
+
+  }
+
+  /** Test of <code>LanguageParser.parseLanguage(String)</code> method. */
+  @Test
+  public void testParseLanguage() {
+    String tests[][] = { { "(SCHEME=ISO.639-1) sv", "sv" },
+        { "(SCHEME=RFC1766) sv-FI", "sv" }, { "(SCHEME=Z39.53) SWE", "sv" },
+        { "EN_US, SV, EN, EN_UK", "en" }, { "English Swedish", "en" },
+        { "English, swedish", "en" }, { "English,Swedish", "en" },
+        { "Other (Svenska)", "sv" }, { "SE", "se" }, { "SV", "sv" },
+        { "SV charset=iso-8859-1", "sv" }, { "SV-FI", "sv" },
+        { "SV; charset=iso-8859-1", "sv" }, { "SVE", "sv" }, { "SW", "sw" },
+        { "SWE", "sv" }, { "SWEDISH", "sv" }, { "Sv", "sv" }, { "Sve", "sv" },
+        { "Svenska", "sv" }, { "Swedish", "sv" }, { "Swedish, svenska", "sv" },
+        { "en, sv", "en" }, { "sv", "sv" },
+        { "sv, be, dk, de, fr, no, pt, ch, fi, en", "sv" }, { "sv,en", "sv" },
+        { "sv-FI", "sv" }, { "sv-SE", "sv" }, { "sv-en", "sv" },
+        { "sv-fi", "sv" }, { "sv-se", "sv" },
+        { "sv; Content-Language: sv", "sv" }, { "sv_SE", "sv" },
+        { "sve", "sv" }, { "svenska, swedish, engelska, english", "sv" },
+        { "sw", "sw" }, { "swe", "sv" }, { "swe.SPR.", "sv" },
+        { "sweden", "sv" }, { "swedish", "sv" }, { "swedish,", "sv" },
+        { "text/html; charset=sv-SE", "sv" }, { "text/html; sv", "sv" },
+        { "torp, stuga, uthyres, bed & breakfast", null } };
+
+    for (int i = 0; i < 44; i++) {
+      Assert.assertEquals(tests[i][1],
+          HTMLLanguageParser.LanguageParser.parseLanguage(tests[i][0]));
+    }
+  }
+
+  private Content getContent(String text) {
+    Metadata meta = new Metadata();
+    meta.add("Content-Type", "text/html");
+    return new Content(URL, BASE, text.getBytes(), "text/html", meta,
+        NutchConfiguration.create());
+  }
+
+  @Test
+  public void testLanguageIndentifier() {
+    try {
+      long total = 0;
+      LanguageIdentifier identifier;
+      BufferedReader in = new BufferedReader(new InputStreamReader(this
+          .getClass().getResourceAsStream("test-referencial.txt")));
+      String line = null;
+      while ((line = in.readLine()) != null) {
+        String[] tokens = line.split(";");
+        if (!tokens[0].equals("")) {
+          StringBuilder content = new StringBuilder();
+          // Test each line of the file...
+          BufferedReader testFile = new BufferedReader(new InputStreamReader(
+              this.getClass().getResourceAsStream(tokens[0]), "UTF-8"));
+          String testLine = null, lang = null;
+          while ((testLine = testFile.readLine()) != null) {
+            content.append(testLine + "\n");
+            testLine = testLine.trim();
+            if (testLine.length() > 256) {
+              identifier = new LanguageIdentifier(testLine);
+              lang = identifier.getLanguage();
+              Assert.assertEquals(tokens[1], lang);
+            }
+          }
+          testFile.close();
+
+          // Test the whole file
+          long start = System.currentTimeMillis();
+          System.out.println(content.toString());
+          identifier = new LanguageIdentifier(content.toString());
+          lang = identifier.getLanguage();
+          System.out.println(lang);
+          total += System.currentTimeMillis() - start;
+          Assert.assertEquals(tokens[1], lang);
+        }
+      }
+      in.close();
+      System.out.println("Total Time=" + total);
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.toString());
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/nutch/blob/20d28406/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/da.test
----------------------------------------------------------------------
diff --git a/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/da.test b/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/da.test
new file mode 100644
index 0000000..1238cd5
--- /dev/null
+++ b/nutch-plugins/language-identifier/src/test/java/org/apache/nutch/analysis/lang/da.test
@@ -0,0 +1,108 @@
+Genoptagelse af sessionen
+Jeg erkl�rer Europa-Parlamentets session, der blev afbrudt fredag den 17. december, for genoptaget. Endnu en gang vil jeg �nske Dem godt nyt�r, og jeg h�ber, De har haft en god ferie.
+Som De kan se, indfandt det store "�r 2000-problem" sig ikke. Til geng�ld har borgerne i en del af medlemslandene v�ret ramt af meget forf�rdelige naturkatastrofer. De har udtrykt �nske om en debat om dette emne i l�bet af m�deperioden. I mellemtiden �nsker jeg - som ogs� en del kolleger har anmodet om - at vi iagttager et minuts stilhed til minde om ofrene for bl.a. stormene i de medlemslande, der blev ramt. Jeg opfordrer Dem til st�ende at iagttage et minuts stilhed.
+(Parlamentet iagttog st�ende et minuts stilhed
+
+Fru formand, en bem�rkning til forretningsordenen. Gennem pressen og tv vil De v�re bekendt med en r�kke bombeeksplosioner og drab i Sri Lanka. En af de personer, der blev myrdet for ganske nylig i Sri Lanka, var hr. Kumar Ponnambalam, der bes�gte Europa-Parlamentet for f� m�neder siden. Ville det v�re passende, hvis De, fru formand, sendte en skrivelse til Sri Lankas pr�sident for at udtrykke vores dybe beklagelse i forbindelse med Kumar Ponnambalams d�d og de andre voldsomme d�dsfald i Sri Lanka og for indtr�ngende at anmode pr�sidenten om at g�re alt for at opn� en fredelig l�sning p� en meget vanskelig situation?
+
+Ja, hr. Evans, jeg mener, at et initiativ, som det, De foresl�r, ville v�re meget hensigtsm�ssigt. Hvis Europa-Parlamentet er enigt, vil jeg g�re, som hr. Evans har foresl�et.
+
+Fru formand, en bem�rkning til forretningsordenen. Jeg vil gerne have Deres r�d om artikel 143 vedr�rende afvisning. Mit sp�rgsm�l omhandler et emne, der vil blive behandlet p� torsdag, og jeg vil gerne tage emnet op igen ved den lejlighed.
+Bet�nkningen af Cunha om fler�rige udviklingsprogrammer skal forhandles af Parlamentet p� torsdag og indeholder et forslag i punkt 6 om, at der skal indf�res kvotesanktioner for lande, der ikke overholder deres �rlige m�ls�tninger for fl�dereduktion. Dette skal i henhold til punkt 6 indf�res til trods for princippet om relativ stabilitet. Jeg mener, at princippet om relativ stabilitet er et grundl�ggende retsprincip for den f�lles fiskeripolitik, og at der vil v�re juridisk bel�g for at afvise et forslag om at undergrave dette princip. Jeg vil gerne vide, om man kan g�re indsigelse mod noget, der bare er en bet�nkning og ikke et forslag til retsakt, og om det er noget, jeg kan g�re p� torsdag?
+
+Det er netop d�r, De - hvis De �nsker det - kan rejse dette sp�rgsm�l, det vil sige p� torsdag ved forhandlingens begyndelse.
+
+Fru formand, samtidig med Europa-Parlamentets f�rste m�deperiode i �r har man i Texas i USA fastsat datoen for henrettelsen af en d�dsd�mt, nemlig en ung mand p� 34 �r ved navn Hicks, og det er desv�rre p� n�ste torsdag.
+P� anmodning af et fransk parlamentsmedlem, hr. Zimeray, er der allerede indgivet et andragende, som mange har skrevet under p�, heriblandt undertegnede, men i tr�d med den holdning, som Europa-Parlamentet og hele Det Europ�iske F�llesskab konstant giver udtryk for, anmoder jeg Dem om at g�re den indflydelse, De har i kraft af Deres embede og den institution, De repr�senterer, g�ldende over for pr�sidenten og Texas' guvern�r Bush, som har bef�jelse til at oph�ve d�dsdommen og ben�de den d�mte.
+Alt dette er i tr�d med de principper, vi altid har v�ret tilh�ngere af.
+
+Tak, hr. Segni, det g�r jeg med gl�de. Det er s�ledes helt i tr�d med den holdning, Europa-Parlamentet altid har indtaget.
+
+Fru formand, jeg vil gerne g�re Dem opm�rksom p� en sag, som Parlamentet har besk�ftiget sig med gentagne gange. Det drejer sig om Alexander Nikitin. Vi gl�der os alle sammen over, at domstolen har frifundet ham og understreget, at adgangen til milj�informationer ogs� er konstitutionel ret i Rusland. Men nu er det s�dan, at han skal anklages igen, fordi statsadvokaten har anket dommen. Vi ved og har fastsl�et i virkelig mange beslutninger - netop p� det sidste m�de sidste �r - at dette ikke bare er en juridisk sag, og at det er forkert at beskylde Alexander Nikitin for at have beg�et kriminalitet og forr�deri, fordi vi som ber�rte nyder godt af hans resultater. Disse resultater er grundlaget for de europ�iske programmer til beskyttelse af Barentsee, og derfor beder jeg Dem gennemg� et brevudkast, som beskriver de vigtigste fakta, og tydeligg�re denne holdning i Rusland i overensstemmelse med Parlamentets beslutninger.
+
+Ja, fru Schroedter, jeg skal med gl�de unders�ge dette sp�rgsm�l, n�r jeg har modtaget Deres brev.
+
+Fru formand, jeg vil gerne f�rst give Dem en kompliment for den kendsgerning, at De har holdt Deres ord, og at antallet af tv-kanaler p� vores kontorer faktisk er udvidet enormt nu i denne f�rste m�deperiode i det nye �r. Men, fru formand, det, som jeg havde anmodet om, er ikke sket. Der er nu ganske vist to finske kanaler og en portugisisk kanal, men der er stadig ingen nederlandsk kanal, og jeg havde anmodet Dem om en nederlandsk kanal, fordi ogs� nederl�ndere gerne vil f�lge med i nyhederne hver m�ned, n�r vi forvises til dette sted. Jeg vil s�ledes endnu en gang anmode Dem om alligevel at s�rge for, at vi ogs� f�r en nederlandsk kanal.
+
+Fru Plooij-van Gorsel, jeg kan oplyse Dem om, at dette sp�rgsm�l er opf�rt p� dagsordenen for kv�storernes m�de p� onsdag. Det vil, h�ber jeg, blive behandlet i en positiv �nd.
+
+Fru formand, kan De fort�lle mig, hvorfor Parlamentet ikke overholder de lovgivningsbestemmelser om sundhed og sikkerhed, som det selv har fastsat? Hvorfor er der ikke foretaget en unders�gelse af luftkvaliteten i denne bygning, siden vi blev valgt? Hvorfor har Sundheds- og Sikkerhedsudvalget ikke haft et m�de siden 1998? Hvorfor har der ikke v�ret brand�velser, hverken i parlamentsbygningerne i Bruxelles eller Strasbourg? Hvorfor er der ingen brandinstrukser? Hvorfor etableres der ikke omr�der med rygeforbud? Det er fuldst�ndig skandal�st, at vi fasts�tter lovgivningsbestemmelser og s� ikke overholder dem selv.
+
+Fru Lynne, De har fuldst�ndig ret, og jeg vil kontrollere, om alle disse ting virkelig ikke er blevet gjort. Jeg vil ligeledes freml�gge problemet for kv�storerne, og jeg er sikker p�, at kv�storerne vil bestr�be sig p� at s�rge for, at vi overholder den lovgivning, vi vedtager.
+
+Fru formand, fru D�ez Gonz�lez og jeg havde stillet nogle sp�rgsm�l om visse holdninger gengivet i en spansk avis, som n�stformanden, fru de Palacio, har givet udtryk for. De kompetente tjenestegrene har ikke opf�rt dem p� dagsordenen, fordi de mener, at de blev besvaret ved et tidligere m�de.
+Jeg anmoder om, at denne beslutning tages op til fornyet overvejelse, for det er ikke tilf�ldet. De sp�rgsm�l, der tidligere er blevet besvaret, drejede sig om fru de Palacios medvirken i en bestemt sag og ikke om de erkl�ringer, som kunne l�ses i avisen ABC den 18. november sidste �r.
+
+K�re kolleger, vi vil unders�ge alt dette. Jeg m� indr�mme, at det hele forekommer mig lidt forvirrende i �jeblikket. Derfor vil vi unders�ge det meget omhyggeligt, s�ledes at alt er, som det skal v�re.
+
+Fru formand, jeg vil gerne vide, om der kommer en klar melding fra Parlamentet i denne uge om vores utilfredshed i forbindelse med dagens beslutning om ikke at forl�nge embargoen mod v�beneksport til Indonesien i betragtning af, at et stort flertal i Parlamentet tidligere har undertegnet v�benembargoen i Indonesien. Dagens beslutning om ikke at forl�nge embargoen er meget farlig p� grund af situationen der. Parlamentet b�r derfor tilkendegive sin holdning, da det er flertallets �nske. Det er uansvarligt af EU-medlemsstater at n�gte at forl�nge embargoen. Som n�vnt tidligere er der tale om en meget ustabil situation. Der er endog fare for et milit�rkup i fremtiden. Vi ved ikke, hvad der sker. S� hvorfor skal v�benproducenter i EU profitere p� bekostning af uskyldige mennesker?
+
+Under alle omst�ndigheder er punktet ikke p� nuv�rende tidspunkt opf�rt under forhandlingen om aktuelle og uops�ttelige sp�rgsm�l p� torsdag.
+
+Arbejdsplan
+N�ste punkt p� dagsordenen er fasts�ttelse af arbejdsplanen.
+Det endelige forslag til dagsorden, som det blev opstillet af Formandskonferencen p� m�det torsdag den 13. januar i overensstemmelse med forretningsordenens artikel 95, er omdelt.
+Det foreligger ingen forslag til �ndring for mandag og tirsdag.
+Onsdag:
+PSE-gruppen anmoder om at f� en redeg�relse fra Kommissionen om dens strategiske m�l for de kommende fem �r samt om den administrative reform opf�rt p� dagsordenen.
+Hvis hr. Bar�n Crespo, der har fremsat anmodningen, �nsker det, opfordrer jeg ham til at begrunde sit forslag. Dern�st g�r vi, som vi plejer, det vil sige, at vi h�rer et indl�g for og et indl�g imod forslaget.
+
+Fru formand, forel�ggelsen af Prodi-Kommissionens politiske program for hele valgperioden var til at begynde med et forslag fra De Europ�iske Socialdemokraters Gruppe, som opn�ede enstemmighed p� Formandskonferencen i september og ogs� hr. Prodis udtrykkelige accept, og han gentog sit l�fte i sin inds�ttelsestale.
+Dette l�fte er vigtigt, fordi Kommissionen er et organ, der har initiativmonopol i henhold til traktaterne og derfor grundl�ggende udformer Parlamentets politiske arbejde og lovgivningsarbejde i de kommende fem �r. Jeg vil ogs� minde om, fru formand, at Parlamentet to gange i foreg�ende valgperiode ved afstemning gav udtryk for sin tillid til formand Prodi. I denne valgperiode igen i juli og senere, med den nye Kommission p� plads, gav det igen i september hele Kommissionen et tillidsvotum. Der har derfor v�ret tid nok til, at Kommissionen kunne forberede sit program, og til at vi kunne f� kendskab til det og forklare det til borgerne. I den forbindelse vil jeg minde om beslutningen fra 15. september, hvori der blev henstillet til, at forslaget blev forelagt hurtigst muligt.
+Det, der skete i sidste uge - og som opstod uden for Formandskonferencen, hvor den udelukkende blev brugt til at bekr�fte og godkende beslutninger, som var truffet uden for den - skaber et dilemma: Enten er Kommissionen ikke i stand til at freml�gge det program. (I s� fald ville det v�re passende, at den informerede om det. If�lge kommissionsformandens udsagn er de i stand til at g�re det. Eftersom Kommissionen er repr�senteret af n�stformanden, fru de Palacio, mener jeg, at det f�r afstemningen ville v�re p� sin plads at v�re p� det rene med Kommissionens situation, hvad ang�r dets vilje til at forel�gge programmet, ligesom det var blevet aftalt.) Eller ogs� er Parlamentet ikke i stand til at behandle dette program, som der vist er nogle, der p�st�r. Efter min mening ville denne anden hypotese v�re det samme som at give afkald p� vores ansvar som parlament og desuden at indf�re en original teori, en ukendt metode, der best�r i skriftligt at give de politiske g
 rupper kendskab til Kommissionens program en uge f�r - og ikke dagen f�r, som det var aftalen - i betragtning af, at lovgivningsprogrammet skal diskuteres i februar, s�ledes at vi kunne springe forhandlingen over, fordi pressen og Internettet dagen efter havde givet alle borgerne kendskab til det, og Parlamentet ville ikke l�ngere beh�ve at bekymre sig om sagen.
+Da min gruppe mener, at et parlament er til for at lytte, diskutere og overveje, mener vi, at der ikke er noget som helst, der kan retf�rdigg�re denne uds�ttelse, og vi mener, at hvis Kommissionen er i stand til at g�re det, er der tid nok til, at vi kan genetablere den oprindelige aftale mellem Parlamentet og Kommissionen og handle ansvarligt over for vores medborgere. Derfor g�r det forslag, som De Europ�iske Socialdemokraters Gruppe stiller, og som De har n�vnt, ud p�, at vi holder fast ved forel�ggelsen af Prodi-Kommissionens program for valgperioden p� onsdag, og at dette program ogs� omfatter forslaget til administrativ reform, for hvis det ikke bliver s�dan, kan vi komme i en paradoksal situation: Med en undskyldning om at der ikke er en tekst, n�gtes formanden for Kommissionen p� den ene side retten til at tale i Parlamentet, og p� den anden side forhindres det, at der finder en forhandling sted om reformen, uden at Parlamentet p� forh�nd kender de tekster, 
 som den er baseret p�. Derfor, fru formand, anmoder jeg Dem om at bede Kommissionen om at udtale sig nu, og at vi derefter g�r over til afstemning.
+(Bifald fra PSE-gruppen)
+
+Fru formand, k�re kolleger, jeg er godt nok noget forbavset over vores kollega Bar�n Crespos opf�rsel. Han forlanger nu, at dette punkt s�ttes p� dagsordenen for onsdag.
+Hr. Bar�n Crespo, De kunne ikke deltage den sidste torsdag p� Formandskonferencen. Det kritiserer jeg ikke, for det sker af og til, at man lader sig repr�sentere. Hr. H�nsch repr�senterede Dem d�r. Vi havde en udf�rlig debat p� Formandskonferencen. Kun Deres gruppe repr�senterede det, som De siger nu. Vi stemte derefter om det. Hver ordf�rer har jo lige s� mange stemmer, som der er medlemmer i gruppen. Der var en afstemning om dette punkt. S� vidt jeg husker, faldt denne afstemning s�ledes ud: 422 mod 180 stemmer og nogle f�, der undlod at stemme. Det vil sige, at alle grupper med undtagelse af l�sg�ngerne - men de udg�r jo ikke nogen gruppe - var enige, kun Deres gruppe mente, at man skulle b�re sig s�dan ad, som De har foresl�et her. Alle andre mente noget andet. Det var beslutningen.
+Nu vil jeg gerne sige noget til selve sagen. Vi har tillid til Kommissionen, til Romano Prodi, og flertallet i vores gruppe har udtrykt tillid til Romano Prodi og Kommissionen efter en vanskelig proces, som alle kender til. Men vi mener ogs�, at vi skal have en debat om Kommissionens strategi i en ordin�r procedure, ikke kun p� baggrund af en mundtlig forklaring her i Europa-Parlamentet, men ogs� p� baggrund af et dokument, som er blevet besluttet i Kommissionen, og som beskriver dette program for fem �r. Et s�dant dokument findes ikke!
+
+Kommissionen vil freml�gge programmet for �r 2000 til februar. Vi har sagt, at hvis Kommissionen ikke �nsker at lave programmet for �r 2000 i januar, s� g�r vi det i februar. Det har vi godkendt. Vi �nsker s�dan set ikke nogen konflikt med Kommissionen, vi mener derimod, at hvis det g�r, skal Kommissionen og Parlamentet g� samme vej. Men Parlamentet er ogs� Kommissionens kontroll�r. Og ikke alt, hvad der kommer fra Kommissionen, skal n�dvendigvis v�re i overensstemmelse med os.
+Jeg vil gerne have, at vi f�r mulighed for at forberede os fornuftigt p� en debat om fem�rsprogrammet i grupperne. Man kan ikke forberede sig, hvis man h�rer en forklaring her og slet ikke ved, hvad indholdet af en s�dan forklaring er. Derfor anbefaler vi - og det er mit indtryk, at Kommissionen ogs� er �ben over for denne tanke - at vi f�rer debatten om Kommissionens langsigtede program frem til �r 2005 i februar - jeg h�ber ogs�, at Kommissionen er blevet enig om et program til den tid, som den vil foresl� os - og at vi samtidig f�rer en debat om Kommissionens lovgivningsprogram for �r 2000 i februar. Det er s�ledes ogs� en fornuftig saglig sammenh�ng, som r�der os til at f�re debatten om begge programmer i f�llesskab. Derfor afviser min gruppe p� det bestemteste Den Socialdemokratiske Gruppes forslag!
+(Bifald fra PPE-DE-gruppen)
+
+Fru formand, jeg vil g�re det meget klart, at Kommissionen f�rst og fremmest har den st�rste respekt for Parlamentets beslutninger, deriblandt opstillingen af dagsordenen. Derfor respekterer vi Parlamentets beslutning, hvad det ang�r.
+Men jeg vil ogs� g�re det meget klart, at hr. Prodi aftalte med Parlamentet at indf�re en ny forhandling, som hr. Bar�n nok husker, ud over den �rlige forhandling om Kommissionens lovgivningsprogram, om hovedlinjerne i aktionerne for den kommende fem�rsperiode, alts� for denne valgperiode.
+Jeg vil sige, fru formand, at denne forhandling i den aftale, som blev indg�et i september, adskilte sig fra Kommissionens �rlige forel�ggelse af programmet for lovgivningen. Og jeg vil sige, fru formand, at vi i Kommissionen er forberedt p� og rede til at deltage i den forhandling, n�r det er belejligt, at vi var rede til at gennemf�re den i denne uge, som det var aftalt fra begyndelsen, med udgangspunkt i at den blev forelagt dagen f�r i en tale til de parlamentariske grupper.
+Jeg vil derfor gentage, fru formand, at vi for vores del har diskuteret handlingsprogrammet for de kommende fem �r, og at vi er rede til, n�r Parlamentet bestemmer det - i denne uge, hvis det er beslutningen - at komme og forel�gge programmet for de kommende fem �r og i n�ste m�ned programmet for 2000, hvilket er helt i overensstemmelse med aftalen.
+
+Jeg foresl�r, at vi stemmer om PSE-gruppens anmodning om at f� en redeg�relse fra Kommissionen om dens strategiske m�l genopf�rt p� dagsordenen.
+(Forslaget forkastedes) Formanden. Stadig med hensyn til dagsordenen for onsdag har jeg et forslag om de mundtlige foresp�rgsler om kapitalskat. PPE-DE-gruppen �nsker, at dette punkt tages af dagsordenen.
+�nsker nogen at tage ordet p� vegne af gruppen for at begrunde denne anmodning?
+
+Fru formand, da jeg kan h�re en smule latter fra Socialdemokraterne - jeg har f�et fortalt, at brede kredse i Den Socialdemokratiske Gruppe ogs� gerne vil have taget dette punkt af dagsordenen, fordi der ved afstemningen p� Formandskonferencen ikke forel� noget votum fra arbejdsgruppen af ansvarlige kolleger i Den Socialdemokratiske Gruppe. Jeg ved ikke, om denne oplysning er rigtig, men PPE-DE-gruppen ville i hvert fald v�re taknemmelig, hvis dette punkt blev annulleret, fordi Parlamentet allerede har besk�ftiget sig med dette sp�rgsm�l flere gange. Der er ogs� truffet beslutninger mod en s�dan skat. Derfor anmoder min gruppe om, at dette punkt tages af dagsordenen.
+
+Tak, hr. Poettering.
+Vi skal nu h�re hr. Wurtz, der er imod forslaget.
+
+Fru formand, jeg vil f�rst og fremmest fremh�ve hr. Poetterings manglende konsekvens. For et �jeblik siden bel�rte han socialdemokraterne, fordi de ville �ndre en klar beslutning truffet p� Formandskonferencen. Imidlertid g�r han det samme. Vi havde en diskussion, vi var alle - p� n�r PPE-DE-gruppen og Den Liberale Gruppe - enige, og jeg bem�rkede endda - som De sikkert husker, k�re medform�nd - at det ikke drejede sig om, hvorvidt De er for eller imod Tobin-afgiften, men om De turde h�re, hvad Kommissionen og R�det mente om den. Dette er ikke for meget forlangt. Derfor fastholder jeg forslaget om at bevare det mundtlige sp�rgsm�l til Kommissionen og R�det, s�ledes at vi �n gang for alle f�r opklaret, hvilken holdning de to institutioner har til dette ret beskedne forslag, som dog sender et vigtigt signal til befolkningen, navnlig efter fiaskoen i Seattle.
+
+Vi skal stemme om PPE-DE-gruppens anmodning om, at de mundtlige foresp�rgsler om kapitalskat tages af dagsordenen.
+(Forslaget forkastedes. 164 stemte for, 166 stemte imod, og 7 undlod at stemme)
+
+Fru formand, jeg vil gerne takke hr. Poettering for den reklame, han netop har gjort for denne debat. Tak.
+
+Fru formand, er min stemme, som jeg ikke kunne afgive elektronisk, fordi jeg ikke har kortet, blevet talt med? Jeg stemte for.
+
+Det er rigtigt. Hvis vi tilf�jer de to kolleger, der har givet sig til kende, bliver resultatet ...
+
+Fru formand, formandskabet har bekendtgjort afstemningens udfald. Det kan der ikke laves om p�.
+
+K�re kolleger, jeg minder endnu en gang om, at det er vigtigt, at alle har deres kort om mandagen. Det er tydeligt, at vi har et problem, og jeg m� derfor tr�ffe en beslutning.
+Jeg har ogs� glemt mit kort, og jeg ville have stemt imod. Derfor mener jeg, at det mundtlige sp�rgsm�l fortsat skal medtages p� dagsordenen.
+Det er sidste gang, vi vil tage hensyn til glemte kort. Lad dette v�re helt klart, og husk det.
+(Bifald)
+Ja, det mundtlige sp�rgsm�l er fortsat opf�rt p� dagsordenen, og ja, formanden har ret til at stemme, ligesom hun har ret til at glemme sit kort.
+Vi forts�tter nu med de �vrige �ndringer af dagsordenen.
+
+Fru formand, i den tidligere afstemning - og jeg vil rette mig efter Deres afg�relse om dette emne - om sp�rgsm�let om Kommissionens redeg�relse om dens strategiske m�l gav jeg udtryk for, at jeg gerne ville tale p� vegne af min gruppe f�r afstemningen. Det blev ikke til noget. Jeg vil s�tte pris p� at f� lejlighed til at afgive stemmeforklaring p� vegne af min gruppe i forbindelse med afslutningen af dette sp�rgsm�l. Det er et vigtigt sp�rgsm�l, og det vil v�re nyttigt for Parlamentet, hvis det er angivet, hvordan de forskellige personer opfatter vores handlinger i lyset af deres egne politiske analyser.
+
+Fru formand, jeg vil ikke genoptage debatten, men jeg havde ogs� meldt mig for at tage stilling til hr. Bar�n Crespos �ndringsforslag. De r�bte mig heller ikke op. Det beklager jeg, men afstemningen er gennemf�rt, afg�relsen er truffet, vi lader det alts� ligge.
+
+Jeg beklager, hr. H�nsch og hr. Cox, jeg s� ikke, at De anmodede om ordet. Men i �vrigt mener jeg, at holdningerne er meget klare, og de vil blive indf�rt i protokollen. N�r vi i morgen skal vedtage protokollen for i dag, kan de kolleger, der ikke synes, at holdningerne er blevet tilstr�kkeligt forklaret, anmode om �ndringer. Det, mener jeg, er en god l�sning. Selvf�lgelig vil protokollen for m�det i morgen tage hensyn til alle de supplerende forklaringer. Jeg mener, at det er en bedre l�sning end at g� over til stemmeforklaringer p� nuv�rende tidspunkt, som ville v�re et stort sidespring. Hr. Cox og hr. H�nsch, passer denne l�sning Dem?
+
+Fru formand, hvis protokollen giver korrekt udtryk for min gruppes holdning i forbindelse med afstemningen, vil og kan jeg ikke g�re indsigelser. Hvis De afg�r, at der ikke er grund til at afgive stemmeforklaring, vil jeg acceptere det, men med forbehold.
+
+Vi vil derfor v�re meget opm�rksomme p� udarbejdelsen af protokollen. Det er vi i �vrigt altid. Hvis holdningerne ikke klart fremg�r, kan vi eventuelt �ndre den.
+(Den s�ledes �ndrede dagsorden godkendtes)
+