Index: src/test/org/apache/nutch/analysis/TestQueryParser.java
===================================================================
--- src/test/org/apache/nutch/analysis/TestQueryParser.java	(revision 359225)
+++ src/test/org/apache/nutch/analysis/TestQueryParser.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.nutch.analysis;
 
 import org.apache.nutch.searcher.Query;
+import org.apache.nutch.util.NutchConf;
 
 import junit.framework.TestCase;
 
@@ -26,9 +27,10 @@
  */
 public class TestQueryParser extends TestCase {
 
+  private static NutchConf nutchConf = new NutchConf();
   public void assertQueryEquals(String query, String result) throws Exception {
     try {
-      Query q = NutchAnalysis.parseQuery(query);
+      Query q = NutchAnalysis.parseQuery(query, nutchConf);
       String s = q.toString();
       if (!s.equals(result)) {
         fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
Index: src/test/org/apache/nutch/net/TestBasicUrlNormalizer.java
===================================================================
--- src/test/org/apache/nutch/net/TestBasicUrlNormalizer.java	(revision 359225)
+++ src/test/org/apache/nutch/net/TestBasicUrlNormalizer.java	(working copy)
@@ -17,6 +17,9 @@
 package org.apache.nutch.net;
 
 import java.net.URL;
+
+import org.apache.nutch.util.NutchConf;
+
 import junit.framework.TestCase;
 
 /** Unit tests for BasicUrlNormalizer. */
@@ -81,7 +84,7 @@
   }
 
   private void normalizeTest(String weird, String normal) throws Exception {
-    assertEquals(normal, UrlNormalizerFactory.getNormalizer().normalize(weird));
+    assertEquals(normal, UrlNormalizerFactory.getNormalizer(new NutchConf()).normalize(weird));
   }
 	
   public static void main(String[] args) throws Exception {
Index: src/test/org/apache/nutch/ndfs/TestNDFS.java
===================================================================
--- src/test/org/apache/nutch/ndfs/TestNDFS.java	(revision 359225)
+++ src/test/org/apache/nutch/ndfs/TestNDFS.java	(working copy)
@@ -72,8 +72,9 @@
   private static final Logger LOG =
       LogFormatter.getLogger("org.apache.nutch.ndfs.TestNDFS");
 
+  private static NutchConf nutchConf = new NutchConf();
   private static int BUFFER_SIZE =
-      NutchConf.get().getInt("io.file.buffer.size", 4096);
+      nutchConf.getInt("io.file.buffer.size", 4096);
 
   private static int testCycleNumber = 0;
 
@@ -124,7 +125,7 @@
 
   protected void setUp() throws Exception {
     super.setUp();
-    NutchConf.get().setBoolean("test.ndfs.same.host.targets.allowed", true);
+    nutchConf.setBoolean("test.ndfs.same.host.targets.allowed", true);
   }
 
  /**
@@ -134,7 +135,7 @@
   protected void prepareTempFileSpace() {
     if (baseDir.exists()) {
       try { // start from a blank slate
-        FileUtil.fullyDelete(baseDir);
+        FileUtil.fullyDelete(baseDir, nutchConf);
       } catch (Exception ignored) {
       }
     }
@@ -192,17 +193,17 @@
 
     //
     // set given config param to override other config settings
-    NutchConf.get().setInt("test.ndfs.block_size", blockSize);
+    nutchConf.setInt("test.ndfs.block_size", blockSize);
     // verify that config changed
-    assertTrue(blockSize == NutchConf.get().getInt("test.ndfs.block_size", 2)); // 2 is an intentional obviously-wrong block size
+    assertTrue(blockSize == nutchConf.getInt("test.ndfs.block_size", 2)); // 2 is an intentional obviously-wrong block size
     // downsize for testing (just to save resources)
-    NutchConf.get().setInt("ndfs.namenode.handler.count", 3);
+    nutchConf.setInt("ndfs.namenode.handler.count", 3);
     if (false) { //  use MersenneTwister, if present
-      NutchConf.get().set("nutch.random.class",
+      nutchConf.set("nutch.random.class",
                           "org.apache.nutch.util.MersenneTwister");
     }
-    NutchConf.get().setLong("ndfs.blockreport.intervalMsec", 50*1000L);
-    NutchConf.get().setLong("ndfs.datanode.startupMsec", 15*1000L);
+    nutchConf.setLong("ndfs.blockreport.intervalMsec", 50*1000L);
+    nutchConf.setLong("ndfs.datanode.startupMsec", 15*1000L);
 
     String nameFSDir = baseDirSpecified + "/name";
     msg("----Start Test Cycle=" + currentTestCycleNumber +
@@ -216,20 +217,19 @@
 
     int nameNodePort = 9000 + testCycleNumber++; // ToDo: settable base port
     String nameNodeSocketAddr = "localhost:" + nameNodePort;
-    NameNode nameNodeDaemon = new NameNode(new File(nameFSDir), nameNodePort);
+    NameNode nameNodeDaemon = new NameNode(new File(nameFSDir), nameNodePort, nutchConf);
     NDFSClient ndfsClient = null;
     try {
       //
       //        start some DataNodes
       //
       ArrayList listOfDataNodeDaemons = new ArrayList();
-      NutchConf conf = NutchConf.get();
-      conf.set("fs.default.name", nameNodeSocketAddr);
+      nutchConf.set("fs.default.name", nameNodeSocketAddr);
       for (int i = 0; i < initialDNcount; i++) {
         // uniquely config real fs path for data storage for this datanode
         String dataDir = baseDirSpecified + "/datanode" + i;
-        conf.set("ndfs.data.dir", dataDir);
-        DataNode dn = DataNode.makeInstanceForDir(dataDir, conf);
+        nutchConf.set("ndfs.data.dir", dataDir);
+        DataNode dn = DataNode.makeInstanceForDir(dataDir, nutchConf);
         if (dn != null) {
           listOfDataNodeDaemons.add(dn);
           (new Thread(dn, "DataNode" + i + ": " + dataDir)).start();
@@ -244,7 +244,7 @@
         awaitQuiescence();
 
         //  act as if namenode is a remote process
-        ndfsClient = new NDFSClient(new InetSocketAddress("localhost", nameNodePort));
+        ndfsClient = new NDFSClient(new InetSocketAddress("localhost", nameNodePort), nutchConf);
 
         //
         //           write nBytes of data using randomDataGenerator to numFiles
@@ -431,12 +431,12 @@
    * testing (a default is set here if property is not set.)
    */
   private Random makeRandomDataGenerator() {
-    long seed = NutchConf.get().getLong("test.ndfs.random.seed", 0xB437EF);
+    long seed = nutchConf.getLong("test.ndfs.random.seed", 0xB437EF);
     try {
       if (randomDataGeneratorCtor == null) {
         // lazy init
         String rndDataGenClassname =
-            NutchConf.get().get("nutch.random.class", "java.util.Random");
+            nutchConf.get("nutch.random.class", "java.util.Random");
         Class clazz = Class.forName(rndDataGenClassname);
         randomDataGeneratorCtor = clazz.getConstructor(new Class[]{Long.TYPE});
       }
Index: src/test/org/apache/nutch/searcher/TestQuery.java
===================================================================
--- src/test/org/apache/nutch/searcher/TestQuery.java	(revision 359225)
+++ src/test/org/apache/nutch/searcher/TestQuery.java	(working copy)
@@ -20,36 +20,40 @@
 import junit.framework.TestCase;
 import java.util.Arrays;
 import org.apache.nutch.analysis.NutchAnalysis;
+import org.apache.nutch.util.NutchConf;
 
 public class TestQuery extends TestCase {
+    
+  private static NutchConf nutchConf = new NutchConf();
+    
   public TestQuery(String name) { super(name); }
 
   public void testRequiredTerm() throws Exception {
-    Query query = new Query();
+    Query query = new Query(nutchConf);
     query.addRequiredTerm("bobo");
     testQuery(query, "bobo");
   }
 
   public void testProhibitedTerm() throws Exception {
-    Query query = new Query();
+    Query query = new Query(nutchConf);
     query.addProhibitedTerm("bobo");
     testQuery(query, "-bobo");
   }
 
   public void testRequiredPhrase() throws Exception {
-    Query query = new Query();
+    Query query = new Query(nutchConf);
     query.addRequiredPhrase(new String[] {"bobo", "bogo"});
     testQuery(query, "\"bobo bogo\"");
   }
 
   public void testProhibitedPhrase() throws Exception {
-    Query query = new Query();
+    Query query = new Query(nutchConf);
     query.addProhibitedPhrase(new String[] {"bobo", "bogo"});
     testQuery(query, "-\"bobo bogo\"");
   }
 
   public void testComplex() throws Exception {
-    Query query = new Query();
+    Query query = new Query(nutchConf);
     query.addRequiredTerm("bobo");
     query.addProhibitedTerm("bono");
     query.addRequiredPhrase(new String[] {"bobo", "bogo"});
@@ -69,7 +73,7 @@
 
   public static void testQueryParser(Query query, String string)
     throws Exception {
-    Query after = NutchAnalysis.parseQuery(string);
+    Query after = NutchAnalysis.parseQuery(string, nutchConf);
     assertEquals(after, query);
     assertEquals(after.toString(), string);
   }
@@ -82,7 +86,7 @@
     ByteArrayInputStream iBuf = new ByteArrayInputStream(oBuf.toByteArray());
     DataInputStream in = new DataInputStream(iBuf);
 
-    Query after = Query.read(in);
+    Query after = Query.read(in, nutchConf);
 
     assertEquals(after, query);
   }
@@ -95,7 +99,7 @@
 
   public static void testQueryTerms(String query, String[] terms)
     throws Exception {
-    assertTrue(Arrays.equals(NutchAnalysis.parseQuery(query).getTerms(),
+    assertTrue(Arrays.equals(NutchAnalysis.parseQuery(query, nutchConf).getTerms(),
                              terms));
   }
 
Index: src/test/org/apache/nutch/plugin/TestPluginSystem.java
===================================================================
--- src/test/org/apache/nutch/plugin/TestPluginSystem.java	(revision 359225)
+++ src/test/org/apache/nutch/plugin/TestPluginSystem.java	(working copy)
@@ -38,10 +38,17 @@
     private int fPluginCount;
 
     private LinkedList fFolders = new LinkedList();
+    private NutchConf nutchConf ;
+    private PluginRepository repository;
 
     protected void setUp() throws Exception {
+        this.nutchConf = new NutchConf();
+        nutchConf.set("plugin.includes", ".*");
+//        String string = this.nutchConf.get("plugin.includes", "");
+//        nutchConf.set("plugin.includes", string + "|Dummy*");
         fPluginCount = 5;
         createDummyPlugins(fPluginCount);
+        this.repository = nutchConf.getPluginRepository();
     }
 
     /*
@@ -72,7 +79,7 @@
     /**
      */
     public void testLoadPlugins() {
-        PluginDescriptor[] descriptors = PluginRepository.getInstance()
+        PluginDescriptor[] descriptors = repository
                 .getPluginDescriptors();
         int k = descriptors.length;
         assertTrue(fPluginCount <= k);
@@ -91,10 +98,10 @@
      */
     public void testGetExtensionAndAttributes() {
         String xpId = " sdsdsd";
-        ExtensionPoint extensionPoint = PluginRepository.getInstance()
+        ExtensionPoint extensionPoint =repository
                 .getExtensionPoint(xpId);
         assertEquals(extensionPoint, null);
-        Extension[] extension1 = PluginRepository.getInstance()
+        Extension[] extension1 = repository
                 .getExtensionPoint(getGetExtensionId()).getExtensions();
         assertEquals(extension1.length, fPluginCount);
         for (int i = 0; i < extension1.length; i++) {
@@ -108,7 +115,7 @@
      * @throws PluginRuntimeException
      */
     public void testGetExtensionInstances() throws PluginRuntimeException {
-        Extension[] extensions = PluginRepository.getInstance()
+        Extension[] extensions = repository
                 .getExtensionPoint(getGetExtensionId()).getExtensions();
         assertEquals(extensions.length, fPluginCount);
         for (int i = 0; i < extensions.length; i++) {
@@ -127,7 +134,7 @@
      *  
      */
     public void testGetClassLoader() {
-        PluginDescriptor[] descriptors = PluginRepository.getInstance()
+        PluginDescriptor[] descriptors = repository
                 .getPluginDescriptors();
         for (int i = 0; i < descriptors.length; i++) {
             PluginDescriptor descriptor = descriptors[i];
@@ -139,7 +146,7 @@
      * @throws IOException
      */
     public void testGetResources() throws IOException {
-        PluginDescriptor[] descriptors = PluginRepository.getInstance()
+        PluginDescriptor[] descriptors = repository
                 .getPluginDescriptors();
         for (int i = 0; i < descriptors.length; i++) {
             PluginDescriptor descriptor = descriptors[i];
@@ -159,12 +166,12 @@
      * @return a PluginFolderPath
      */
     private String getPluginFolder() {
-        String[] strings = NutchConf.get().getStrings("plugin.folders");
+        String[] strings = nutchConf.getStrings("plugin.folders");
         if (strings == null || strings.length == 0)
             fail("no plugin directory setuped..");
 
         String name = strings[0];
-        return PluginManifestParser.getPluginFolder(name).toString();
+        return new PluginManifestParser(nutchConf, this.repository).getPluginFolder(name).toString();
     }
 
     /**
Index: src/test/org/apache/nutch/protocol/TestContentProperties.java
===================================================================
--- src/test/org/apache/nutch/protocol/TestContentProperties.java	(revision 359225)
+++ src/test/org/apache/nutch/protocol/TestContentProperties.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.nutch.protocol;
 
 import org.apache.nutch.io.TestWritable;
+import org.apache.nutch.util.NutchConf;
 
 import junit.framework.TestCase;
 
@@ -53,7 +54,7 @@
         }
         TestWritable.testWritable(properties);
         Content content = new Content("url", "url", new byte[0], "text/html",
-                new ContentProperties());
+                new ContentProperties(), new NutchConf());
         ContentProperties metadata = content.getMetadata();
         for (int i = 0; i < 100; i++) {
             metadata.setProperty("aKey", "" + i);
Index: src/test/org/apache/nutch/protocol/TestContent.java
===================================================================
--- src/test/org/apache/nutch/protocol/TestContent.java	(revision 359225)
+++ src/test/org/apache/nutch/protocol/TestContent.java	(working copy)
@@ -17,11 +17,16 @@
 package org.apache.nutch.protocol;
 
 import org.apache.nutch.io.*;
+import org.apache.nutch.util.NutchConf;
+
 import junit.framework.TestCase;
 
 /** Unit tests for Content. */
 
 public class TestContent extends TestCase {
+    
+  private static NutchConf nutchConf = new NutchConf();
+    
   public TestContent(String name) { super(name); }
 
   public void testContent() throws Exception {
@@ -35,7 +40,7 @@
     metaData.put("Content-Type", "text/html");
 
     Content r = new Content(url, url, page.getBytes("UTF8"), "text/html",
-                            metaData);
+                            metaData, nutchConf);
                         
     TestWritable.testWritable(r);
     assertEquals("text/html", r.getMetadata().get("Content-Type"));
@@ -50,49 +55,49 @@
     c = new Content("http://www.foo.com/",
                     "http://www.foo.com/",
                     "".getBytes("UTF8"),
-                    "text/html; charset=UTF-8", p);
+                    "text/html; charset=UTF-8", p, nutchConf);
     assertEquals("text/html", c.getContentType());
 
     c = new Content("http://www.foo.com/foo.html",
                     "http://www.foo.com/",
                     "".getBytes("UTF8"),
-                    "", p);
+                    "", p, nutchConf);
     assertEquals("text/html", c.getContentType());
 
     c = new Content("http://www.foo.com/foo.html",
                     "http://www.foo.com/",
                     "".getBytes("UTF8"),
-                    null, p);
+                    null, p, nutchConf);
     assertEquals("text/html", c.getContentType());
 
     c = new Content("http://www.foo.com/",
                     "http://www.foo.com/",
                     "<html></html>".getBytes("UTF8"),
-                    "", p);
+                    "", p, nutchConf);
     assertEquals("text/html", c.getContentType());
 
     c = new Content("http://www.foo.com/foo.html",
                     "http://www.foo.com/",
                     "<html></html>".getBytes("UTF8"),
-                    "text/plain", p);
+                    "text/plain", p, nutchConf);
     assertEquals("text/html", c.getContentType());
 
     c = new Content("http://www.foo.com/foo.png",
                     "http://www.foo.com/",
                     "<html></html>".getBytes("UTF8"),
-                    "text/plain", p);
+                    "text/plain", p, nutchConf);
     assertEquals("text/html", c.getContentType());
 
     c = new Content("http://www.foo.com/",
                     "http://www.foo.com/",
                     "".getBytes("UTF8"),
-                    "", p);
+                    "", p, nutchConf);
     assertEquals("", c.getContentType());
 
     c = new Content("http://www.foo.com/",
                     "http://www.foo.com/",
                     "".getBytes("UTF8"),
-                    null, p);
+                    null, p, nutchConf);
     assertNull(c.getContentType());
   }
 	
Index: src/test/org/apache/nutch/io/TestSequenceFile.java
===================================================================
--- src/test/org/apache/nutch/io/TestSequenceFile.java	(revision 359225)
+++ src/test/org/apache/nutch/io/TestSequenceFile.java	(working copy)
@@ -28,6 +28,8 @@
 public class TestSequenceFile extends TestCase {
   private static Logger LOG = SequenceFile.LOG;
 
+  private static NutchConf nutchConf = new NutchConf();
+  
   public TestSequenceFile(String name) { super(name); }
 
   /** Unit tests for SequenceFile. */
@@ -39,7 +41,7 @@
  
     int seed = new Random().nextInt();
 
-    NutchFileSystem nfs = new LocalFileSystem();
+    NutchFileSystem nfs = new LocalFileSystem(new NutchConf());
     try {
         //LOG.setLevel(Level.FINE);
         writeTest(nfs, count, seed, file, false);
@@ -85,7 +87,7 @@
     RandomDatum k = new RandomDatum();
     RandomDatum v = new RandomDatum();
     LOG.fine("reading " + count + " records");
-    SequenceFile.Reader reader = new SequenceFile.Reader(nfs, file);
+    SequenceFile.Reader reader = new SequenceFile.Reader(nfs, file, nutchConf);
     RandomDatum.Generator generator = new RandomDatum.Generator(seed);
     for (int i = 0; i < count; i++) {
       generator.next();
@@ -129,7 +131,7 @@
     RandomDatum k = new RandomDatum();
     RandomDatum v = new RandomDatum();
     Iterator iterator = map.entrySet().iterator();
-    SequenceFile.Reader reader = new SequenceFile.Reader(nfs, file + ".sorted");
+    SequenceFile.Reader reader = new SequenceFile.Reader(nfs, file + ".sorted", nutchConf);
     for (int i = 0; i < count; i++) {
       Map.Entry entry = (Map.Entry)iterator.next();
       RandomDatum key = (RandomDatum)entry.getKey();
@@ -195,8 +197,8 @@
                                                int megabytes, int factor) {
     SequenceFile.Sorter sorter = 
       fast
-      ? new SequenceFile.Sorter(nfs, new RandomDatum.Comparator(),RandomDatum.class)
-      : new SequenceFile.Sorter(nfs, RandomDatum.class, RandomDatum.class);
+      ? new SequenceFile.Sorter(nfs, new RandomDatum.Comparator(),RandomDatum.class, nutchConf)
+      : new SequenceFile.Sorter(nfs, RandomDatum.class, RandomDatum.class, nutchConf);
     sorter.setMemory(megabytes * 1024*1024);
     sorter.setFactor(factor);
     return sorter;
@@ -221,7 +223,7 @@
         System.exit(-1);
     }
     int i = 0;
-    NutchFileSystem nfs = NutchFileSystem.parseArgs(args, i);      
+    NutchFileSystem nfs = NutchFileSystem.parseArgs(args, i, nutchConf);      
     try {
       for (; i < args.length; i++) {       // parse command line
           if (args[i] == null) {
Index: src/test/org/apache/nutch/io/TestSetFile.java
===================================================================
--- src/test/org/apache/nutch/io/TestSetFile.java	(revision 359225)
+++ src/test/org/apache/nutch/io/TestSetFile.java	(working copy)
@@ -30,10 +30,12 @@
   private static String FILE =
     System.getProperty("test.build.data",".") + "/test.set";
 
+  private static NutchConf nutchConf = new NutchConf();
+  
   public TestSetFile(String name) { super(name); }
 
   public void testSetFile() throws Exception {
-    NutchFileSystem nfs = new LocalFileSystem();
+    NutchFileSystem nfs = new LocalFileSystem(nutchConf);
     try {
         RandomDatum[] data = generate(10000);
         writeTest(nfs, data, FILE);
@@ -70,7 +72,7 @@
     throws IOException {
     RandomDatum v = new RandomDatum();
     LOG.fine("reading " + data.length + " records");
-    SetFile.Reader reader = new SetFile.Reader(nfs, file);
+    SetFile.Reader reader = new SetFile.Reader(nfs, file, nutchConf);
     for (int i = 0; i < data.length; i++) {
       if (!reader.seek(data[i]))
         throw new RuntimeException("wrong value at " + i);
@@ -94,7 +96,7 @@
     }
       
     int i = 0;
-    NutchFileSystem nfs = NutchFileSystem.parseArgs(args, i);      
+    NutchFileSystem nfs = NutchFileSystem.parseArgs(args, i, nutchConf);      
     try {
       for (; i < args.length; i++) {       // parse command line
         if (args[i] == null) {
Index: src/test/org/apache/nutch/io/TestArrayFile.java
===================================================================
--- src/test/org/apache/nutch/io/TestArrayFile.java	(revision 359225)
+++ src/test/org/apache/nutch/io/TestArrayFile.java	(working copy)
@@ -35,16 +35,18 @@
   }
 
   public void testArrayFile() throws Exception {
-    NutchFileSystem nfs = new LocalFileSystem();
+      NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = new LocalFileSystem(nutchConf);
     RandomDatum[] data = generate(10000);
     writeTest(nfs, data, FILE);
-    readTest(nfs, data, FILE);
+    readTest(nfs, data, FILE, nutchConf);
   }
 
   public void testEmptyFile() throws Exception {
-    NutchFileSystem nfs = new LocalFileSystem();
+    NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = new LocalFileSystem(nutchConf);
     writeTest(nfs, new RandomDatum[0], FILE);
-    ArrayFile.Reader reader = new ArrayFile.Reader(nfs, FILE);
+    ArrayFile.Reader reader = new ArrayFile.Reader(nfs, FILE, nutchConf);
     assertNull(reader.get(0, new RandomDatum()));
     reader.close();
   }
@@ -71,11 +73,11 @@
     writer.close();
   }
 
-  private static void readTest(NutchFileSystem nfs, RandomDatum[] data, String file)
+  private static void readTest(NutchFileSystem nfs, RandomDatum[] data, String file, NutchConf nutchConf)
     throws IOException {
     RandomDatum v = new RandomDatum();
     LOG.fine("reading " + data.length + " records");
-    ArrayFile.Reader reader = new ArrayFile.Reader(nfs, file);
+    ArrayFile.Reader reader = new ArrayFile.Reader(nfs, file, nutchConf);
     for (int i = 0; i < data.length; i++) {       // try forwards
       reader.get(i, v);
       if (!v.equals(data[i])) {
@@ -106,8 +108,9 @@
       System.exit(-1);
     }
 
+    NutchConf nutchConf = new NutchConf();
     int i = 0;
-    NutchFileSystem nfs = NutchFileSystem.parseArgs(args, i);
+    NutchFileSystem nfs = NutchFileSystem.parseArgs(args, i, nutchConf);
     try {
         for (; i < args.length; i++) {       // parse command line
             if (args[i] == null) {
@@ -138,7 +141,7 @@
         }
 
         if (check) {
-            readTest(nfs, data, file);
+            readTest(nfs, data, file, nutchConf);
         }
     } finally {
         nfs.close();
Index: src/test/org/apache/nutch/mapred/TestSequenceFileInputFormat.java
===================================================================
--- src/test/org/apache/nutch/mapred/TestSequenceFileInputFormat.java	(revision 359225)
+++ src/test/org/apache/nutch/mapred/TestSequenceFileInputFormat.java	(working copy)
@@ -29,10 +29,11 @@
   private static final Logger LOG = InputFormatBase.LOG;
 
   private static int MAX_LENGTH = 10000;
+  private static NutchConf nutchConf = new NutchConf();
 
   public void testFormat() throws Exception {
-    JobConf job = new JobConf(NutchConf.get());
-    NutchFileSystem fs = NutchFileSystem.getNamed("local");
+    JobConf job = new JobConf(nutchConf);
+    NutchFileSystem fs = NutchFileSystem.getNamed("local", nutchConf);
     File dir = new File(System.getProperty("test.build.data",".") + "/mapred");
     File file = new File(dir, "test.seq");
     
Index: src/test/org/apache/nutch/mapred/TestTextInputFormat.java
===================================================================
--- src/test/org/apache/nutch/mapred/TestTextInputFormat.java	(revision 359225)
+++ src/test/org/apache/nutch/mapred/TestTextInputFormat.java	(working copy)
@@ -29,10 +29,11 @@
   private static final Logger LOG = InputFormatBase.LOG;
 
   private static int MAX_LENGTH = 10000;
-
+  private static NutchConf nutchConf = new NutchConf();
+  
   public void testFormat() throws Exception {
-    JobConf job = new JobConf(NutchConf.get());
-    NutchFileSystem fs = NutchFileSystem.getNamed("local");
+    JobConf job = new JobConf(nutchConf);
+    NutchFileSystem fs = NutchFileSystem.getNamed("local", nutchConf);
     File dir = new File(System.getProperty("test.build.data",".") + "/mapred");
     File file = new File(dir, "test.txt");
 
Index: src/test/org/apache/nutch/fs/TestNutchFileSystem.java
===================================================================
--- src/test/org/apache/nutch/fs/TestNutchFileSystem.java	(revision 359225)
+++ src/test/org/apache/nutch/fs/TestNutchFileSystem.java	(working copy)
@@ -30,8 +30,8 @@
 public class TestNutchFileSystem extends TestCase {
   private static final Logger LOG = InputFormatBase.LOG;
 
-  private static int BUFFER_SIZE =
-    NutchConf.get().getInt("io.file.buffer.size", 4096);
+  private static NutchConf nutchConf = new NutchConf();
+  private static int BUFFER_SIZE = nutchConf.getInt("io.file.buffer.size", 4096);
 
   private static final long MEGA = 1024 * 1024;
   private static final int SEEKS_PER_FILE = 4;
@@ -49,7 +49,7 @@
   public static void testFs(long megaBytes, int numFiles, long seed)
     throws Exception {
 
-    NutchFileSystem fs = NutchFileSystem.get();
+    NutchFileSystem fs = NutchFileSystem.get(nutchConf);
 
     if (seed == 0)
       seed = new Random().nextLong();
@@ -107,7 +107,7 @@
     
     {
       try {
-        fs = NutchFileSystem.get();
+        fs = NutchFileSystem.get(nutchConf);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
@@ -164,7 +164,7 @@
     fs.delete(DATA_DIR);
     fs.delete(WRITE_DIR);
     
-    JobConf job = new JobConf(NutchConf.get());
+    JobConf job = new JobConf(nutchConf);
     job.setBoolean("fs.test.fastCheck", fastCheck);
 
     job.setInputDir(CONTROL_DIR);
@@ -191,7 +191,7 @@
 
     {
       try {
-        fs = NutchFileSystem.get();
+        fs = NutchFileSystem.get(nutchConf);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
@@ -255,7 +255,7 @@
 
     fs.delete(READ_DIR);
 
-    JobConf job = new JobConf(NutchConf.get());
+    JobConf job = new JobConf(nutchConf);
     job.setBoolean("fs.test.fastCheck", fastCheck);
 
 
@@ -283,7 +283,7 @@
 
     {
       try {
-        fs = NutchFileSystem.get();
+        fs = NutchFileSystem.get(nutchConf);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
@@ -347,7 +347,7 @@
 
     fs.delete(READ_DIR);
 
-    JobConf job = new JobConf(NutchConf.get());
+    JobConf job = new JobConf(nutchConf);
     job.setBoolean("fs.test.fastCheck", fastCheck);
 
     job.setInputDir(CONTROL_DIR);
@@ -401,7 +401,7 @@
     LOG.info("files = " + files);
     LOG.info("megaBytes = " + megaBytes);
   
-    NutchFileSystem fs = NutchFileSystem.get();
+    NutchFileSystem fs = NutchFileSystem.get(nutchConf);
 
     if (!noWrite) {
       createControlFile(fs, megaBytes*MEGA, files, seed);
Index: src/test/org/apache/nutch/parse/TestOutlinkExtractor.java
===================================================================
--- src/test/org/apache/nutch/parse/TestOutlinkExtractor.java	(revision 359225)
+++ src/test/org/apache/nutch/parse/TestOutlinkExtractor.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.apache.nutch.parse.Outlink;
 import org.apache.nutch.parse.OutlinkExtractor;
+import org.apache.nutch.util.NutchConf;
 
 import junit.framework.TestCase;
 
@@ -30,14 +31,15 @@
  */
 public class TestOutlinkExtractor extends TestCase {
 
+  private static NutchConf nutchConf = new NutchConf();
   public void testGetNoOutlinks() {
     Outlink[]  outlinks = null;
             
-    outlinks = OutlinkExtractor.getOutlinks(null);
+    outlinks = OutlinkExtractor.getOutlinks(null, nutchConf);
     assertNotNull(outlinks);
     assertEquals(0, outlinks.length);
     
-    outlinks = OutlinkExtractor.getOutlinks("");
+    outlinks = OutlinkExtractor.getOutlinks("", nutchConf);
     assertNotNull(outlinks);
     assertEquals(0, outlinks.length);
   }
@@ -46,7 +48,7 @@
     Outlink[] outlinks = OutlinkExtractor.getOutlinks(
         "Test with http://www.nutch.org/index.html is it found? " +
         "What about www.google.com at http://www.google.de " +
-        "A longer URL could be http://www.sybit.com/solutions/portals.html");
+        "A longer URL could be http://www.sybit.com/solutions/portals.html", nutchConf);
     
     assertTrue("Url not found!", outlinks.length == 3);
     assertEquals("Wrong URL", "http://www.nutch.org/index.html", outlinks[0].getToUrl());
@@ -58,7 +60,7 @@
     Outlink[] outlinks = OutlinkExtractor.getOutlinks(
         "Test with http://www.nutch.org/index.html is it found? " +
         "What about www.google.com at http://www.google.de " +
-        "A longer URL could be http://www.sybit.com/solutions/portals.html", "http://www.sybit.de");
+        "A longer URL could be http://www.sybit.com/solutions/portals.html", "http://www.sybit.de", nutchConf);
     
     assertTrue("Url not found!", outlinks.length == 3);
     assertEquals("Wrong URL", "http://www.nutch.org/index.html", outlinks[0].getToUrl());
@@ -68,7 +70,7 @@
   public void testGetOutlinksFtp() {
     Outlink[] outlinks = OutlinkExtractor.getOutlinks(
         "Test with ftp://www.nutch.org is it found? " +
-        "What about www.google.com at ftp://www.google.de");
+        "What about www.google.com at ftp://www.google.de", nutchConf);
     
     assertTrue("Url not found!", outlinks.length >1);
     assertEquals("Wrong URL", "ftp://www.nutch.org/", outlinks[0].getToUrl());
Index: src/test/org/apache/nutch/parse/TestParseData.java
===================================================================
--- src/test/org/apache/nutch/parse/TestParseData.java	(revision 359225)
+++ src/test/org/apache/nutch/parse/TestParseData.java	(working copy)
@@ -18,11 +18,16 @@
 
 import org.apache.nutch.io.*;
 import org.apache.nutch.protocol.ContentProperties;
+import org.apache.nutch.util.NutchConf;
+
 import junit.framework.TestCase;
 
 /** Unit tests for ParseData. */
 
 public class TestParseData extends TestCase {
+    
+  private  NutchConf nutchConf = new NutchConf();
+  
   public TestParseData(String name) { super(name); }
 
   public void testParseData() throws Exception {
@@ -30,15 +35,15 @@
     String title = "The Foo Page";
 
     Outlink[] outlinks = new Outlink[] {
-      new Outlink("http://foo.com/", "Foo"),
-      new Outlink("http://bar.com/", "Bar")
+      new Outlink("http://foo.com/", "Foo", nutchConf),
+      new Outlink("http://bar.com/", "Bar", nutchConf)
     };
 
     ContentProperties metaData = new ContentProperties();
     metaData.put("Language", "en/us");
     metaData.put("Charset", "UTF-8");
 
-    ParseData r = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metaData);
+    ParseData r = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metaData, nutchConf);
                         
     TestWritable.testWritable(r);
   }
Index: src/test/org/apache/nutch/parse/TestParserFactory.java
===================================================================
--- src/test/org/apache/nutch/parse/TestParserFactory.java	(revision 359225)
+++ src/test/org/apache/nutch/parse/TestParserFactory.java	(working copy)
@@ -27,6 +27,7 @@
 import java.io.File;
 
 import java.net.MalformedURLException;
+import java.util.Arrays;
 
 
 /**
@@ -37,69 +38,74 @@
  */
 public class TestParserFactory extends TestCase {
 	
-  
+  private  NutchConf nutchConf;
+  private  ParserFactory parserFactory;
+    
   public TestParserFactory(String name) { super(name); }
 
   /** Inits the Test Case with the test parse-plugin file */
   protected void setUp() throws Exception {
-    NutchConf.get().set("parse.plugin.file",
+      nutchConf = new NutchConf();
+      nutchConf.set("plugin.includes", ".*");
+      nutchConf.set("parse.plugin.file",
                         "org/apache/nutch/parse/parse-plugin-test.xml");
+      parserFactory = new ParserFactory(nutchConf);
   }
   
   /** Unit test for <code>getParser(String, String)</code> method. */
   public void testGetParser() throws Exception {
-    Parser  parser = ParserFactory.getParser("text/html", "http://foo.com/");
+    Parser  parser = parserFactory.getParser("text/html", "http://foo.com/");
     assertNotNull(parser);
-    parser  = ParserFactory.getParser("foo/bar", "http://foo.com/");
+    parser  = parserFactory.getParser("foo/bar", "http://foo.com/");
     assertNotNull(parser);
   }
   
   /** Unit test for <code>getExtensions(String)</code> method. */
   public void testGetExtensions() throws Exception {
-    Extension ext = (Extension)ParserFactory.getExtensions("text/html").get(0);
+    Extension ext = (Extension)parserFactory.getExtensions("text/html").get(0);
     assertEquals("parse-html", ext.getDescriptor().getPluginId());
-    ext = (Extension) ParserFactory.getExtensions("text/html; charset=ISO-8859-1").get(0);
+    ext = (Extension) parserFactory.getExtensions("text/html; charset=ISO-8859-1").get(0);
     assertEquals("parse-html", ext.getDescriptor().getPluginId());
-    ext = (Extension)ParserFactory.getExtensions("foo/bar").get(0);
+    ext = (Extension)parserFactory.getExtensions("foo/bar").get(0);
     assertEquals("parse-text", ext.getDescriptor().getPluginId());
   }
   
   /** Unit test to check <code>getParsers</code> method */
   public void testGetParsers() throws Exception {
-    Parser [] parsers = ParserFactory.getParsers("text/html", "http://foo.com");
+    Parser [] parsers = new ParserFactory(nutchConf).getParsers("text/html", "http://foo.com");
     assertNotNull(parsers);
     assertEquals(1, parsers.length);
     assertEquals("org.apache.nutch.parse.html.HtmlParser",
         parsers[0].getClass().getName());
 
-    parsers = ParserFactory.getParsers("text/html; charset=ISO-8859-1", "http://foo.com");
+    parsers = new ParserFactory(nutchConf).getParsers("text/html; charset=ISO-8859-1", "http://foo.com");
     assertNotNull(parsers);
     assertEquals(1, parsers.length);
     assertEquals("org.apache.nutch.parse.html.HtmlParser",
         parsers[0].getClass().getName());
 
     
-    parsers = ParserFactory.getParsers("application/x-javascript",
+    parsers = parserFactory.getParsers("application/x-javascript",
     "http://foo.com");
     assertNotNull(parsers);
     assertEquals(1, parsers.length);
     assertEquals("org.apache.nutch.parse.js.JSParseFilter",
         parsers[0].getClass().getName());
     
-    parsers = ParserFactory.getParsers("text/plain", "http://foo.com");
+    parsers = parserFactory.getParsers("text/plain", "http://foo.com");
     assertNotNull(parsers);
     assertEquals(1, parsers.length);
     assertEquals("org.apache.nutch.parse.text.TextParser",
         parsers[0].getClass().getName());
     
-    Parser parser1 = ParserFactory.getParsers("text/plain", "http://foo.com")[0];
-    Parser parser2 = ParserFactory.getParsers("*", "http://foo.com")[0];
+    Parser parser1 = parserFactory.getParsers("text/plain", "http://foo.com")[0];
+    Parser parser2 = parserFactory.getParsers("*", "http://foo.com")[0];
    
     assertEquals("Different instances!", parser1.hashCode(), parser2.hashCode());
     
     //test and make sure that the rss parser is loaded even though its plugin.xml
     //doesn't claim to support text/rss, only application/rss+xml
-    parsers = ParserFactory.getParsers("text/rss","http://foo.com");
+    parsers = parserFactory.getParsers("text/rss","http://foo.com");
     assertNotNull(parsers);
     assertEquals(1,parsers.length);
     assertEquals("org.apache.nutch.parse.rss.RSSParser",parsers[0].getClass().getName());
Index: src/test/org/apache/nutch/ipc/TestRPC.java
===================================================================
--- src/test/org/apache/nutch/ipc/TestRPC.java	(revision 359225)
+++ src/test/org/apache/nutch/ipc/TestRPC.java	(working copy)
@@ -27,6 +27,7 @@
 import java.util.Arrays;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 /** Unit tests for RPC. */
 public class TestRPC extends TestCase {
@@ -34,6 +35,8 @@
 
   public static final Logger LOG =
     LogFormatter.getLogger("org.apache.nutch.ipc.TestRPC");
+  
+  private static NutchConf nutchConf = new NutchConf();
 
   // quiet during testing, since output ends up on console
   static {
@@ -80,12 +83,12 @@
   }
 
   public void testCalls() throws Exception {
-    Server server = RPC.getServer(new TestImpl(), PORT);
+    Server server = RPC.getServer(new TestImpl(), PORT, nutchConf);
     server.start();
 
     InetSocketAddress addr = new InetSocketAddress(PORT);
     TestProtocol proxy =
-      (TestProtocol)RPC.getProxy(TestProtocol.class, addr);
+      (TestProtocol)RPC.getProxy(TestProtocol.class, addr, nutchConf);
     
     proxy.ping();
 
@@ -114,7 +117,7 @@
     Method method =
       TestProtocol.class.getMethod("echo", new Class[] { String.class });
     String[] values = (String[])RPC.call(method, new String[][]{{"a"},{"b"}},
-                                         new InetSocketAddress[] {addr, addr});
+                                         new InetSocketAddress[] {addr, addr}, nutchConf);
     assertTrue(Arrays.equals(values, new String[]{"a","b"}));
 
 
Index: src/test/org/apache/nutch/ipc/TestIPC.java
===================================================================
--- src/test/org/apache/nutch/ipc/TestIPC.java	(revision 367309)
+++ src/test/org/apache/nutch/ipc/TestIPC.java	(working copy)
@@ -29,12 +29,15 @@
 import java.util.logging.Level;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 /** Unit tests for IPC. */
 public class TestIPC extends TestCase {
   public static final Logger LOG =
     LogFormatter.getLogger("org.apache.nutch.ipc.TestIPC");
 
+  private static NutchConf nutchConf = new NutchConf();
+  
   // quiet during testing, since output ends up on console
   static {
     LOG.setLevel(Level.WARNING);
@@ -52,7 +55,7 @@
     private boolean sleep;
 
     public TestServer(int port, int handlerCount, boolean sleep) {
-      super(port, LongWritable.class, handlerCount);
+      super(port, LongWritable.class, handlerCount, nutchConf);
       this.setTimeout(1000);
       this.sleep = sleep;
     }
@@ -145,7 +148,7 @@
 
     Client[] clients = new Client[clientCount];
     for (int i = 0; i < clientCount; i++) {
-      clients[i] = new Client(LongWritable.class);
+      clients[i] = new Client(LongWritable.class, nutchConf);
     }
     
     SerialCaller[] callers = new SerialCaller[callerCount];
@@ -184,7 +187,7 @@
 
     Client[] clients = new Client[clientCount];
     for (int i = 0; i < clientCount; i++) {
-      clients[i] = new Client(LongWritable.class);
+      clients[i] = new Client(LongWritable.class, nutchConf);
     }
     
     ParallelCaller[] callers = new ParallelCaller[callerCount];
Index: src/java/org/apache/nutch/clustering/OnlineClustererFactory.java
===================================================================
--- src/java/org/apache/nutch/clustering/OnlineClustererFactory.java	(revision 359225)
+++ src/java/org/apache/nutch/clustering/OnlineClustererFactory.java	(working copy)
@@ -30,12 +30,12 @@
 public class OnlineClustererFactory {
   public static final Logger LOG = LogFormatter
     .getLogger(OnlineClustererFactory.class.getName());
+  private ExtensionPoint extensionPoint;
 
-  private final static ExtensionPoint X_POINT = PluginRepository.getInstance()
-    .getExtensionPoint(OnlineClusterer.X_POINT_ID);
+  public OnlineClustererFactory(NutchConf nutchConf) {
+      this.extensionPoint = nutchConf.getPluginRepository().getExtensionPoint(OnlineClusterer.X_POINT_ID);
+  }
 
-  private OnlineClustererFactory() {}
-
   /**
   * @return Returns the online clustering extension specified
   * in nutch configuration's key
@@ -43,15 +43,14 @@
   * empty (no preference), the first available clustering extension is
   * returned.
   */
-  public static OnlineClusterer getOnlineClusterer()
+  public OnlineClusterer getOnlineClusterer(String extensionName)
     throws PluginRuntimeException {
 
-    if (X_POINT == null) {
+    if (this.extensionPoint == null) {
       // not even an extension point defined.
       return null;
     }
 
-    String extensionName = NutchConf.get().get("extension.clustering.extension-name");
     if (extensionName != null) {
       Extension extension = findExtension(extensionName);
       if (extension != null) {
@@ -63,7 +62,7 @@
       // not found, fallback to the default, if available.
     }
 
-    Extension[] extensions = X_POINT.getExtensions();
+    Extension[] extensions = this.extensionPoint.getExtensions();
     if (extensions.length > 0) {
       LOG.info("Using the first clustering extension found: "
         + extensions[0].getId());
@@ -73,10 +72,10 @@
     }
   }
 
-  private static Extension findExtension(String name)
+  private Extension findExtension(String name)
     throws PluginRuntimeException {
 
-    Extension[] extensions = X_POINT.getExtensions();
+    Extension[] extensions = this.extensionPoint.getExtensions();
 
     for (int i = 0; i < extensions.length; i++) {
       Extension extension = extensions[i];
Index: src/java/org/apache/nutch/fetcher/Fetcher.java
===================================================================
--- src/java/org/apache/nutch/fetcher/Fetcher.java	(revision 367309)
+++ src/java/org/apache/nutch/fetcher/Fetcher.java	(working copy)
@@ -73,9 +73,18 @@
   private boolean parsing;
 
   private class FetcherThread extends Thread {
-    public FetcherThread() {
+    private NutchConf nutchConf;
+    private URLFilters urlFilters;
+    private ParseUtil parseUtil;
+    private ProtocolFactory protocolFactory;
+
+    public FetcherThread(NutchConf nutchConf) {
       this.setDaemon(true);                       // don't hang JVM on exit
       this.setName("FetcherThread");              // use an informative name
+      this.nutchConf = nutchConf;
+      this.urlFilters = new URLFilters(nutchConf);
+      this.parseUtil = new ParseUtil(nutchConf);
+      this.protocolFactory = new ProtocolFactory(nutchConf);
     }
 
     public void run() {
@@ -112,7 +121,7 @@
             do {
               redirecting = false;
               LOG.fine("redirectCount=" + redirectCount);
-              Protocol protocol = ProtocolFactory.getProtocol(url);
+              Protocol protocol = this.protocolFactory.getProtocol(url);
               ProtocolOutput output = protocol.getProtocolOutput(key, datum);
               ProtocolStatus status = output.getStatus();
               Content content = output.getContent();
@@ -127,7 +136,7 @@
               case ProtocolStatus.MOVED:         // redirect
               case ProtocolStatus.TEMP_MOVED:
                 String newUrl = status.getMessage();
-                newUrl = URLFilters.filter(newUrl);
+                newUrl = this.urlFilters.filter(newUrl);
                 if (newUrl != null && !newUrl.equals(url)) {
                   url = newUrl;
                   redirecting = true;
@@ -196,7 +205,7 @@
 
       if (content == null) {
         String url = key.toString();
-        content = new Content(url, url, new byte[0], "", new ContentProperties());
+        content = new Content(url, url, new byte[0], "", new ContentProperties(), this.nutchConf);
       }
 
       content.getMetadata().setProperty           // add segment to metadata
@@ -208,14 +217,14 @@
       if (parsing && status == CrawlDatum.STATUS_FETCH_SUCCESS) {
         ParseStatus parseStatus;
         try {
-          parse = ParseUtil.parse(content);
+          parse = this.parseUtil.parse(content);
           parseStatus = parse.getData().getStatus();
         } catch (Exception e) {
           parseStatus = new ParseStatus(e);
         }
         if (!parseStatus.isSuccess()) {
           LOG.warning("Error parsing: " + key + ": " + parseStatus);
-          parse = parseStatus.getEmptyParse();
+          parse = parseStatus.getEmptyParse(getConf());
         }
         // Calculate page signature. For non-parsing fetchers this will
         // be done in ParseSegment
@@ -292,7 +301,7 @@
     LOG.info("Fetcher: threads: " + threadCount);
 
     for (int i = 0; i < threadCount; i++) {       // spawn threads
-      new FetcherThread().start();
+      new FetcherThread(getConf()).start();
     }
 
     // select a timeout that avoids a task timeout
@@ -358,7 +367,7 @@
       
     File segment = new File(args[0]);
 
-    NutchConf conf = NutchConf.get();
+    NutchConf conf = new NutchConf();
 
     int threads = conf.getInt("fetcher.threads.fetch", 10);
     boolean parsing = true;
Index: src/java/org/apache/nutch/analysis/NutchAnalysis.jj
===================================================================
--- src/java/org/apache/nutch/analysis/NutchAnalysis.jj	(revision 359225)
+++ src/java/org/apache/nutch/analysis/NutchAnalysis.jj	(working copy)
@@ -31,7 +31,8 @@
 import org.apache.nutch.searcher.Query;
 import org.apache.nutch.searcher.QueryFilters;
 import org.apache.nutch.searcher.Query.Clause;
-
+import org.apache.nutch.searcher.Query.Clause;
+import org.apache.nutch.util.NutchConf;
 import org.apache.lucene.analysis.StopFilter;
 
 import java.io.*;
@@ -51,6 +52,8 @@
   private static final Set STOP_SET = StopFilter.makeStopSet(STOP_WORDS);
 
   private String queryString;
+  private QueryFilters queryFilters;
+  
 
   /** True iff word is a stop word.  Stop words are only removed from queries.
    * Every word is indexed.  */
@@ -59,11 +62,12 @@
   }
 
   /** Construct a query parser for the text in a reader. */
-  public static Query parseQuery(String queryString) throws IOException {
+  public static Query parseQuery(String queryString, NutchConf nutchConf) throws IOException {
     NutchAnalysis parser =
       new NutchAnalysis(new FastCharStream(new StringReader(queryString)));
     parser.queryString = queryString;
-    return parser.parse();
+    parser.queryFilters = new QueryFilters(nutchConf);
+    return parser.parse(nutchConf);
   }
 
   /** For debugging. */
@@ -72,7 +76,7 @@
     while (true) {
       System.out.print("Query: ");
       String line = in.readLine();
-      System.out.println(parseQuery(line));
+      System.out.println(parseQuery(line, new NutchConf()));
     }
   }
 
@@ -174,9 +178,9 @@
 
 
 /** Parse a query. */
-Query parse() :
+Query parse(NutchConf nutchConf) :
 {
-  Query query = new Query();
+  Query query = new Query(nutchConf);
   ArrayList terms;
   Token token;
   String field;
@@ -245,7 +249,7 @@
   (<QUOTE>|<EOF>)
     
   {
-    if (QueryFilters.isRawField(field)) {
+    if (this.queryFilters.isRawField(field)) {
       result.clear();
       result.add(queryString.substring(start, end));
     }
@@ -272,7 +276,7 @@
     term = term() { result.add(term); })*
 
   {
-    if (QueryFilters.isRawField(field)) {
+    if (this.queryFilters.isRawField(field)) {
       result.clear();
       result.add(queryString.substring(start, token.endColumn));
     }
Index: src/java/org/apache/nutch/analysis/AnalyzerFactory.java
===================================================================
--- src/java/org/apache/nutch/analysis/AnalyzerFactory.java	(revision 359225)
+++ src/java/org/apache/nutch/analysis/AnalyzerFactory.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.plugin.PluginRepository;
 import org.apache.nutch.plugin.PluginRuntimeException;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 
 /**
@@ -38,26 +39,23 @@
   public final static Logger LOG =
           LogFormatter.getLogger(AnalyzerFactory.class.getName());
 
-  private final static ExtensionPoint X_POINT = 
-          PluginRepository.getInstance()
-                          .getExtensionPoint(NutchAnalyzer.X_POINT_ID);
+  private Map CACHE = new HashMap();
 
-  private final static Map CACHE = new HashMap();
-
-  private final static NutchAnalyzer DEFAULT_ANALYZER = 
+  private NutchAnalyzer DEFAULT_ANALYZER = 
                                             new NutchDocumentAnalyzer();
   
+  private ExtensionPoint extensionPoint;
+
+  private AnalyzerFactory() {}
   
-  static {
-    if (X_POINT == null) {
-      throw new RuntimeException("x point " + NutchAnalyzer.X_POINT_ID +
-                                 " not found.");
-    }
+  public AnalyzerFactory (NutchConf nutchConf) {
+      this.extensionPoint = nutchConf.getPluginRepository().getExtensionPoint(NutchAnalyzer.X_POINT_ID);
+      if(this.extensionPoint == null) {
+          throw new RuntimeException("x point " + NutchAnalyzer.X_POINT_ID +
+          " not found.");
+      }
   }
 
-
-  private AnalyzerFactory() {}
-
   
   /**
    * Returns the appropriate {@link NutchAnalyzer analyzer} implementation
@@ -67,7 +65,7 @@
    * plugin found whose "lang" attribute equals the specified lang parameter is
    * used. If none match, then the {@link NutchDocumentAnalyzer} is used.
    */
-  public static NutchAnalyzer get(String lang) {
+  public NutchAnalyzer get(String lang) {
 
     NutchAnalyzer analyzer = DEFAULT_ANALYZER;
     Extension extension = getExtension(lang);
@@ -81,7 +79,7 @@
     return analyzer;
   }
 
-  private static Extension getExtension(String lang) {
+  private Extension getExtension(String lang) {
 
     Extension extension = (Extension) CACHE.get(lang);
     if (extension == null) {
@@ -91,10 +89,10 @@
     return extension;
   }
 
-  private static Extension findExtension(String lang) {
+  private Extension findExtension(String lang) {
 
     if (lang != null) {
-      Extension[] extensions = X_POINT.getExtentens();
+      Extension[] extensions = this.extensionPoint.getExtentens();
       for (int i=0; i<extensions.length; i++) {
         if (lang.equals(extensions[i].getAttribute("lang"))) {
           return extensions[i];
Index: src/java/org/apache/nutch/analysis/NutchAnalysisTokenManager.java
===================================================================
--- src/java/org/apache/nutch/analysis/NutchAnalysisTokenManager.java	(revision 359225)
+++ src/java/org/apache/nutch/analysis/NutchAnalysisTokenManager.java	(working copy)
@@ -3,6 +3,8 @@
 import org.apache.nutch.searcher.Query;
 import org.apache.nutch.searcher.QueryFilters;
 import org.apache.nutch.searcher.Query.Clause;
+import org.apache.nutch.searcher.Query.Clause;
+import org.apache.nutch.util.NutchConf;
 import org.apache.lucene.analysis.StopFilter;
 import java.io.*;
 import java.util.*;
Index: src/java/org/apache/nutch/analysis/CommonGrams.java
===================================================================
--- src/java/org/apache/nutch/analysis/CommonGrams.java	(revision 359225)
+++ src/java/org/apache/nutch/analysis/CommonGrams.java	(working copy)
@@ -38,12 +38,10 @@
     LogFormatter.getLogger("org.apache.nutch.analysis.CommonGrams");
   private static final char SEPARATOR = '-';
   private static final HashMap COMMON_TERMS = new HashMap();
+  
+  public CommonGrams(NutchConf nutchConf) {init(nutchConf);}                        // no public ctor
 
-  static { init(); }
-
-  private CommonGrams() {}                        // no public ctor
-
-  private static class Filter extends TokenFilter {
+  private  class Filter extends TokenFilter {
     private HashSet common;
     private Token previous;
     private LinkedList gramQueue = new LinkedList();
@@ -130,10 +128,10 @@
   }
 
   /** Construct using the provided config file. */
-  private static void init() {
+  private  void init(NutchConf nutchConf) {
     try {
-      Reader reader = NutchConf.get().getConfResourceAsReader
-        (NutchConf.get().get("analysis.common.terms.file"));
+      Reader reader = nutchConf.getConfResourceAsReader
+        (nutchConf.get("analysis.common.terms.file"));
       BufferedReader in = new BufferedReader(reader);
       String line;
       while ((line = in.readLine()) != null) {
@@ -170,12 +168,12 @@
 
   /** Construct a token filter that inserts n-grams for common terms.  For use
    * while indexing documents.  */
-  public static TokenFilter getFilter(TokenStream ts, String field) {
+  public  TokenFilter getFilter(TokenStream ts, String field) {
     return new Filter(ts, (HashSet)COMMON_TERMS.get(field));
   }
 
   /** Utility to convert an array of Query.Terms into a token stream. */
-  private static class ArrayTokens extends TokenStream {
+  private  class ArrayTokens extends TokenStream {
     private Term[] terms;
     private int index;
 
@@ -190,7 +188,7 @@
   }
 
   /** Optimizes phrase queries to use n-grams when possible. */
-  public static String[] optimizePhrase(Phrase phrase, String field) {
+  public  String[] optimizePhrase(Phrase phrase, String field) {
     //LOG.info("Optimizing " + phrase + " for " + field);
     ArrayList result = new ArrayList();
     TokenStream ts = getFilter(new ArrayTokens(phrase), field);
@@ -221,7 +219,7 @@
 
   }
 
-  private static int arity(String gram) {
+  private  int arity(String gram) {
     int index = 0;
     int arity = 0;
     while ((index = gram.indexOf(SEPARATOR, index+1)) != -1) {
@@ -239,12 +237,13 @@
     }
     TokenStream ts =
       new NutchDocumentTokenizer(new StringReader(text.toString()));
-    ts = getFilter(ts, "url");
+    CommonGrams commonGrams = new CommonGrams(new NutchConf());
+    ts = commonGrams.getFilter(ts, "url");
     Token token;
     while ((token = ts.next()) != null) {
       System.out.println("Token: " + token);
     }
-    String[] optimized = optimizePhrase(new Phrase(args), "url");
+    String[] optimized = commonGrams.optimizePhrase(new Phrase(args), "url");
     System.out.print("Optimized: ");
     for (int i = 0; i < optimized.length; i++) {
       System.out.print(optimized[i] + " ");
Index: src/java/org/apache/nutch/analysis/NutchAnalysis.java
===================================================================
--- src/java/org/apache/nutch/analysis/NutchAnalysis.java	(revision 359225)
+++ src/java/org/apache/nutch/analysis/NutchAnalysis.java	(working copy)
@@ -4,7 +4,8 @@
 import org.apache.nutch.searcher.Query;
 import org.apache.nutch.searcher.QueryFilters;
 import org.apache.nutch.searcher.Query.Clause;
-
+import org.apache.nutch.searcher.Query.Clause;
+import org.apache.nutch.util.NutchConf;
 import org.apache.lucene.analysis.StopFilter;
 
 import java.io.*;
@@ -24,7 +25,9 @@
   private static final Set STOP_SET = StopFilter.makeStopSet(STOP_WORDS);
 
   private String queryString;
+  private QueryFilters queryFilters;
 
+
   /** True iff word is a stop word.  Stop words are only removed from queries.
    * Every word is indexed.  */
   public static boolean isStopWord(String word) {
@@ -32,11 +35,12 @@
   }
 
   /** Construct a query parser for the text in a reader. */
-  public static Query parseQuery(String queryString) throws IOException {
+  public static Query parseQuery(String queryString, NutchConf nutchConf) throws IOException {
     NutchAnalysis parser =
       new NutchAnalysis(new FastCharStream(new StringReader(queryString)));
     parser.queryString = queryString;
-    return parser.parse();
+    parser.queryFilters = new QueryFilters(nutchConf);
+    return parser.parse(nutchConf);
   }
 
   /** For debugging. */
@@ -45,13 +49,13 @@
     while (true) {
       System.out.print("Query: ");
       String line = in.readLine();
-      System.out.println(parseQuery(line));
+      System.out.println(parseQuery(line, new NutchConf()));
     }
   }
 
 /** Parse a query. */
-  final public Query parse() throws ParseException {
-  Query query = new Query();
+  final public Query parse(NutchConf nutchConf) throws ParseException {
+  Query query = new Query(nutchConf);
   ArrayList terms;
   Token token;
   String field;
@@ -213,7 +217,7 @@
       jj_consume_token(-1);
       throw new ParseException();
     }
-    if (QueryFilters.isRawField(field)) {
+    if (this.queryFilters.isRawField(field)) {
       result.clear();
       result.add(queryString.substring(start, end));
     }
@@ -259,7 +263,7 @@
       term = term();
                     result.add(term);
     }
-    if (QueryFilters.isRawField(field)) {
+    if (this.queryFilters.isRawField(field)) {
       result.clear();
       result.add(queryString.substring(start, token.endColumn));
     }
Index: src/java/org/apache/nutch/analysis/NutchDocumentAnalyzer.java
===================================================================
--- src/java/org/apache/nutch/analysis/NutchDocumentAnalyzer.java	(revision 359225)
+++ src/java/org/apache/nutch/analysis/NutchDocumentAnalyzer.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.analysis.TokenFilter;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.Token;
+import org.apache.nutch.util.NutchConf;
 
 
 /**
@@ -36,8 +37,9 @@
   /** Analyzer used to index textual content. */
   private static class ContentAnalyzer extends Analyzer {
     /** Constructs a {@link NutchDocumentTokenizer}. */
-    public TokenStream tokenStream(String field, Reader reader) {
-      return CommonGrams.getFilter(new NutchDocumentTokenizer(reader), field);
+    public TokenStream tokenStream(String field, Reader reader, NutchConf nutchConf) {
+        //TODO mb: is this file really generated by javacc?
+      return new CommonGrams(nutchConf).getFilter(new NutchDocumentTokenizer(reader), field);
     }
   }
 
Index: src/java/org/apache/nutch/servlet/Cached.java
===================================================================
--- src/java/org/apache/nutch/servlet/Cached.java	(revision 359225)
+++ src/java/org/apache/nutch/servlet/Cached.java	(working copy)
@@ -47,9 +47,9 @@
 
   NutchBean bean = null;
 
-  public void init() {
+  public void init(NutchConf nutchConf) {
     try {
-      bean = NutchBean.get(this.getServletContext());
+      bean = NutchBean.get(this.getServletContext(), nutchConf);
     } catch (IOException e) {
       // nothing
     }
Index: src/java/org/apache/nutch/net/RegexUrlNormalizer.java
===================================================================
--- src/java/org/apache/nutch/net/RegexUrlNormalizer.java	(revision 359225)
+++ src/java/org/apache/nutch/net/RegexUrlNormalizer.java	(working copy)
@@ -61,8 +61,8 @@
       * or <tt>nutch-default.xml</tt> and reads that configuration file.  It stores the regex patterns
       * and corresponding substitutions in a List. The file should be in the CLASSPATH. */
     public RegexUrlNormalizer() throws IOException, MalformedPatternException {
-      String filename = NutchConf.get().get("urlnormalizer.regex.file");
-      URL url= NutchConf.get().getResource(filename);
+      String filename = getConf().get("urlnormalizer.regex.file");
+      URL url=getConf().getResource(filename);
      
       rules=readConfigurationFile(url.toString());
     }
Index: src/java/org/apache/nutch/net/UrlNormalizer.java
===================================================================
--- src/java/org/apache/nutch/net/UrlNormalizer.java	(revision 359225)
+++ src/java/org/apache/nutch/net/UrlNormalizer.java	(working copy)
@@ -18,8 +18,10 @@
 
 import java.net.MalformedURLException;
 
+import org.apache.nutch.util.NutchConfigurable;
+
 /** Interface used to convert URLs to normal form and optionally do regex substitutions */
-public interface UrlNormalizer {
+public interface UrlNormalizer extends NutchConfigurable{
   
   /* Interface for URL normalization */
   public String normalize(String urlString) throws MalformedURLException;
Index: src/java/org/apache/nutch/net/BasicUrlNormalizer.java
===================================================================
--- src/java/org/apache/nutch/net/BasicUrlNormalizer.java	(revision 359225)
+++ src/java/org/apache/nutch/net/BasicUrlNormalizer.java	(working copy)
@@ -23,6 +23,7 @@
 
 import java.util.logging.Logger;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.oro.text.regex.*;
 
 /** Converts URLs to a normal form . */
@@ -39,6 +40,8 @@
     private Rule relativePathRule = null;
     private Rule leadingRelativePathRule = null;
 
+    private NutchConf nutchConf;
+
     public BasicUrlNormalizer() {
       try {
         // this pattern tries to find spots like "/xx/../" in the url, which
@@ -172,5 +175,20 @@
         public Perl5Substitution substitution;
     }
 
+
+    /* (non-Javadoc)
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
 
Index: src/java/org/apache/nutch/net/URLFilter.java
===================================================================
--- src/java/org/apache/nutch/net/URLFilter.java	(revision 359225)
+++ src/java/org/apache/nutch/net/URLFilter.java	(working copy)
@@ -16,12 +16,14 @@
 
 package org.apache.nutch.net;
 
+import org.apache.nutch.util.NutchConfigurable;
+
 /**
  * Interface used to limit which URLs enter Nutch.
  * Used by the injector and the db updater.
  */
 
-public interface URLFilter {
+public interface URLFilter extends NutchConfigurable{
   /** The name of the extension point. */
   public final static String X_POINT_ID = URLFilter.class.getName();
 
Index: src/java/org/apache/nutch/net/URLFilters.java
===================================================================
--- src/java/org/apache/nutch/net/URLFilters.java	(revision 359225)
+++ src/java/org/apache/nutch/net/URLFilters.java	(working copy)
@@ -24,51 +24,50 @@
 import org.apache.nutch.plugin.PluginRuntimeException;
 
 import org.apache.nutch.util.NutchConf;
-
+//TODO mb: are cache required?
 /** Creates and caches {@link URLFilter} implementing plugins.*/
 public class URLFilters {
 
-  private static final URLFilter[] CACHE;
-  static {
-    String order = NutchConf.get().get("urlfilter.order");
-    String[] orderedFilters = null;
-    if (order!=null && !order.trim().equals("")) {
-      orderedFilters = order.split("\\s+");
-    }
+  private final URLFilter[] CACHE;
+ 
+  public URLFilters(NutchConf nutchConf) {
+      String order = nutchConf.get("urlfilter.order");
+      String[] orderedFilters = null;
+      if (order!=null && !order.trim().equals("")) {
+        orderedFilters = order.split("\\s+");
+      }
 
-    try {
-      ExtensionPoint point =
-        PluginRepository.getInstance().getExtensionPoint(URLFilter.X_POINT_ID);
+      try {
+        ExtensionPoint point =
+          nutchConf.getPluginRepository().getExtensionPoint(URLFilter.X_POINT_ID);
 
-      if (point == null)
-        throw new RuntimeException(URLFilter.X_POINT_ID+" not found.");
+        if (point == null)
+          throw new RuntimeException(URLFilter.X_POINT_ID+" not found.");
 
-      Extension[] extensions = point.getExtensions();
-      HashMap filterMap = new HashMap();
-      for (int i = 0; i < extensions.length; i++) {
-        Extension extension = extensions[i];
-        URLFilter filter = (URLFilter)extension.getExtensionInstance();
-        if (!filterMap.containsKey(filter.getClass().getName())) {
-        	filterMap.put(filter.getClass().getName(), filter);
+        Extension[] extensions = point.getExtensions();
+        HashMap filterMap = new HashMap();
+        for (int i = 0; i < extensions.length; i++) {
+          Extension extension = extensions[i];
+          URLFilter filter = (URLFilter)extension.getExtensionInstance();
+          if (!filterMap.containsKey(filter.getClass().getName())) {
+            filterMap.put(filter.getClass().getName(), filter);
+          }
         }
-      }
-      if (orderedFilters==null) {
-        CACHE = (URLFilter[])filterMap.values().toArray(new URLFilter[0]);
-      } else {
-        CACHE = new URLFilter[orderedFilters.length];
-        for (int i=0; i<orderedFilters.length; i++) {
-          CACHE[i] = (URLFilter)filterMap.get(orderedFilters[i]);
+        if (orderedFilters==null) {
+          CACHE = (URLFilter[])filterMap.values().toArray(new URLFilter[0]);
+        } else {
+          CACHE = new URLFilter[orderedFilters.length];
+          for (int i=0; i<orderedFilters.length; i++) {
+            CACHE[i] = (URLFilter)filterMap.get(orderedFilters[i]);
+          }
         }
+      } catch (PluginRuntimeException e) {
+        throw new RuntimeException(e);
       }
-    } catch (PluginRuntimeException e) {
-      throw new RuntimeException(e);
-    }
-  }
+  }  
 
-  private URLFilters() {}                  // no public ctor
-
   /** Run all defined filters. Assume logical AND. */
-  public static String filter(String urlString) throws URLFilterException {
+  public String filter(String urlString) throws URLFilterException {
 
     for (int i = 0; i < CACHE.length; i++) {
       if (urlString == null)
Index: src/java/org/apache/nutch/net/URLFilterChecker.java
===================================================================
--- src/java/org/apache/nutch/net/URLFilterChecker.java	(revision 359225)
+++ src/java/org/apache/nutch/net/URLFilterChecker.java	(working copy)
@@ -21,6 +21,7 @@
 import org.apache.nutch.plugin.PluginRepository;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 import java.util.logging.Logger;
 
@@ -37,14 +38,17 @@
 
   public static final Logger LOG =
     LogFormatter.getLogger(URLFilterChecker.class.getName());
+  private NutchConf nutchConf;
 
-  public URLFilterChecker() {}
+  public URLFilterChecker(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+  }
 
   private void checkOne(String filterName) throws Exception {
     URLFilter filter = null;
 
     ExtensionPoint point =
-      PluginRepository.getInstance().getExtensionPoint(URLFilter.X_POINT_ID);
+      this.nutchConf.getPluginRepository().getExtensionPoint(URLFilter.X_POINT_ID);
 
     if (point == null)
       throw new RuntimeException(URLFilter.X_POINT_ID+" not found.");
@@ -90,7 +94,7 @@
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
     String line;
     while((line=in.readLine())!=null) {
-      String out=URLFilters.filter(line);
+      String out=new URLFilters(this.nutchConf).filter(line);
       if(out!=null) {
         System.out.print("+");
         System.out.println(out);
@@ -119,7 +123,7 @@
       filterName = args[1];
     }
 
-    URLFilterChecker checker = new URLFilterChecker();
+    URLFilterChecker checker = new URLFilterChecker(new NutchConf());
     if (filterName != null) {
       checker.checkOne(filterName);
     } else {
Index: src/java/org/apache/nutch/net/UrlNormalizerFactory.java
===================================================================
--- src/java/org/apache/nutch/net/UrlNormalizerFactory.java	(revision 359225)
+++ src/java/org/apache/nutch/net/UrlNormalizerFactory.java	(working copy)
@@ -17,6 +17,8 @@
 package org.apache.nutch.net;
 
 import org.apache.nutch.util.*;
+
+import java.net.URL;
 import java.util.logging.*;
 
 /** Factory to create a UrlNormalizer from "urlnormalizer.class" config property. */
@@ -24,28 +26,22 @@
   private static final Logger LOG =
     LogFormatter.getLogger("org.apache.nutch.net.UrlNormalizerFactory");
 
-  private static final String URLNORMALIZER_CLASS =
-    NutchConf.get().get("urlnormalizer.class");
-
   private UrlNormalizerFactory() {}                   // no public ctor
 
-  private static UrlNormalizer normalizer;
-
   /** Return the default UrlNormalizer implementation. */
-  public static UrlNormalizer getNormalizer() {
+  public static UrlNormalizer getNormalizer(NutchConf nutchConf) {
 
-    if (normalizer == null) {
-      try {
-        LOG.info("Using URL normalizer: " + URLNORMALIZER_CLASS);
-        Class normalizerClass = Class.forName(URLNORMALIZER_CLASS);
-        normalizer = (UrlNormalizer)normalizerClass.newInstance();
-      } catch (Exception e) {
-        throw new RuntimeException("Couldn't create "+URLNORMALIZER_CLASS, e);
-      }
-    }
-
-    return normalizer;
-
+      UrlNormalizer normalizer = null;
+      String urlNormalizer = null;
+        try {
+            urlNormalizer = nutchConf.get("urlnormalizer.class");
+            LOG.info("Using URL normalizer: " + urlNormalizer);
+            Class normalizerClass = Class.forName(urlNormalizer);
+            normalizer = (UrlNormalizer) normalizerClass.newInstance();
+            normalizer.setConf(nutchConf);
+        } catch (Exception e) {
+            throw new RuntimeException("Couldn't create " + urlNormalizer, e);
+        }
+        return normalizer;
   }
-
 }
Index: src/java/org/apache/nutch/ndfs/FSConstants.java
===================================================================
--- src/java/org/apache/nutch/ndfs/FSConstants.java	(revision 359225)
+++ src/java/org/apache/nutch/ndfs/FSConstants.java	(working copy)
@@ -107,8 +107,8 @@
     public static long LEASE_PERIOD = 60 * 1000;
     public static int READ_TIMEOUT = 60 * 1000;
 
-    public static int BUFFER_SIZE =
-      NutchConf.get().getInt("io.file.buffer.size", 4096);
+    //TODO mb: should be nutchConf injected?
+    public static int BUFFER_SIZE = new NutchConf().getInt("io.file.buffer.size", 4096);
 
 }
 
Index: src/java/org/apache/nutch/ndfs/FSNamesystem.java
===================================================================
--- src/java/org/apache/nutch/ndfs/FSNamesystem.java	(revision 359225)
+++ src/java/org/apache/nutch/ndfs/FSNamesystem.java	(working copy)
@@ -34,28 +34,8 @@
 public class FSNamesystem implements FSConstants {
     public static final Logger LOG = LogFormatter.getLogger("org.apache.nutch.fs.FSNamesystem");
 
-    // DESIRED_REPLICATION is how many copies we try to have at all times
-    final static int DESIRED_REPLICATION =
-      NutchConf.get().getInt("ndfs.replication", 3);
+   
 
-    // The maximum number of replicates we should allow for a single block
-    final static int MAX_REPLICATION = DESIRED_REPLICATION;
-
-    // How many outgoing replication streams a given node should have at one time
-    final static int MAX_REPLICATION_STREAMS = NutchConf.get().getInt("ndfs.max-repl-streams", 2);
-
-    // MIN_REPLICATION is how many copies we need in place or else we disallow the write
-    final static int MIN_REPLICATION = 1;
-
-    // HEARTBEAT_RECHECK is how often a datanode sends its hearbeat
-    final static long HEARTBEAT_RECHECK = 1000;
-
-    // Whether we should use disk-availability info when determining target
-    final static boolean USE_AVAILABILITY = NutchConf.get().getBoolean("ndfs.availability.allocation", false);
-
-    private boolean allowSameHostTargets =
-        NutchConf.get().getBoolean("test.ndfs.same.host.targets.allowed", false);
-
     //
     // Stores the correct file name hierarchy
     //
@@ -148,18 +128,44 @@
     Daemon hbthread = null, lmthread = null;
     boolean fsRunning = true;
     long systemStart = 0;
+    private NutchConf nutchConf;
+
+    //  DESIRED_REPLICATION is how many copies we try to have at all times
+    private int desiredReplication;
+    //  The maximum number of replicates we should allow for a single block
+    private int maxReplication;
+    //  How many outgoing replication streams a given node should have at one time
+    private int maxReplicationStreams;
+    // MIN_REPLICATION is how many copies we need in place or else we disallow the write
+    private int minReplication;
+    // HEARTBEAT_RECHECK is how often a datanode sends its hearbeat
+    private int heartBeatRecheck;
+   //  Whether we should use disk-availability info when determining target
+    private boolean useAvailability;
+
+    private boolean allowSameHostTargets;
     
     /**
      * dir is where the filesystem directory state 
      * is stored
      */
-    public FSNamesystem(File dir) throws IOException {
+    public FSNamesystem(File dir, NutchConf nutchConf) throws IOException {
         this.dir = new FSDirectory(dir);
         this.hbthread = new Daemon(new HeartbeatMonitor());
         this.lmthread = new Daemon(new LeaseMonitor());
         hbthread.start();
         lmthread.start();
         this.systemStart = System.currentTimeMillis();
+        this.nutchConf = nutchConf;
+        
+        this.desiredReplication = nutchConf.getInt("ndfs.replication", 3);
+        this.maxReplication = desiredReplication;
+        this.maxReplicationStreams = nutchConf.getInt("ndfs.max-repl-streams", 2);
+        this.minReplication = 1;
+        this.heartBeatRecheck= 1000;
+        this.useAvailability = nutchConf.getBoolean("ndfs.availability.allocation", false);
+        this.allowSameHostTargets =
+           nutchConf.getBoolean("test.ndfs.same.host.targets.allowed", false);
     }
 
     /** Close down this filesystem manager.
@@ -244,10 +250,10 @@
                 results = new Object[2];
 
                 // Get the array of replication targets 
-                DatanodeInfo targets[] = chooseTargets(DESIRED_REPLICATION, null);
-                if (targets.length < MIN_REPLICATION) {
+                DatanodeInfo targets[] = chooseTargets(this.desiredReplication, null);
+                if (targets.length < this.minReplication) {
                     LOG.warning("Target-length is " + targets.length +
-                        ", below MIN_REPLICATION (" + MIN_REPLICATION + ")");
+                        ", below MIN_REPLICATION (" + this.minReplication+ ")");
                     return null;
                 }
 
@@ -300,8 +306,8 @@
             //
             if (checkFileProgress(src)) {
                 // Get the array of replication targets 
-                DatanodeInfo targets[] = chooseTargets(DESIRED_REPLICATION, null);
-                if (targets.length < MIN_REPLICATION) {
+                DatanodeInfo targets[] = chooseTargets(this.desiredReplication, null);
+                if (targets.length < this.minReplication) {
                     return null;
                 }
 
@@ -411,9 +417,9 @@
                 // the blocks.
                 for (int i = 0; i < pendingBlocks.length; i++) {
                     TreeSet containingNodes = (TreeSet) blocksMap.get(pendingBlocks[i]);
-                    if (containingNodes.size() < DESIRED_REPLICATION) {
+                    if (containingNodes.size() < this.desiredReplication) {
                         synchronized (neededReplications) {
-                            LOG.info("Completed file " + src + ", at holder " + holder + ".  There is/are only " + containingNodes.size() + " copies of block " + pendingBlocks[i] + ", so replicating up to " + DESIRED_REPLICATION);
+                            LOG.info("Completed file " + src + ", at holder " + holder + ".  There is/are only " + containingNodes.size() + " copies of block " + pendingBlocks[i] + ", so replicating up to " + this.desiredReplication);
                             neededReplications.add(pendingBlocks[i]);
                         }
                     }
@@ -449,7 +455,7 @@
         for (Iterator it = v.iterator(); it.hasNext(); ) {
             Block b = (Block) it.next();
             TreeSet containingNodes = (TreeSet) blocksMap.get(b);
-            if (containingNodes == null || containingNodes.size() < MIN_REPLICATION) {
+            if (containingNodes == null || containingNodes.size() < this.minReplication) {
                 return false;
             }
         }
@@ -814,7 +820,7 @@
             while (fsRunning) {
                 heartbeatCheck();
                 try {
-                    Thread.sleep(HEARTBEAT_RECHECK);
+                    Thread.sleep(heartBeatRecheck);
                 } catch (InterruptedException ie) {
                 }
             }
@@ -946,10 +952,10 @@
 
         synchronized (neededReplications) {
             if (dir.isValidBlock(block)) {
-                if (containingNodes.size() >= DESIRED_REPLICATION) {
+                if (containingNodes.size() >= this.desiredReplication) {
                     neededReplications.remove(block);
                     pendingReplications.remove(block);
-                } else if (containingNodes.size() < DESIRED_REPLICATION) {
+                } else if (containingNodes.size() < this.desiredReplication) {
                     if (! neededReplications.contains(block)) {
                         neededReplications.add(block);
                     }
@@ -968,8 +974,8 @@
                         nonExcess.add(cur);
                     }
                 }
-                if (nonExcess.size() > MAX_REPLICATION) {
-                    chooseExcessReplicates(nonExcess, block, MAX_REPLICATION);    
+                if (nonExcess.size() > this.maxReplication) {
+                    chooseExcessReplicates(nonExcess, block, this.maxReplication);    
                 }
             }
         }
@@ -1032,7 +1038,7 @@
         // necessary.  In that case, put block on a possibly-will-
         // be-replicated list.
         //
-        if (dir.isValidBlock(block) && (containingNodes.size() < DESIRED_REPLICATION)) {
+        if (dir.isValidBlock(block) && (containingNodes.size() < this.desiredReplication)) {
             synchronized (neededReplications) {
                 neededReplications.add(block);
             }
@@ -1147,7 +1153,7 @@
                     //
                     // We can only reply with 'maxXfers' or fewer blocks
                     //
-                    if (scheduledXfers >= MAX_REPLICATION_STREAMS - xmitsInProgress) {
+                    if (scheduledXfers >= this.maxReplicationStreams - xmitsInProgress) {
                         break;
                     }
 
@@ -1157,7 +1163,7 @@
                     } else {
                         TreeSet containingNodes = (TreeSet) blocksMap.get(block);
                         if (containingNodes.contains(srcNode)) {
-                            DatanodeInfo targets[] = chooseTargets(Math.min(DESIRED_REPLICATION - containingNodes.size(), MAX_REPLICATION_STREAMS - xmitsInProgress), containingNodes);
+                            DatanodeInfo targets[] = chooseTargets(Math.min(this.desiredReplication - containingNodes.size(), this.maxReplicationStreams - xmitsInProgress), containingNodes);
                             if (targets.length > 0) {
                                 // Build items to return
                                 replicateBlocks.add(block);
@@ -1181,7 +1187,7 @@
                         DatanodeInfo targets[] = (DatanodeInfo[]) replicateTargetSets.elementAt(i);
                         TreeSet containingNodes = (TreeSet) blocksMap.get(block);
 
-                        if (containingNodes.size() + targets.length >= DESIRED_REPLICATION) {
+                        if (containingNodes.size() + targets.length >= this.desiredReplication) {
                             neededReplications.remove(block);
                             pendingReplications.add(block);
                         }
@@ -1313,7 +1319,7 @@
                 " forbidden2.size()=" +
                 ( forbidden2 != null ? forbidden2.size() : 0 ));
             return null;
-        } else if (! USE_AVAILABILITY) {
+        } else if (! this.useAvailability) {
             int target = r.nextInt(targetList.size());
             return (DatanodeInfo) targetList.elementAt(target);
         } else {
Index: src/java/org/apache/nutch/ndfs/FSDataset.java
===================================================================
--- src/java/org/apache/nutch/ndfs/FSDataset.java	(revision 359225)
+++ src/java/org/apache/nutch/ndfs/FSDataset.java	(working copy)
@@ -191,7 +191,7 @@
     /**
      * An FSDataset has a directory where it loads its data files.
      */
-    public FSDataset(File dir) throws IOException {
+    public FSDataset(File dir, NutchConf nutchConf) throws IOException {
         this.dirpath = dir.getCanonicalPath();
         this.data = new File(dir, "data");
         if (! data.exists()) {
@@ -199,7 +199,7 @@
         }
         this.tmp = new File(dir, "tmp");
         if (tmp.exists()) {
-            FileUtil.fullyDelete(tmp);
+            FileUtil.fullyDelete(tmp, nutchConf);
         }
         this.tmp.mkdirs();
         this.dirTree = new FSDir(data);
Index: src/java/org/apache/nutch/ndfs/DataNode.java
===================================================================
--- src/java/org/apache/nutch/ndfs/DataNode.java	(revision 359225)
+++ src/java/org/apache/nutch/ndfs/DataNode.java	(working copy)
@@ -85,8 +85,8 @@
      * Needs a directory to find its data (and config info)
      */
     public DataNode(String machineName, File datadir, InetSocketAddress nameNodeAddr, NutchConf conf) throws IOException {
-        this.namenode = (DatanodeProtocol) RPC.getProxy(DatanodeProtocol.class, nameNodeAddr);
-        this.data = new FSDataset(datadir);
+        this.namenode = (DatanodeProtocol) RPC.getProxy(DatanodeProtocol.class, nameNodeAddr, conf);
+        this.data = new FSDataset(datadir, conf);
 
         ServerSocket ss = null;
         int tmpPort = conf.getInt("ndfs.datanode.port", 50010);
@@ -748,6 +748,6 @@
      */
     public static void main(String args[]) throws IOException {
         LogFormatter.setShowThreadIDs(true);
-        runAndWait(NutchConf.get());
+        runAndWait(new NutchConf());
     }
 }
Index: src/java/org/apache/nutch/ndfs/NameNode.java
===================================================================
--- src/java/org/apache/nutch/ndfs/NameNode.java	(revision 359225)
+++ src/java/org/apache/nutch/ndfs/NameNode.java	(working copy)
@@ -48,21 +48,20 @@
     /**
      * Create a NameNode at the default location
      */
-    public NameNode() throws IOException {
-        this(new File(NutchConf.get().get("ndfs.name.dir",
+    public NameNode(NutchConf nutchConf) throws IOException {
+        this(new File(nutchConf.get("ndfs.name.dir",
                                           "/tmp/nutch/ndfs/name")),
              DataNode.createSocketAddr
-             (NutchConf.get().get("fs.default.name", "local")).getPort());
+             (nutchConf.get("fs.default.name", "local")).getPort(), nutchConf);
     }
 
     /**
      * Create a NameNode at the specified location and start it.
      */
-    public NameNode(File dir, int port) throws IOException {
-        this.namesystem = new FSNamesystem(dir);
-        this.handlerCount =
-            NutchConf.get().getInt("ndfs.namenode.handler.count", 10);
-        this.server = RPC.getServer(this, port, handlerCount, false);
+    public NameNode(File dir, int port, NutchConf nutchConf) throws IOException {
+        this.namesystem = new FSNamesystem(dir, nutchConf);
+        this.handlerCount = nutchConf.getInt("ndfs.namenode.handler.count", 10);
+        this.server = RPC.getServer(this, port, handlerCount, false, nutchConf);
         this.server.start();
     }
 
@@ -346,7 +345,7 @@
     /**
      */
     public static void main(String argv[]) throws IOException, InterruptedException {
-        NameNode namenode = new NameNode();
+        NameNode namenode = new NameNode(new NutchConf());
         namenode.join();
     }
 }
Index: src/java/org/apache/nutch/ndfs/NDFSClient.java
===================================================================
--- src/java/org/apache/nutch/ndfs/NDFSClient.java	(revision 359225)
+++ src/java/org/apache/nutch/ndfs/NDFSClient.java	(working copy)
@@ -42,8 +42,8 @@
 
     /** Create a new NDFSClient connected to the given namenode server.
      */
-    public NDFSClient(InetSocketAddress nameNodeAddr) {
-        this.namenode = (ClientProtocol) RPC.getProxy(ClientProtocol.class, nameNodeAddr);
+    public NDFSClient(InetSocketAddress nameNodeAddr, NutchConf nutchConf) {
+        this.namenode = (ClientProtocol) RPC.getProxy(ClientProtocol.class, nameNodeAddr, nutchConf);
         this.clientName = "NDFSClient_" + r.nextInt();
         this.leaseChecker = new Daemon(new LeaseChecker());
         this.leaseChecker.start();
Index: src/java/org/apache/nutch/searcher/LuceneQueryOptimizer.java
===================================================================
--- src/java/org/apache/nutch/searcher/LuceneQueryOptimizer.java	(revision 367309)
+++ src/java/org/apache/nutch/searcher/LuceneQueryOptimizer.java	(working copy)
@@ -37,7 +37,7 @@
  * which do not affect ranking but might otherwise slow search considerably. */
 class LuceneQueryOptimizer {
 
-  private static int MAX_HITS = NutchConf.get().getInt("searcher.max.hits",-1);
+//  private int MAX_HITS;
 
   private static class LimitExceeded extends RuntimeException {
     private int maxDoc;
@@ -63,18 +63,24 @@
 
   private float threshold;
 
+  private int searcherMaxHits;
+
   /** Construct an optimizer that caches and uses filters for required clauses
    * whose boost is zero.
    * @param cacheSize the number of QueryFilters to cache
    * @param threshold the fraction of documents which must contain a term
    */
-  public LuceneQueryOptimizer(final int cacheSize, float threshold) {
+  public LuceneQueryOptimizer(NutchConf nutchConf) {
+      final int cacheSize = nutchConf.getInt("searcher.filter.cache.size", 16);
+      this.threshold = nutchConf.getFloat("searcher.filter.cache.threshold", 0.05f);
+      this.searcherMaxHits = nutchConf.getInt("searcher.max.hits",-1);
+      
+      this.searcherMaxHits =searcherMaxHits;
     this.cache = new LinkedHashMap(cacheSize, 0.75f, true) {
         protected boolean removeEldestEntry(Map.Entry eldest) {
           return size() > cacheSize;              // limit size of cache
         }
       };
-    this.threshold = threshold;
   }
 
   public TopDocs optimize(BooleanQuery original,
@@ -151,12 +157,12 @@
     if (sortField == null && !reverse) {
 
       // no hit limit
-      if (MAX_HITS <= 0) {
+      if (this.searcherMaxHits <= 0) {
         return searcher.search(query, filter, numHits);
       }
 
       // hits limited -- use a LimitedCollector
-      LimitedCollector collector = new LimitedCollector(numHits, MAX_HITS);
+      LimitedCollector collector = new LimitedCollector(numHits, searcherMaxHits);
       LimitExceeded exceeded = null;
       try {
         searcher.search(query, filter, collector);
Index: src/java/org/apache/nutch/searcher/Query.java
===================================================================
--- src/java/org/apache/nutch/searcher/Query.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/Query.java	(working copy)
@@ -26,6 +26,7 @@
 import java.util.logging.Logger;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.analysis.NutchAnalysis;
 
 import org.apache.nutch.io.Writable;
@@ -47,30 +48,34 @@
     private boolean isProhibited;
     private String field = DEFAULT_FIELD;
     private float weight = 1.0f;
-    private Object termOrPhrase; 
+    private Object termOrPhrase;
 
+    private NutchConf nutchConf; 
+
     public Clause(Term term, String field,
-                  boolean isRequired, boolean isProhibited) {
-      this(term, isRequired, isProhibited);
+                  boolean isRequired, boolean isProhibited, NutchConf nutchConf) {
+      this(term, isRequired, isProhibited, nutchConf);
       this.field = field;
     }
 
-    public Clause(Term term, boolean isRequired, boolean isProhibited) {
+    public Clause(Term term, boolean isRequired, boolean isProhibited, NutchConf nutchConf) {
       this.isRequired = isRequired;
       this.isProhibited = isProhibited;
       this.termOrPhrase = term;
+      this.nutchConf = nutchConf;
     }
 
     public Clause(Phrase phrase, String field,
-                  boolean isRequired, boolean isProhibited) {
-      this(phrase, isRequired, isProhibited);
+                  boolean isRequired, boolean isProhibited, NutchConf nutchConf) {
+      this(phrase, isRequired, isProhibited, nutchConf);
       this.field = field;
     }
 
-    public Clause(Phrase phrase, boolean isRequired, boolean isProhibited) {
+    public Clause(Phrase phrase, boolean isRequired, boolean isProhibited, NutchConf nutchConf) {
       this.isRequired = isRequired;
       this.isProhibited = isProhibited;
       this.termOrPhrase = phrase;
+      this.nutchConf = nutchConf;
     }
 
     public boolean isRequired() { return isRequired; }
@@ -104,7 +109,7 @@
         getTerm().write(out);
     }
 
-    public static Clause read(DataInput in) throws IOException {
+    public static Clause read(DataInput in, NutchConf nutchConf) throws IOException {
       byte bits = in.readByte();
       boolean required = ((bits & REQUIRED_BIT) != 0);
       boolean prohibited = ((bits & PROHIBITED_BIT) != 0);
@@ -114,9 +119,9 @@
 
       Clause clause;
       if ((bits & PHRASE_BIT) == 0) {
-        clause = new Clause(Term.read(in), field, required, prohibited);
+        clause = new Clause(Term.read(in), field, required, prohibited, nutchConf);
       } else {
-        clause = new Clause(Phrase.read(in), field, required, prohibited);
+        clause = new Clause(Phrase.read(in), field, required, prohibited, nutchConf);
       }
       clause.weight = weight;
       return clause;
@@ -135,7 +140,7 @@
         buffer.append(":");
       }
 
-      if (!isPhrase() && QueryFilters.isRawField(field)) {
+      if (!isPhrase() && new QueryFilters(this.nutchConf).isRawField(field)) {
         buffer.append('"');                        // quote raw terms
         buffer.append(termOrPhrase.toString());
         buffer.append('"');
@@ -274,7 +279,13 @@
 
   private ArrayList clauses = new ArrayList();
 
+  private NutchConf nutchConf;
+
   private static final Clause[] CLAUSES_PROTO = new Clause[0];
+  
+  public Query(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+  }
 
   /** Return all clauses. */
   public Clause[] getClauses() {
@@ -288,7 +299,7 @@
 
   /** Add a required term in a specified field. */
   public void addRequiredTerm(String term, String field) {
-    clauses.add(new Clause(new Term(term), field, true, false));
+    clauses.add(new Clause(new Term(term), field, true, false, this.nutchConf));
   }
 
   /** Add a prohibited term in the default field. */
@@ -298,7 +309,7 @@
 
   /** Add a prohibited term in the specified field. */
   public void addProhibitedTerm(String term, String field) {
-    clauses.add(new Clause(new Term(term), field, false, true));
+    clauses.add(new Clause(new Term(term), field, false, true, this.nutchConf));
   }
 
   /** Add a required phrase in the default field. */
@@ -312,7 +323,7 @@
     } else if (terms.length == 1) {
       addRequiredTerm(terms[0], field);           // optimize to term query
     } else {
-      clauses.add(new Clause(new Phrase(terms), field, true, false));
+      clauses.add(new Clause(new Phrase(terms), field, true, false, this.nutchConf));
     }
   }
 
@@ -327,7 +338,7 @@
     } else if (terms.length == 1) {
       addProhibitedTerm(terms[0], field);         // optimize to term query
     } else {
-      clauses.add(new Clause(new Phrase(terms), field, false, true));
+      clauses.add(new Clause(new Phrase(terms), field, false, true, this.nutchConf));
     }
   }
 
@@ -337,8 +348,8 @@
       ((Clause)clauses.get(i)).write(out);
   }
   
-  public static Query read(DataInput in) throws IOException {
-    Query result = new Query();
+  public static Query read(DataInput in, NutchConf nutchConf) throws IOException {
+    Query result = new Query(nutchConf);
     result.readFields(in);
     return result;
   }
@@ -347,7 +358,7 @@
     clauses.clear();
     int length = in.readByte();
     for (int i = 0; i < length; i++)
-      clauses.add(Clause.read(in));
+      clauses.add(Clause.read(in, this.nutchConf));
   }
 
   public String toString() {
@@ -404,18 +415,18 @@
 
 
   /** Parse a query from a string. */
-  public static Query parse(String queryString) throws IOException {
-    return fixup(NutchAnalysis.parseQuery(queryString));
+  public static Query parse(String queryString, NutchConf nutchConf) throws IOException {
+    return fixup(NutchAnalysis.parseQuery(queryString, nutchConf), nutchConf);
   }
 
   /** Convert clauses in unknown fields to the default field. */
-  private static Query fixup(Query input) {
+  private static Query fixup(Query input, NutchConf nutchConf) {
     // walk the query
-    Query output = new Query();
+    Query output = new Query(nutchConf);
     Clause[] clauses = input.getClauses();
     for (int i = 0; i < clauses.length; i++) {
       Clause c = clauses[i];
-      if (!QueryFilters.isField(c.getField())) {  // unknown field
+      if (!new QueryFilters(nutchConf).isField(c.getField())) {  // unknown field
         ArrayList terms = new ArrayList();        // add name to query
         if (c.isPhrase()) {                       
           terms.addAll(Arrays.asList(c.getPhrase().getTerms()));
@@ -436,12 +447,13 @@
   /** For debugging. */
   public static void main(String[] args) throws Exception {
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+    NutchConf nutchConf = new NutchConf();
     while (true) {
       System.out.print("Query: ");
       String line = in.readLine();
-      Query query = parse(line);
+      Query query = parse(line, nutchConf);
       System.out.println("Parsed: " + query);
-      System.out.println("Translated: " + QueryFilters.filter(query));
+      System.out.println("Translated: " + new QueryFilters(nutchConf).filter(query));
     }
   }
 }
Index: src/java/org/apache/nutch/searcher/NutchBean.java
===================================================================
--- src/java/org/apache/nutch/searcher/NutchBean.java	(revision 367309)
+++ src/java/org/apache/nutch/searcher/NutchBean.java	(working copy)
@@ -42,7 +42,7 @@
     LogFormatter.setShowThreadIDs(true);
   }
 
-  private NutchFileSystem fs = NutchFileSystem.get();
+  //private NutchFileSystem fs = NutchFileSystem.get();
 
   private String[] segmentNames;
 
@@ -52,50 +52,62 @@
   private HitContent content;
   private HitInlinks linkDb;
 
-  private float RAW_HITS_FACTOR =
-    NutchConf.get().getFloat("searcher.hostgrouping.rawhits.factor", 2.0f);
 
   /** BooleanQuery won't permit more than 32 required/prohibited clauses.  We
    * don't want to use too many of those. */ 
   private static final int MAX_PROHIBITED_TERMS = 20;
+  
+  private NutchConf nutchConf;
 
+private NutchFileSystem fs;
+
   /** Cache in servlet context. */
-  public static NutchBean get(ServletContext app) throws IOException {
+  public static NutchBean get(ServletContext app, NutchConf nutchConf) throws IOException {
     NutchBean bean = (NutchBean)app.getAttribute("nutchBean");
     if (bean == null) {
       LOG.info("creating new bean");
-      bean = new NutchBean();
+      bean = new NutchBean(nutchConf);
       app.setAttribute("nutchBean", bean);
     }
     return bean;
   }
 
-  /** Construct reading from connected directory. */
-  public NutchBean() throws IOException {
-    this(new File(NutchConf.get().get("searcher.dir", "crawl")));
-  }
+  //TODO delete
+//  /** Construct reading from connected directory. */
+//  public NutchBean(NutchConf nutchConf) throws IOException {
+//    this(nutchConf);
+//  }
 
   /** Construct in a named directory. */
-  public NutchBean(File dir) throws IOException {
-    File servers = new File(dir, "search-servers.txt");
-    if (fs.exists(servers)) {
-      LOG.info("searching servers in " + servers.getCanonicalPath());
-      init(new DistributedSearch.Client(servers));
-    } else {
-      init(new File(dir, "index"),
-           new File(dir, "indexes"),
-           new File(dir, "segments"),
-           new File(dir, "linkdb"));
-    }
+  public NutchBean(NutchConf nutchConf) throws IOException {
+    this(nutchConf, null);
   }
+  
+  public NutchBean(NutchConf nutchConf, File dir) throws IOException {
+      this.nutchConf = nutchConf;
+      this.fs = NutchFileSystem.get(this.nutchConf);
+      if(dir==null){
+          dir = new File(this.nutchConf.get("searcher.dir", "crawl"));
+      }
+      File servers = new File(dir, "search-servers.txt");
+      if (fs.exists(servers)) {
+        LOG.info("searching servers in " + servers.getCanonicalPath());
+        init(new DistributedSearch.Client(servers, nutchConf));
+      } else {
+        init(new File(dir, "index"),
+             new File(dir, "indexes"),
+             new File(dir, "segments"),
+             new File(dir, "linkdb"));
+      }      
+  }
 
   private void init(File indexDir, File indexesDir, File segmentsDir,
                     File linkDb)
     throws IOException {
     IndexSearcher indexSearcher;
-    if (fs.exists(indexDir)) {
+    if (this.fs.exists(indexDir)) {
       LOG.info("opening merged index in " + indexDir);
-      indexSearcher = new IndexSearcher(indexDir);
+      indexSearcher = new IndexSearcher(indexDir,this.nutchConf);
     } else {
       LOG.info("opening indexes in " + indexesDir);
       
@@ -108,16 +120,17 @@
         }
       }
       
+      
       directories = new File[ vDirs.size() ];
       for(int i = 0; vDirs.size()>0; i++) {
         directories[i]=(File)vDirs.remove(0);
       }
       
-      indexSearcher = new IndexSearcher(directories);
+      indexSearcher = new IndexSearcher(directories,this.nutchConf);
     }
 
     LOG.info("opening segments in " + segmentsDir);
-    FetchedSegments segments = new FetchedSegments(fs, segmentsDir.toString());
+    FetchedSegments segments = new FetchedSegments(this.fs, segmentsDir.toString(),this.nutchConf);
     
     this.segmentNames = segments.getSegmentNames();
 
@@ -127,7 +140,7 @@
     this.content = segments;
 
     LOG.info("opening linkdb in " + linkDb);
-    this.linkDb = new LinkDbInlinks(fs, linkDb);
+    this.linkDb = new LinkDbInlinks(fs, linkDb, this.nutchConf);
   }
 
   private void init(DistributedSearch.Client client) {
@@ -216,7 +229,8 @@
     if (maxHitsPerDup <= 0)                      // disable dup checking
       return search(query, numHits, dedupField, sortField, reverse);
 
-    int numHitsRaw = (int)(numHits * RAW_HITS_FACTOR);
+    float rawHitsFactor = this.nutchConf.getFloat("searcher.hostgrouping.rawhits.factor", 2.0f);
+    int numHitsRaw = (int)(numHits * rawHitsFactor);
     LOG.info("searching for "+numHitsRaw+" raw hits");
     Hits hits = searcher.search(query, numHitsRaw,
                                 dedupField, sortField, reverse);
@@ -237,7 +251,7 @@
           optQuery.addProhibitedTerm(((String)excludedValues.get(i)),
                                      dedupField);
         }
-        numHitsRaw = (int)(numHitsRaw * RAW_HITS_FACTOR);
+        numHitsRaw = (int)(numHitsRaw * rawHitsFactor);
         LOG.info("re-searching for "+numHitsRaw+" raw hits, query: "+optQuery);
         hits = searcher.search(optQuery, numHitsRaw,
                                dedupField, sortField, reverse);
@@ -344,8 +358,9 @@
       System.exit(-1);
     }
 
-    NutchBean bean = new NutchBean();
-    Query query = Query.parse(args[0]);
+    NutchConf nutchConf = new NutchConf();
+    NutchBean bean = new NutchBean(nutchConf);
+    Query query = Query.parse(args[0], nutchConf);
 
     Hits hits = bean.search(query, 10);
     System.out.println("Total hits: " + hits.getTotal());
Index: src/java/org/apache/nutch/searcher/FetchedSegments.java
===================================================================
--- src/java/org/apache/nutch/searcher/FetchedSegments.java	(revision 367309)
+++ src/java/org/apache/nutch/searcher/FetchedSegments.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.nutch.fs.*;
 import org.apache.nutch.protocol.*;
 import org.apache.nutch.parse.*;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.mapred.*;
 import org.apache.nutch.mapred.lib.*;
 import org.apache.nutch.crawl.*;
@@ -43,10 +44,12 @@
     private MapFile.Reader[] parseText;
     private MapFile.Reader[] parseData;
     private MapFile.Reader[] crawl;
+    private NutchConf nutchConf;
 
-    public Segment(NutchFileSystem nfs, File segmentDir) throws IOException {
+    public Segment(NutchFileSystem nfs, File segmentDir, NutchConf nutchConf) throws IOException {
       this.nfs = nfs;
       this.segmentDir = segmentDir;
+      this.nutchConf = nutchConf;
     }
 
     public CrawlDatum getCrawlDatum(UTF8 url) throws IOException {
@@ -82,7 +85,7 @@
     }
     
     private MapFile.Reader[] getReaders(String subDir) throws IOException {
-      return MapFileOutputFormat.getReaders(nfs, new File(segmentDir, subDir));
+      return MapFileOutputFormat.getReaders(nfs, new File(segmentDir, subDir), this.nutchConf);
     }
 
     private Writable getEntry(MapFile.Reader[] readers, UTF8 url,
@@ -93,10 +96,14 @@
   }
 
   private HashMap segments = new HashMap();
+  private int sumContext=5;
+  private int sumLength = 20;
 
   /** Construct given a directory containing fetcher output. */
-  public FetchedSegments(NutchFileSystem nfs, String segmentsDir) throws IOException {
+  public FetchedSegments(NutchFileSystem nfs, String segmentsDir, NutchConf nutchConf) throws IOException {
     File[] segmentDirs = nfs.listFiles(new File(segmentsDir));
+    this.sumContext = nutchConf.getInt("searcher.summary.context", 5);
+    this.sumLength = nutchConf.getInt("searcher.summary.length", 20);
 
     if (segmentDirs != null) {
         for (int i = 0; i < segmentDirs.length; i++) {
@@ -105,7 +112,7 @@
 //             if (nfs.exists(indexdone) && nfs.isFile(indexdone)) {
 //             	segments.put(segmentDir.getName(), new Segment(nfs, segmentDir));
 //             }
-            segments.put(segmentDir.getName(), new Segment(nfs, segmentDir));
+            segments.put(segmentDir.getName(), new Segment(nfs, segmentDir, nutchConf));
 
         }
     }
@@ -137,7 +144,7 @@
 
     String text = getSegment(details).getParseText(getUrl(details)).getText();
 
-    return new Summarizer().getSummary(text, query).toString();
+    return new Summarizer().getSummary(text, query, this.sumContext, this.sumLength).toString();
   }
     
   private class SummaryThread extends Thread {
Index: src/java/org/apache/nutch/searcher/DistributedSearch.java
===================================================================
--- src/java/org/apache/nutch/searcher/DistributedSearch.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/DistributedSearch.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.parse.ParseText;
 import org.apache.nutch.crawl.Inlinks;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.io.*;
 import org.apache.nutch.ipc.RPC;
 
@@ -61,9 +62,10 @@
       int port = Integer.parseInt(args[0]);
       File directory = new File(args[1]);
 
-      NutchBean bean = new NutchBean(directory);
+      NutchConf nutchConf = new NutchConf();
+      NutchBean bean = new NutchBean(nutchConf, directory);
 
-      org.apache.nutch.ipc.Server server = RPC.getServer(bean, port, 10, true);
+      org.apache.nutch.ipc.Server server = RPC.getServer(bean, port, 10, true, nutchConf);
       server.start();
       server.join();
     }
@@ -80,14 +82,15 @@
     private HashMap segmentToAddress = new HashMap();
     
     private boolean running = true;
+    private NutchConf nutchConf;
 
     /** Construct a client talking to servers listed in the named file.
      * Each line in the file lists a server hostname and port, separated by
      * whitespace. 
      */
 
-    public Client(File file) throws IOException {
-      this(readConfig(file));
+    public Client(File file, NutchConf nutchConf) throws IOException {
+      this(readConfig(file), nutchConf);
     }
 
     private static InetSocketAddress[] readConfig(File config)
@@ -111,11 +114,12 @@
     }
 
     /** Construct a client talking to the named servers. */
-    public Client(InetSocketAddress[] addresses) throws IOException {
+    public Client(InetSocketAddress[] addresses, NutchConf nutchConf) throws IOException {
       this.defaultAddresses = addresses;
       updateSegments();
       setDaemon(true);
       start();
+      this.nutchConf = nutchConf;
     }
     
     private static final Method GET_SEGMENTS;
@@ -152,7 +156,7 @@
       // build segmentToAddress map
       Object[][] params = new Object[defaultAddresses.length][0];
       String[][] results =
-        (String[][])RPC.call(GET_SEGMENTS, params, defaultAddresses);
+        (String[][])RPC.call(GET_SEGMENTS, params, defaultAddresses, this.nutchConf);
 
       for (int i = 0; i < results.length; i++) {  // process results of call
         InetSocketAddress addr = defaultAddresses[i];
@@ -196,7 +200,7 @@
         params[i][3] = sortField;
         params[i][4] = Boolean.valueOf(reverse);
       }
-      Hits[] results = (Hits[])RPC.call(SEARCH, params, liveAddresses);
+      Hits[] results = (Hits[])RPC.call(SEARCH, params, liveAddresses, this.nutchConf);
 
       TreeSet queue;                              // cull top hits from results
 
@@ -235,13 +239,13 @@
     
     private Protocol getRemote(Hit hit) {
       return (Protocol)
-        RPC.getProxy(Protocol.class, liveAddresses[hit.getIndexNo()]);
+        RPC.getProxy(Protocol.class, liveAddresses[hit.getIndexNo()], nutchConf);
     }
 
     private Protocol getRemote(HitDetails hit) {
       InetSocketAddress address =
         (InetSocketAddress)segmentToAddress.get(hit.getValue("segment"));
-      return (Protocol)RPC.getProxy(Protocol.class, address);
+      return (Protocol)RPC.getProxy(Protocol.class, address, nutchConf);
     }
 
     public String getExplanation(Query query, Hit hit) throws IOException {
@@ -259,7 +263,7 @@
         addrs[i] = liveAddresses[hits[i].getIndexNo()];
         params[i][0] = hits[i];
       }
-      return (HitDetails[])RPC.call(DETAILS, params, addrs);
+      return (HitDetails[])RPC.call(DETAILS, params, addrs, nutchConf);
     }
 
 
@@ -278,7 +282,7 @@
         params[i][0] = hit;
         params[i][1] = query;
       }
-      return (String[])RPC.call(SUMMARY, params, addrs);
+      return (String[])RPC.call(SUMMARY, params, addrs, nutchConf);
     }
     
     public byte[] getContent(HitDetails hit) throws IOException {
@@ -313,7 +317,7 @@
         System.exit(-1);
       }
 
-      Query query = Query.parse(args[0]);
+      Query query = Query.parse(args[0], new NutchConf());
       
       InetSocketAddress[] addresses = new InetSocketAddress[(args.length-1)/2];
       for (int i = 0; i < (args.length-1)/2; i++) {
@@ -321,7 +325,7 @@
           new InetSocketAddress(args[i*2+1], Integer.parseInt(args[i*2+2]));
       }
 
-      Client client = new Client(addresses);
+      Client client = new Client(addresses, new NutchConf());
       //client.setTimeout(Integer.MAX_VALUE);
 
       Hits hits = client.search(query, 10, null, null, false);
Index: src/java/org/apache/nutch/searcher/QueryFilter.java
===================================================================
--- src/java/org/apache/nutch/searcher/QueryFilter.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/QueryFilter.java	(working copy)
@@ -17,12 +17,13 @@
 package org.apache.nutch.searcher;
 
 import org.apache.lucene.search.BooleanQuery;
+import org.apache.nutch.util.NutchConfigurable;
 
 /** Extension point for query translation.  Permits one to add metadata to a
  * query.  All plugins found which implement this extension point are run
  * sequentially on the query.
  */
-public interface QueryFilter {
+public interface QueryFilter extends NutchConfigurable{
   /** The name of the extension point. */
   final static String X_POINT_ID = QueryFilter.class.getName();
 
Index: src/java/org/apache/nutch/searcher/FieldQueryFilter.java
===================================================================
--- src/java/org/apache/nutch/searcher/FieldQueryFilter.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/FieldQueryFilter.java	(working copy)
@@ -25,12 +25,15 @@
 
 import org.apache.nutch.searcher.Query.Clause;
 import org.apache.nutch.searcher.Query.Phrase;
+import org.apache.nutch.util.NutchConf;
 
 /** Translate query fields to search the same-named field, as indexed by an
  * IndexingFilter.  Best for tokenized fields. */
 public abstract class FieldQueryFilter implements QueryFilter {
   private String field;
   private float boost = 1.0f;
+private NutchConf nutchConf;
+private CommonGrams commonGrams;
 
   /** Construct for the named field.*/
   protected FieldQueryFilter(String field) {
@@ -57,12 +60,12 @@
 
       // optimize phrase clause
       if (c.isPhrase()) {
-        String[] opt = CommonGrams.optimizePhrase(c.getPhrase(), field);
+        String[] opt = this.commonGrams.optimizePhrase(c.getPhrase(), field);
         if (opt.length==1) {
           c = new Clause(new Query.Term(opt[0]),
-                         c.isRequired(), c.isProhibited());
+                         c.isRequired(), c.isProhibited(), getConf());
         } else {
-          c = new Clause(new Phrase(opt), c.isRequired(), c.isProhibited());
+          c = new Clause(new Phrase(opt), c.isRequired(), c.isProhibited(), getConf());
         }
       }
 
@@ -89,4 +92,23 @@
     // return the modified Lucene query
     return output;
   }
+  
+  /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        this.commonGrams = new CommonGrams(conf);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
Index: src/java/org/apache/nutch/searcher/IndexSearcher.java
===================================================================
--- src/java/org/apache/nutch/searcher/IndexSearcher.java	(revision 367309)
+++ src/java/org/apache/nutch/searcher/IndexSearcher.java	(working copy)
@@ -47,38 +47,41 @@
 
   private org.apache.lucene.search.Searcher luceneSearcher;
   private org.apache.lucene.index.IndexReader reader;
+  private LuceneQueryOptimizer optimizer;
+  private NutchFileSystem fs;
+  private NutchConf nutchConf;
+  private QueryFilters queryFilters;
 
-  private LuceneQueryOptimizer optimizer = new LuceneQueryOptimizer
-    (NutchConf.get().getInt("searcher.filter.cache.size", 16),
-     NutchConf.get().getFloat("searcher.filter.cache.threshold", 0.05f));
-
   /** Construct given a number of indexes. */
-  public IndexSearcher(File[] indexDirs) throws IOException {
+  public IndexSearcher(File[] indexDirs, NutchConf nutchConf) throws IOException {
     IndexReader[] readers = new IndexReader[indexDirs.length];
     for (int i = 0; i < indexDirs.length; i++) {
       readers[i] = IndexReader.open(getDirectory(indexDirs[i]));
     }
-    init(new MultiReader(readers));
+    init(new MultiReader(readers), nutchConf);
   }
 
   /** Construct given a single merged index. */
-  public IndexSearcher(File index)
+  public IndexSearcher(File index,  NutchConf nutchConf)
     throws IOException {
-    init(IndexReader.open(getDirectory(index)));
+    init(IndexReader.open(getDirectory(index)),  nutchConf);
   }
 
-  private void init(IndexReader reader) throws IOException {
+  private void init(IndexReader reader, NutchConf nutchConf) throws IOException {
     this.reader = reader;
     this.luceneSearcher = new org.apache.lucene.search.IndexSearcher(reader);
     this.luceneSearcher.setSimilarity(new NutchSimilarity());
+    this.fs = NutchFileSystem.get(nutchConf);
+    this.nutchConf = nutchConf;
+    this.optimizer = new LuceneQueryOptimizer(nutchConf);
+    this.queryFilters = new QueryFilters(nutchConf);
   }
 
   private Directory getDirectory(File file) throws IOException {
-    NutchFileSystem fs = NutchFileSystem.get();
-    if ("local".equals(fs.getName())) {
+    if ("local".equals(this.fs.getName())) {
       return FSDirectory.getDirectory(file, false);
     } else {
-      return new NdfsDirectory(fs, file, false);
+      return new NdfsDirectory(this.fs, file, false, this.nutchConf);
     }
   }
 
@@ -88,7 +91,7 @@
     throws IOException {
 
     org.apache.lucene.search.BooleanQuery luceneQuery =
-      QueryFilters.filter(query);
+      this.queryFilters.filter(query);
     
     return translateHits
       (optimizer.optimize(luceneQuery, luceneSearcher, numHits,
@@ -97,7 +100,7 @@
   }
 
   public String getExplanation(Query query, Hit hit) throws IOException {
-    return luceneSearcher.explain(QueryFilters.filter(query),
+    return luceneSearcher.explain(this.queryFilters.filter(query),
                                   hit.getIndexDocNo()).toHtml();
   }
 
Index: src/java/org/apache/nutch/searcher/LinkDbInlinks.java
===================================================================
--- src/java/org/apache/nutch/searcher/LinkDbInlinks.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/LinkDbInlinks.java	(working copy)
@@ -11,6 +11,7 @@
 import org.apache.nutch.crawl.LinkDbReader;
 import org.apache.nutch.fs.NutchFileSystem;
 import org.apache.nutch.io.UTF8;
+import org.apache.nutch.util.NutchConf;
 
 import java.io.File;
 
@@ -18,8 +19,8 @@
   
   private LinkDbReader linkdb = null;
   
-  public LinkDbInlinks(NutchFileSystem fs, File dir) {
-    linkdb = new LinkDbReader(fs, dir);
+  public LinkDbInlinks(NutchFileSystem fs, File dir, NutchConf nutchConf) {
+    linkdb = new LinkDbReader(fs, dir, nutchConf);
   }
 
   public String[] getAnchors(HitDetails details) throws IOException {
Index: src/java/org/apache/nutch/searcher/OpenSearchServlet.java
===================================================================
--- src/java/org/apache/nutch/searcher/OpenSearchServlet.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/OpenSearchServlet.java	(working copy)
@@ -31,6 +31,8 @@
 import javax.servlet.http.HttpServletResponse;
 
 import javax.xml.parsers.*;
+
+import org.apache.nutch.util.NutchConf;
 import org.w3c.dom.*;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.Transformer;
@@ -55,10 +57,12 @@
   }
 
   private NutchBean bean;
+  private NutchConf nutchConf;
 
-  public void init(ServletConfig config) throws ServletException {
+  public void init(ServletConfig config, NutchConf nutchConf) throws ServletException {
     try {
-      bean = NutchBean.get(config.getServletContext());
+      bean = NutchBean.get(config.getServletContext(), nutchConf);
+      this.nutchConf = nutchConf;
     } catch (IOException e) {
       throw new ServletException(e);
     }
@@ -114,7 +118,7 @@
         (sort == null ? "" : "&sort=" + sort + (reverse? "&reverse=true": "") +
         (dedupField == null ? "" : "&dedupField=" + dedupField));
 
-    Query query = Query.parse(queryString);
+    Query query = Query.parse(queryString, this.nutchConf);
     NutchBean.LOG.info("query: " + queryString);
 
     // execute the query
Index: src/java/org/apache/nutch/searcher/QueryFilters.java
===================================================================
--- src/java/org/apache/nutch/searcher/QueryFilters.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/QueryFilters.java	(working copy)
@@ -19,6 +19,8 @@
 import org.apache.nutch.plugin.*;
 import org.apache.nutch.searcher.Query.Clause;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
+
 import java.util.logging.Logger;
 import java.util.*;
 
@@ -35,36 +37,10 @@
   private static final Logger LOG =
     LogFormatter.getLogger("org.apache.nutch.searcher.QueryFilters");
 
-  private static final QueryFilter[] CACHE;
-  private static final HashSet FIELD_NAMES = new HashSet();
-  private static final HashSet RAW_FIELD_NAMES = new HashSet();
+  private QueryFilter[] CACHE;
+  private HashSet FIELD_NAMES = new HashSet();
+  private HashSet RAW_FIELD_NAMES = new HashSet();
 
-  static {
-    try {
-      ExtensionPoint point = PluginRepository.getInstance()
-        .getExtensionPoint(QueryFilter.X_POINT_ID);
-      if (point == null)
-        throw new RuntimeException(QueryFilter.X_POINT_ID+" not found.");
-      Extension[] extensions = point.getExtensions();
-      CACHE = new QueryFilter[extensions.length];
-      for (int i = 0; i < extensions.length; i++) {
-        Extension extension = extensions[i];
-        ArrayList fieldNames = parseFieldNames(extension, "fields");
-        ArrayList rawFieldNames = parseFieldNames(extension, "raw-fields");
-        if (fieldNames.size() == 0 && rawFieldNames.size() == 0) {
-          LOG.warning("QueryFilter: "+extension.getId()+" names no fields.");
-          continue;
-        }
-        CACHE[i] = (QueryFilter)extension.getExtensionInstance();
-        FIELD_NAMES.addAll(fieldNames);
-        FIELD_NAMES.addAll(rawFieldNames);
-        RAW_FIELD_NAMES.addAll(rawFieldNames);
-      }
-    } catch (PluginRuntimeException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   private static ArrayList parseFieldNames(Extension extension,
                                            String attribute) {
     String fields = extension.getAttribute(attribute);
@@ -72,10 +48,34 @@
     return Collections.list(new StringTokenizer(fields, " ,\t\n\r"));
   }
 
-  private  QueryFilters() {}                  // no public ctor
+  public QueryFilters(NutchConf nutchConf) {
+      try {
+          ExtensionPoint point =nutchConf.getPluginRepository()
+            .getExtensionPoint(QueryFilter.X_POINT_ID);
+          if (point == null)
+            throw new RuntimeException(QueryFilter.X_POINT_ID+" not found.");
+          Extension[] extensions = point.getExtensions();
+          CACHE = new QueryFilter[extensions.length];
+          for (int i = 0; i < extensions.length; i++) {
+            Extension extension = extensions[i];
+            ArrayList fieldNames = parseFieldNames(extension, "fields");
+            ArrayList rawFieldNames = parseFieldNames(extension, "raw-fields");
+            if (fieldNames.size() == 0 && rawFieldNames.size() == 0) {
+              LOG.warning("QueryFilter: "+extension.getId()+" names no fields.");
+              continue;
+            }
+            CACHE[i] = (QueryFilter)extension.getExtensionInstance();
+            FIELD_NAMES.addAll(fieldNames);
+            FIELD_NAMES.addAll(rawFieldNames);
+            RAW_FIELD_NAMES.addAll(rawFieldNames);
+          }
+        } catch (PluginRuntimeException e) {
+          throw new RuntimeException(e);
+        }
+  }              
 
   /** Run all defined filters. */
-  public static BooleanQuery filter(Query input) throws QueryException {
+  public BooleanQuery filter(Query input) throws QueryException {
     // first check that all field names are claimed by some plugin
     Clause[] clauses = input.getClauses();
     for (int i = 0; i < clauses.length; i++) {
@@ -92,10 +92,10 @@
     return output;
   }
 
-  public static boolean isField(String name) {
+  public boolean isField(String name) {
     return FIELD_NAMES.contains(name);
   }
-  public static boolean isRawField(String name) {
+  public boolean isRawField(String name) {
     return RAW_FIELD_NAMES.contains(name);
   }
 }
Index: src/java/org/apache/nutch/searcher/Summarizer.java
===================================================================
--- src/java/org/apache/nutch/searcher/Summarizer.java	(revision 359225)
+++ src/java/org/apache/nutch/searcher/Summarizer.java	(working copy)
@@ -30,14 +30,7 @@
 /** Implements hit summarization. */
 public class Summarizer {
 
-  /** The number of context terms to display preceding and following matches.*/
-  private static final int SUM_CONTEXT =
-    NutchConf.get().getInt("searcher.summary.context", 5);
-
-  /** The total number of terms to display in a summary.*/
-  private static final int SUM_LENGTH = 
-    NutchConf.get().getInt("searcher.summary.length", 20);
-
+   
   /** Converts text to tokens. */
   private static final Analyzer ANALYZER = new NutchDocumentAnalyzer();
 
@@ -55,6 +48,7 @@
       public Excerpt() {
       }
 
+      
       /**
        */
       public void addToken(String token) {
@@ -99,7 +93,7 @@
   }
 
   /** Returns a summary for the given pre-tokenized text. */
-  public Summary getSummary(String text, Query query) throws IOException {
+  public Summary getSummary(String text, Query query, int sumContext, int sumLength) throws IOException {
 
     // Simplistic implementation.  Finds the first fragments in the document
     // containing any query terms.
@@ -161,8 +155,8 @@
         // Start searching at a point SUM_CONTEXT terms back,
         // and move SUM_CONTEXT terms into the future.
         //
-        int startToken = (i > SUM_CONTEXT) ? i-SUM_CONTEXT : 0;
-        int endToken = Math.min(i+SUM_CONTEXT, tokens.length);
+        int startToken = (i > sumContext) ? i-sumContext: 0;
+        int endToken = Math.min(i+sumContext, tokens.length);
         int offset = tokens[startToken].startOffset();
         int j = startToken;
 
@@ -181,7 +175,7 @@
         // the document and we haven't hit the max-number-of-items
         // -in-a-summary.
         //
-        while ((j < endToken) && (j - startToken < SUM_LENGTH)) {
+        while ((j < endToken) && (j - startToken < sumLength)) {
           //
           // Now grab the hit-element, if present
           //
@@ -191,7 +185,7 @@
             excerpt.add(new Fragment(text.substring(offset, t.startOffset())));
             excerpt.add(new Highlight(text.substring(t.startOffset(),t.endOffset())));
             offset = t.endOffset();
-            endToken = Math.min(j+SUM_CONTEXT, tokens.length);
+            endToken = Math.min(j+sumContext, tokens.length);
           }
 
           j++;
@@ -226,7 +220,7 @@
         // Start SUM_CONTEXT places away.  The next
         // search for relevant excerpts begins at i-SUM_CONTEXT
         //
-        i = j+SUM_CONTEXT;
+        i = j+sumContext;
       }
     }
 
@@ -236,7 +230,7 @@
     //
     if (excerptSet.size() == 0) {
         Excerpt excerpt = new Excerpt();
-        int excerptLen = Math.min(SUM_LENGTH, tokens.length);
+        int excerptLen = Math.min(sumLength, tokens.length);
         lastExcerptPos = excerptLen;
 
         excerpt.add(new Fragment(text.substring(tokens[0].startOffset(), tokens[excerptLen-1].startOffset())));
@@ -250,7 +244,7 @@
     //
     double tokenCount = 0;
     Summary s = new Summary();
-    while (tokenCount <= SUM_LENGTH && excerptSet.size() > 0) {
+    while (tokenCount <= sumLength && excerptSet.size() > 0) {
         Excerpt excerpt = (Excerpt) excerptSet.last();
         excerptSet.remove(excerpt);
 
@@ -258,7 +252,7 @@
         for (Enumeration e = excerpt.elements(); e.hasMoreElements(); ) {
             Fragment f = (Fragment) e.nextElement();
             // Don't add fragments if it takes us over the max-limit
-            if (tokenCount + tokenFraction <= SUM_LENGTH) {
+            if (tokenCount + tokenFraction <= sumLength) {
                 s.add(f);
             }
             tokenCount += tokenFraction;
@@ -318,8 +312,11 @@
             in.close();
         }
 
+        NutchConf nutchConf = new NutchConf();
+        int sumContext = nutchConf.getInt("searcher.summary.context",5);
+        int sumLength = nutchConf.getInt("searcher.summary.length",20);
         // Convert the query string into a proper Query
-        Query query = Query.parse(queryBuf.toString());
-        System.out.println("Summary: '" + s.getSummary(body.toString(), query) + "'");
+        Query query = Query.parse(queryBuf.toString(), nutchConf);
+        System.out.println("Summary: '" + s.getSummary(body.toString(), query, sumContext, sumLength) + "'");
     }
 }
Index: src/java/org/apache/nutch/plugin/PluginManifestParser.java
===================================================================
--- src/java/org/apache/nutch/plugin/PluginManifestParser.java	(revision 359225)
+++ src/java/org/apache/nutch/plugin/PluginManifestParser.java	(working copy)
@@ -52,38 +52,15 @@
     private static final boolean WINDOWS = System.getProperty("os.name")
             .startsWith("Windows");
 
-    /**
-     * Filters a list of plugins.
-     * The list of plugins is filtered regarding the configuration
-     * properties <code>plugin.excludes</code> and <code>plugin.includes</code>.
-     */
-    public static Map filter(Map plugins) {
-      Map map = new HashMap();
-      Pattern excludes = Pattern.compile(NutchConf.get().get(
-                                         "plugin.excludes", ""));
-      Pattern includes = Pattern.compile(NutchConf.get().get(
-                                         "plugin.includes", ""));
-      if (plugins == null) { return map; }
+    private NutchConf nutchConf;
 
-      Iterator iter = plugins.values().iterator();
-      while (iter.hasNext()) {
-        PluginDescriptor plugin = (PluginDescriptor) iter.next();
-        if (plugin == null) { continue; }
-        String id = plugin.getPluginId();
-        if (id == null) { continue; }
-        
-        if (!includes.matcher(id).matches()) {
-          LOG.fine("not including: " + id);
-          continue;
-        }
-        if (excludes.matcher(id).matches()) {
-          LOG.fine("excluding: " + id);
-          continue;
-        }
-        map.put(plugin.getPluginId(), plugin);
-      }
-      return map;
+    private PluginRepository pluginRepository;
+
+    public PluginManifestParser(NutchConf nutchConf, PluginRepository pluginRepository){
+        this.nutchConf = nutchConf;
+        this.pluginRepository = pluginRepository;
     }
+   
     
     /**
      * Returns a list with plugin descriptors.
@@ -91,9 +68,8 @@
      * @return ArrayList
      *  
      */
-    public static Map parsePluginFolder() {
+    public Map parsePluginFolder(String[] pluginFolders) {
         Map map = new HashMap();
-        String[] pluginFolders = NutchConf.get().getStrings("plugin.folders");
 
         if (pluginFolders == null) {
             throw new IllegalArgumentException("plugin.folders is not defined");
@@ -136,7 +112,7 @@
      * Return the named plugin folder. If the name is absolute then it is
      * returned. Otherwise, for relative names, the classpath is scanned.
      */
-    static File getPluginFolder(String name) {
+  public  File getPluginFolder(String name) {
         File directory = new File(name);
         if (!directory.isAbsolute()) {
             URL url = PluginManifestParser.class.getClassLoader().getResource(
@@ -168,7 +144,7 @@
      * @throws SAXException
      * @throws MalformedURLException
      */
-    private static PluginDescriptor parseManifestFile(String pManifestPath)
+    private PluginDescriptor parseManifestFile(String pManifestPath)
             throws MalformedURLException, SAXException, IOException,
             ParserConfigurationException {
         Document document = parseXML(new File(pManifestPath).toURL());
@@ -184,7 +160,7 @@
      * @throws ParserConfigurationException
      * @throws DocumentException
      */
-    private static Document parseXML(URL url) throws SAXException, IOException,
+    private Document parseXML(URL url) throws SAXException, IOException,
             ParserConfigurationException {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         DocumentBuilder builder = factory.newDocumentBuilder();
@@ -195,7 +171,7 @@
      * @param pDocument
      * @throws MalformedURLException
      */
-    private static PluginDescriptor parsePlugin(Document pDocument, String pPath)
+    private PluginDescriptor parsePlugin(Document pDocument, String pPath)
             throws MalformedURLException {
         Element rootElement = pDocument.getDocumentElement();
         String id = rootElement.getAttribute("id");
@@ -207,7 +183,7 @@
             pluginClazz = rootElement.getAttribute("class");
         }
         PluginDescriptor pluginDescriptor = new PluginDescriptor(id, version,
-                name, providerName, pluginClazz, pPath);
+                name, providerName, pluginClazz, pPath, this.nutchConf);
         LOG.fine("plugin: id="+id+" name="+name+" version="+version
                  +" provider="+providerName+"class="+pluginClazz);
         parseExtension(rootElement, pluginDescriptor);
@@ -222,7 +198,7 @@
      * @param pDescriptor
      * @throws MalformedURLException
      */
-    private static void parseRequires(Element pRootElement,
+    private void parseRequires(Element pRootElement,
                                       PluginDescriptor pDescriptor)
         throws MalformedURLException {
       
@@ -247,7 +223,7 @@
      * @param pDescriptor
      * @throws MalformedURLException
      */
-    private static void parseLibraries(Element pRootElement,
+    private void parseLibraries(Element pRootElement,
             PluginDescriptor pDescriptor) throws MalformedURLException {
         NodeList nodelist = pRootElement.getElementsByTagName("runtime");
         if (nodelist.getLength() > 0) {
@@ -272,7 +248,7 @@
      * @param rootElement
      * @param pluginDescriptor
      */
-    private static void parseExtensionPoints(Element pRootElement,
+    private void parseExtensionPoints(Element pRootElement,
             PluginDescriptor pPluginDescriptor) {
         NodeList list = pRootElement.getElementsByTagName("extension-point");
         if (list != null) {
@@ -293,7 +269,7 @@
      * @param rootElement
      * @param pluginDescriptor
      */
-    private static void parseExtension(Element pRootElement,
+    private void parseExtension(Element pRootElement,
             PluginDescriptor pPluginDescriptor) {
         NodeList extensions = pRootElement.getElementsByTagName("extension");
         if (extensions != null) {
@@ -316,7 +292,7 @@
                         LOG.fine("impl: point=" + pointId + " class="
                                 + extensionClass);
                         Extension extension = new Extension(pPluginDescriptor,
-                                pointId, id, extensionClass);
+                                pointId, id, extensionClass, this.nutchConf, this.pluginRepository);
                         NamedNodeMap list = oneImplementation.getAttributes();
                         for (int k = 0; k < list.getLength(); k++) {
                             Node attribute = list.item(k);
Index: src/java/org/apache/nutch/plugin/Extension.java
===================================================================
--- src/java/org/apache/nutch/plugin/Extension.java	(revision 359225)
+++ src/java/org/apache/nutch/plugin/Extension.java	(working copy)
@@ -16,6 +16,9 @@
  */
 package org.apache.nutch.plugin;
 import java.util.HashMap;
+
+import org.apache.nutch.util.NutchConf;
+import org.apache.nutch.util.NutchConfigurable;
 /**
  * An <code>Extension</code> is a kind of listener descriptor that will be
  * installed on a concrete <code>ExtensionPoint</code> that acts as kind of
@@ -29,6 +32,8 @@
   private String fTargetPoint;
   private String fClazz;
   private HashMap fAttributes;
+  private NutchConf nutchConf;
+ private PluginRepository pluginRepository;
   /**
    * @param pDescriptor
    *            a plugin descriptor
@@ -38,12 +43,14 @@
    *            an unique id of the plugin
    */
   public Extension(PluginDescriptor pDescriptor, String pExtensionPoint,
-                   String pId, String pExtensionClass) {
+                   String pId, String pExtensionClass, NutchConf nutchConf, PluginRepository pluginRepository) {
     fAttributes = new HashMap();
     setDescriptor(pDescriptor);
     setExtensionPoint(pExtensionPoint);
     setId(pId);
     setClazz(pExtensionClass);
+    this.nutchConf = nutchConf;
+    this.pluginRepository = pluginRepository;
   }
   /**
    * @param point
@@ -140,8 +147,11 @@
         Class extensionClazz = loader.loadClass(getClazz());
         // lazy loading of Plugin in case there is no instance of the plugin
         // already.
-        PluginRepository.getInstance().getPluginInstance(getDescriptor());
+        this.pluginRepository.getPluginInstance(getDescriptor());
         Object object = extensionClazz.newInstance();
+        if(object instanceof NutchConfigurable){
+            ((NutchConfigurable)object).setConf(this.nutchConf);
+        }
         return object;
       } catch (ClassNotFoundException e) {
         throw new PluginRuntimeException(e);
Index: src/java/org/apache/nutch/plugin/PluginDescriptor.java
===================================================================
--- src/java/org/apache/nutch/plugin/PluginDescriptor.java	(revision 359225)
+++ src/java/org/apache/nutch/plugin/PluginDescriptor.java	(working copy)
@@ -26,6 +26,7 @@
 import java.util.ResourceBundle;
 import java.util.logging.Logger;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 /**
  * The <code>PluginDescriptor</code> provide access to all meta information of
  * a nutch-plugin, as well to the internationalizable resources and the plugin
@@ -52,6 +53,8 @@
   private PluginClassLoader fClassLoader;
   public static final Logger LOG = LogFormatter
     .getLogger(PluginDescriptor.class.getName());
+  private NutchConf fNutchConf;
+  
   /**
    * Constructor
    * 
@@ -63,7 +66,7 @@
    * @param pPath
    */
   public PluginDescriptor(String pId, String pVersion, String pName,
-                          String pProviderName, String pPluginclazz, String pPath) {
+                          String pProviderName, String pPluginclazz, String pPath, NutchConf nutchConf) {
     setPath(pPath);
     setPluginId(pId);
     setVersion(pVersion);
@@ -73,6 +76,7 @@
     if (pPluginclazz != null)
       setPluginClass(pPluginclazz);
 
+    this.fNutchConf = nutchConf;
   }
   /**
    * @param pPath
@@ -285,8 +289,7 @@
     String[] pPluginIds = pDescriptor.getDependencies();
     for (int i = 0; i < pPluginIds.length; i++) {
       String id = pPluginIds[i];
-      PluginDescriptor descriptor = PluginRepository.getInstance()
-        .getPluginDescriptor(id);
+      PluginDescriptor descriptor = this.fNutchConf.getPluginRepository().getPluginDescriptor(id);
       URL[] libs = descriptor.getExportedLibUrls();
       for (int j = 0; j < libs.length; j++) {
         URL url = libs[j];
Index: src/java/org/apache/nutch/plugin/PluginRepository.java
===================================================================
--- src/java/org/apache/nutch/plugin/PluginRepository.java	(revision 359225)
+++ src/java/org/apache/nutch/plugin/PluginRepository.java	(working copy)
@@ -25,6 +25,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
+import java.util.regex.Pattern;
 
 // Nutch imports
 import org.apache.nutch.util.LogFormatter;
@@ -45,8 +46,7 @@
  */
 public class PluginRepository {
   
-    private final static boolean AUTO =
-            NutchConf.get().getBoolean("plugin.auto-activation", true);
+    private boolean auto;
     
     private static PluginRepository fInstance;
 
@@ -64,16 +64,28 @@
      * @throws PluginRuntimeException
      * @see java.lang.Object#Object()
      */
-    private PluginRepository() throws PluginRuntimeException{
+    public PluginRepository(NutchConf nutchConf) throws RuntimeException{
       fActivatedPlugins = new HashMap();
       fExtensionPoints = new HashMap();
-      Map allPlugins = PluginManifestParser.parsePluginFolder();
-      Map filteredPlugins = PluginManifestParser.filter(allPlugins);
+      this.auto = nutchConf.getBoolean("plugin.auto-activation", true);
+      String[] pluginFolders = nutchConf.getStrings("plugin.folders");
+      PluginManifestParser manifestParser =  new PluginManifestParser(nutchConf, this);
+      Map allPlugins =manifestParser.parsePluginFolder(pluginFolders);
+      Pattern excludes = Pattern.compile(nutchConf.get(
+              "plugin.excludes", ""));
+      Pattern includes = Pattern.compile(nutchConf.get(
+              "plugin.includes", ""));
+      Map filteredPlugins = filter(excludes, includes, allPlugins);
       fRegisteredPlugins = getDependencyCheckedPlugins(
                               filteredPlugins,
-                              AUTO ? allPlugins : filteredPlugins);
+                              this.auto ? allPlugins : filteredPlugins);
       installExtensionPoints(fRegisteredPlugins);
-      installExtensions(fRegisteredPlugins);
+      try {
+        installExtensions(fRegisteredPlugins);
+    } catch (PluginRuntimeException e) {
+       LOG.severe(e.toString());
+       throw new RuntimeException(e.getMessage());
+    }
       displayStatus();
     }
 
@@ -205,21 +217,6 @@
     }
 
     /**
-     * Returns the singelton instance of the <code>PluginRepository</code>
-     */
-    public static synchronized PluginRepository getInstance() {
-        if (fInstance != null)
-            return fInstance;
-        try {
-            fInstance = new PluginRepository();
-        } catch (Exception e) {
-            LOG.severe(e.toString());
-            throw new RuntimeException(e);
-        }
-        return fInstance;
-    }
-
-    /**
      * Returns all registed plugin descriptors.
      * 
      * @return PluginDescriptor[]
@@ -249,9 +246,10 @@
      * Returns a extension point indentified by a extension point id.
      * 
      * @param pXpId
+     * @return a extentsion point
      */
     public ExtensionPoint getExtensionPoint(String pXpId) {
-        return (ExtensionPoint) fExtensionPoints.get(pXpId);
+        return (ExtensionPoint) this.fExtensionPoints.get(pXpId);
     }
 
     /**
@@ -325,7 +323,7 @@
     
     private void displayStatus() {
 
-      LOG.info("Plugin Auto-activation mode: [" + AUTO + "]");
+      LOG.info("Plugin Auto-activation mode: [" + this.auto + "]");
 
       LOG.info("Registered Plugins:");
       if ((fRegisteredPlugins == null) || (fRegisteredPlugins.size() == 0)) {
@@ -348,4 +346,32 @@
         }
       }
     }
+    /**
+     * Filters a list of plugins.
+     * The list of plugins is filtered regarding the configuration
+     * properties <code>plugin.excludes</code> and <code>plugin.includes</code>.
+     */
+    private Map filter(Pattern excludes, Pattern includes, Map plugins) {
+      Map map = new HashMap();
+      if (plugins == null) { return map; }
+
+      Iterator iter = plugins.values().iterator();
+      while (iter.hasNext()) {
+        PluginDescriptor plugin = (PluginDescriptor) iter.next();
+        if (plugin == null) { continue; }
+        String id = plugin.getPluginId();
+        if (id == null) { continue; }
+        
+        if (!includes.matcher(id).matches()) {
+          LOG.fine("not including: " + id);
+          continue;
+        }
+        if (excludes.matcher(id).matches()) {
+          LOG.fine("excluding: " + id);
+          continue;
+        }
+        map.put(plugin.getPluginId(), plugin);
+      }
+      return map;
+    }
 }
Index: src/java/org/apache/nutch/indexer/NdfsDirectory.java
===================================================================
--- src/java/org/apache/nutch/indexer/NdfsDirectory.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/NdfsDirectory.java	(working copy)
@@ -19,19 +19,22 @@
 import java.io.*;
 import org.apache.lucene.store.*;
 import org.apache.nutch.fs.*;
+import org.apache.nutch.util.NutchConf;
 
 /** Reads a Lucene index stored in NDFS. */
 public class NdfsDirectory extends Directory {
 
   private NutchFileSystem fs;
   private File directory;
+  private int ioFileBufferSize;
 
-  public NdfsDirectory(NutchFileSystem fs, File directory, boolean create)
+  public NdfsDirectory(NutchFileSystem fs, File directory, boolean create, NutchConf nutchConf)
     throws IOException {
 
     this.fs = fs;
     this.directory = directory;
-
+    this.ioFileBufferSize = nutchConf.getInt("io.file.buffer.size", 4096);
+    
     if (create) {
       create();
     }
@@ -103,12 +106,12 @@
     if (fs.exists(file) && !fs.delete(file))      // delete existing, if any
       throw new IOException("Cannot overwrite: " + file);
 
-    return new NdfsIndexOutput(file);
+    return new NdfsIndexOutput(file, this.ioFileBufferSize);
   }
 
 
   public IndexInput openInput(String name) throws IOException {
-    return new NdfsIndexInput(new File(directory, name));
+    return new NdfsIndexInput(new File(directory, name), this.ioFileBufferSize);
   }
 
   public Lock makeLock(final String name) {
@@ -152,7 +155,7 @@
     private class Descriptor {
       public NFSDataInputStream in;
       public long position;                       // cache of in.getPos()
-      public Descriptor(File file) throws IOException {
+      public Descriptor(File file, int ioFileBufferSize) throws IOException {
         this.in = fs.open(file);
       }
     }
@@ -161,8 +164,8 @@
     private final long length;
     private boolean isClone;
 
-    public NdfsIndexInput(File path) throws IOException {
-      descriptor = new Descriptor(path);
+    public NdfsIndexInput(File path, int ioFileBufferSize) throws IOException {
+      descriptor = new Descriptor(path,ioFileBufferSize);
       length = fs.getLength(path);
     }
 
@@ -211,7 +214,7 @@
   private class NdfsIndexOutput extends BufferedIndexOutput {
     private NFSDataOutputStream out;
 
-    public NdfsIndexOutput(File path) throws IOException {
+    public NdfsIndexOutput(File path, int ioFileBufferSize) throws IOException {
       out = fs.create(path);
     }
 
Index: src/java/org/apache/nutch/indexer/DeleteDuplicates.java
===================================================================
--- src/java/org/apache/nutch/indexer/DeleteDuplicates.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/DeleteDuplicates.java	(working copy)
@@ -148,7 +148,7 @@
       return new RecordReader() {
 
           private IndexReader indexReader =
-            IndexReader.open(new NdfsDirectory(fs, split.getFile(), false));
+            IndexReader.open(new NdfsDirectory(fs, split.getFile(), false, job));
 
           { indexReader.undeleteAll(); }
 
@@ -228,6 +228,7 @@
   }
     
   private NutchFileSystem fs;
+  private int ioFileBufferSize;
 
   public DeleteDuplicates() { super(null); }
 
@@ -236,6 +237,7 @@
   public void configure(JobConf job) {
     try {
       fs = NutchFileSystem.get(job);
+      this.ioFileBufferSize = job.getInt("io.file.buffer.size", 4096);
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
@@ -254,7 +256,7 @@
                      OutputCollector output, Reporter reporter)
     throws IOException {
     File index = new File(key.toString());
-    IndexReader reader = IndexReader.open(new NdfsDirectory(fs, index, false));
+    IndexReader reader = IndexReader.open(new NdfsDirectory(fs, index, false, getConf()));
     try {
       while (values.hasNext()) {
         reader.delete(((IntWritable)values.next()).get());
@@ -316,6 +318,7 @@
     job.setInputKeyClass(HashScore.class);
     job.setInputValueClass(IndexDoc.class);
 
+    job.setInt("io.file.buffer.size", 4096);
     job.setMapperClass(DeleteDuplicates.class);
     job.setReducerClass(DeleteDuplicates.class);
 
@@ -331,7 +334,7 @@
   }
 
   public static void main(String[] args) throws Exception {
-    DeleteDuplicates dedup = new DeleteDuplicates(NutchConf.get());
+    DeleteDuplicates dedup = new DeleteDuplicates(new NutchConf());
     
     if (args.length < 1) {
       System.err.println("Usage: <indexes> ...");
Index: src/java/org/apache/nutch/indexer/IndexSorter.java
===================================================================
--- src/java/org/apache/nutch/indexer/IndexSorter.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/IndexSorter.java	(working copy)
@@ -225,14 +225,14 @@
     this.directory = directory;
   }
 
-  public void sort() throws IOException {
+  public void sort(int termIndexInterval) throws IOException {
     IndexReader reader = IndexReader.open(new File(directory, "index"));
 
     SortingReader sorter = new SortingReader(reader, oldToNew(reader));
     IndexWriter writer = new IndexWriter(new File(directory, "index-sorted"),
                                          null, true);
     writer.setTermIndexInterval
-      (NutchConf.get().getInt("indexer.termIndexInterval", 128));
+      (termIndexInterval);
     writer.setUseCompoundFile(false);
     writer.addIndexes(new IndexReader[] { sorter });
     writer.close();
@@ -283,9 +283,10 @@
     IndexSorter sorter = new IndexSorter(directory);
 
     Date start = new Date();
+    NutchConf nutchConf = new NutchConf();
+    int termIndexInterval = nutchConf.getInt("indexer.termIndexInterval", 128);
+    sorter.sort(termIndexInterval);
 
-    sorter.sort();
-
     Date end = new Date();
 
     System.out.print(end.getTime() - start.getTime());
Index: src/java/org/apache/nutch/indexer/IndexMerger.java
===================================================================
--- src/java/org/apache/nutch/indexer/IndexMerger.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/IndexMerger.java	(working copy)
@@ -41,28 +41,22 @@
 
   public static final String DONE_NAME = "merge.done";
 
-  private int MERGE_FACTOR = NutchConf.get().getInt("indexer.mergeFactor",
-      IndexWriter.DEFAULT_MERGE_FACTOR);
-  private int MIN_MERGE_DOCS = NutchConf.get().getInt("indexer.minMergeDocs",
-      IndexWriter.DEFAULT_MIN_MERGE_DOCS);
-  private int MAX_MERGE_DOCS = NutchConf.get().getInt("indexer.maxMergeDocs",
-      IndexWriter.DEFAULT_MAX_MERGE_DOCS);
-  private int TERM_INDEX_INTERVAL =
-    NutchConf.get().getInt("indexer.termIndexInterval",
-                           IndexWriter.DEFAULT_TERM_INDEX_INTERVAL);
   private NutchFileSystem nfs;
   private File outputIndex;
   private File localWorkingDir;
   private File[] indexes;
 
+private NutchConf nutchConf;
+
   /**
    * Merge all of the indexes given
    */
-  public IndexMerger(NutchFileSystem nfs, File[] indexes, File outputIndex, File localWorkingDir) throws IOException {
+  public IndexMerger(NutchFileSystem nfs, File[] indexes, File outputIndex, File localWorkingDir, NutchConf nutchConf) throws IOException {
       this.nfs = nfs;
       this.indexes = indexes;
       this.outputIndex = outputIndex;
       this.localWorkingDir = localWorkingDir;
+      this.nutchConf = nutchConf;
   }
 
   /**
@@ -81,7 +75,7 @@
     Directory[] dirs = new Directory[indexes.length];
     for (int i = 0; i < indexes.length; i++) {
       LOG.info("Adding " + indexes[i]);
-      dirs[i] = new NdfsDirectory(nfs, indexes[i], false);
+      dirs[i] = new NdfsDirectory(nfs, indexes[i], false, this.nutchConf);
     }
 
     //
@@ -90,10 +84,10 @@
     // Merge indices
     //
     IndexWriter writer = new IndexWriter(localOutput, null, true);
-    writer.mergeFactor = MERGE_FACTOR;
-    writer.minMergeDocs = MIN_MERGE_DOCS;
-    writer.maxMergeDocs = MAX_MERGE_DOCS;
-    writer.setTermIndexInterval(TERM_INDEX_INTERVAL);
+    writer.mergeFactor = nutchConf.getInt("indexer.mergeFactor", IndexWriter.DEFAULT_MERGE_FACTOR);
+    writer.minMergeDocs = nutchConf.getInt("indexer.minMergeDocs", IndexWriter.DEFAULT_MIN_MERGE_DOCS);
+    writer.maxMergeDocs = nutchConf.getInt("indexer.maxMergeDocs", IndexWriter.DEFAULT_MAX_MERGE_DOCS);
+    writer.setTermIndexInterval(nutchConf.getInt("indexer.termIndexInterval", IndexWriter.DEFAULT_TERM_INDEX_INTERVAL));
     writer.infoStream = LogFormatter.getLogStream(LOG, Level.FINE);
     writer.setUseCompoundFile(false);
     writer.setSimilarity(new NutchSimilarity());
@@ -121,7 +115,8 @@
     //
     // Parse args, read all index directories to be processed
     //
-    NutchFileSystem nfs = NutchFileSystem.get();
+    NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = NutchFileSystem.get(nutchConf);
     File workDir = new File(new File("").getCanonicalPath());
     List indexDirs = new ArrayList();
 
@@ -146,12 +141,12 @@
     File[] indexFiles = (File[])indexDirs.toArray(new File[indexDirs.size()]);
 
     if (workDir.exists()) {
-      FileUtil.fullyDelete(workDir);
+      FileUtil.fullyDelete(workDir, nutchConf);
     }
     workDir.mkdirs();
-    IndexMerger merger = new IndexMerger(nfs,indexFiles,outputIndex,workDir);
+    IndexMerger merger = new IndexMerger(nfs,indexFiles,outputIndex,workDir, nutchConf);
     merger.merge();
     LOG.info("done merging");
-    FileUtil.fullyDelete(workDir);
+    FileUtil.fullyDelete(workDir, nutchConf);
   }
 }
Index: src/java/org/apache/nutch/indexer/IndexingFilter.java
===================================================================
--- src/java/org/apache/nutch/indexer/IndexingFilter.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/IndexingFilter.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.nutch.parse.Parse;
+import org.apache.nutch.util.NutchConfigurable;
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.crawl.Inlinks;
 import org.apache.nutch.io.UTF8;
@@ -26,7 +27,7 @@
  * fields.  All plugins found which implement this extension point are run
  * sequentially on the parse.
  */
-public interface IndexingFilter {
+public interface IndexingFilter extends NutchConfigurable {
   /** The name of the extension point. */
   final static String X_POINT_ID = IndexingFilter.class.getName();
 
Index: src/java/org/apache/nutch/indexer/Indexer.java
===================================================================
--- src/java/org/apache/nutch/indexer/Indexer.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/Indexer.java	(working copy)
@@ -55,7 +55,7 @@
 
       reporter.setStatus(split.toString());
       
-      return new SequenceFileRecordReader(fs, split) {
+      return new SequenceFileRecordReader(job, split) {
           public synchronized boolean next(Writable key, Writable value)
             throws IOException {
             ObjectWritable wrapper = (ObjectWritable)value;
@@ -217,7 +217,7 @@
 
     try {
       // run indexing filters
-      doc = IndexingFilters.filter(doc,new ParseImpl(parseText, parseData), (UTF8)key, fetchDatum, inlinks);
+      doc = new IndexingFilters(getConf()).filter(doc,new ParseImpl(parseText, parseData), (UTF8)key, fetchDatum, inlinks);
     } catch (IndexingException e) {
       LOG.warning("Error indexing "+key+": "+e);
       return;
@@ -261,7 +261,7 @@
   }
 
   public static void main(String[] args) throws Exception {
-    Indexer indexer = new Indexer(NutchConf.get());
+    Indexer indexer = new Indexer(new NutchConf());
     
     if (args.length < 4) {
       System.err.println("Usage: <index> <crawldb> <linkdb> <segment> ...");
Index: src/java/org/apache/nutch/indexer/IndexingFilters.java
===================================================================
--- src/java/org/apache/nutch/indexer/IndexingFilters.java	(revision 367309)
+++ src/java/org/apache/nutch/indexer/IndexingFilters.java	(working copy)
@@ -22,6 +22,7 @@
 
 import org.apache.nutch.plugin.*;
 import org.apache.nutch.parse.Parse;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.crawl.Inlinks;
 import org.apache.nutch.io.UTF8;
@@ -29,33 +30,32 @@
 /** Creates and caches {@link IndexingFilter} implementing plugins.*/
 public class IndexingFilters {
 
-  private static final IndexingFilter[] CACHE;
-  static {
-    try {
-      ExtensionPoint point = PluginRepository.getInstance()
-        .getExtensionPoint(IndexingFilter.X_POINT_ID);
-      if (point == null)
-        throw new RuntimeException(IndexingFilter.X_POINT_ID+" not found.");
-      Extension[] extensions = point.getExtensions();
-      HashMap filterMap = new HashMap();
-      for (int i = 0; i < extensions.length; i++) {
-        Extension extension = extensions[i];
-        IndexingFilter filter = (IndexingFilter)extension.getExtensionInstance();
-        System.out.println("-adding " + filter.getClass().getName());
-        if (!filterMap.containsKey(filter.getClass().getName())) {
-        	filterMap.put(filter.getClass().getName(), filter);
+  private IndexingFilter[] CACHE;
+
+  public  IndexingFilters(NutchConf nutchConf) {
+      try {
+          ExtensionPoint point = nutchConf.getPluginRepository()
+            .getExtensionPoint(IndexingFilter.X_POINT_ID);
+          if (point == null)
+            throw new RuntimeException(IndexingFilter.X_POINT_ID+" not found.");
+          Extension[] extensions = point.getExtensions();
+          HashMap filterMap = new HashMap();
+          for (int i = 0; i < extensions.length; i++) {
+            Extension extension = extensions[i];
+            IndexingFilter filter = (IndexingFilter)extension.getExtensionInstance();
+            System.out.println("-adding " + filter.getClass().getName());
+            if (!filterMap.containsKey(filter.getClass().getName())) {
+                filterMap.put(filter.getClass().getName(), filter);
+            }
+          }
+          CACHE = (IndexingFilter[])filterMap.values().toArray(new IndexingFilter[0]);
+        } catch (PluginRuntimeException e) {
+          throw new RuntimeException(e);
         }
-      }
-      CACHE = (IndexingFilter[])filterMap.values().toArray(new IndexingFilter[0]);
-    } catch (PluginRuntimeException e) {
-      throw new RuntimeException(e);
-    }
-  }
+  }                  
 
-  private  IndexingFilters() {}                  // no public ctor
-
   /** Run all defined filters. */
-  public static Document filter(Document doc, Parse parse, UTF8 url, CrawlDatum datum, Inlinks inlinks)
+  public Document filter(Document doc, Parse parse, UTF8 url, CrawlDatum datum, Inlinks inlinks)
     throws IndexingException {
 
     for (int i = 0; i < CACHE.length; i++) {
Index: src/java/org/apache/nutch/tools/PruneIndexTool.java
===================================================================
--- src/java/org/apache/nutch/tools/PruneIndexTool.java	(revision 367309)
+++ src/java/org/apache/nutch/tools/PruneIndexTool.java	(working copy)
@@ -459,8 +459,9 @@
     if (qPath != null) {
       is = new FileInputStream(qPath);
     } else {
-      qPath = NutchConf.get().get("prune.index.tool.queries");
-      is = NutchConf.get().getConfResourceAsInputStream(qPath);
+        NutchConf nutchConf = new NutchConf();
+        qPath = nutchConf.get("prune.index.tool.queries");
+        is = nutchConf.getConfResourceAsInputStream(qPath);
     }
     if (is == null) {
       LOG.severe("Can't load queries from " + qPath);
Index: src/java/org/apache/nutch/tools/DmozParser.java
===================================================================
--- src/java/org/apache/nutch/tools/DmozParser.java	(revision 367309)
+++ src/java/org/apache/nutch/tools/DmozParser.java	(working copy)
@@ -338,7 +338,8 @@
     Pattern topicPattern = null; 
     Vector topics = new Vector(); 
     
-    NutchFileSystem nfs = NutchFileSystem.get();
+    NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = NutchFileSystem.get(nutchConf);
     try {
       for (int i = 1; i < argv.length; i++) {
         if ("-includeAdultMaterial".equals(argv[i])) {
Index: src/java/org/apache/nutch/protocol/Protocol.java
===================================================================
--- src/java/org/apache/nutch/protocol/Protocol.java	(revision 367309)
+++ src/java/org/apache/nutch/protocol/Protocol.java	(working copy)
@@ -20,9 +20,10 @@
 
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.io.UTF8;
+import org.apache.nutch.util.NutchConfigurable;
 
 /** A retriever of url content.  Implemented by protocol extensions. */
-public interface Protocol {
+public interface Protocol extends NutchConfigurable{
   /** The name of the extension point. */
   public final static String X_POINT_ID = Protocol.class.getName();
 
Index: src/java/org/apache/nutch/protocol/ProtocolFactory.java
===================================================================
--- src/java/org/apache/nutch/protocol/ProtocolFactory.java	(revision 367309)
+++ src/java/org/apache/nutch/protocol/ProtocolFactory.java	(working copy)
@@ -24,6 +24,7 @@
 
 import java.util.logging.Logger;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 /** Creates and caches {@link Protocol} plugins.  Protocol plugins should
  * define the attribute "protocolName" with the name of the protocol that they
@@ -33,21 +34,20 @@
   public static final Logger LOG = LogFormatter
     .getLogger(ProtocolFactory.class.getName());
 
-  private final static ExtensionPoint X_POINT = PluginRepository.getInstance()
-      .getExtensionPoint(Protocol.X_POINT_ID);
+  private Hashtable CACHE = new Hashtable();
 
-  static {
-    if (X_POINT == null) {
-      throw new RuntimeException("x-point "+Protocol.X_POINT_ID+" not found.");
-    }
-  }
+  private ExtensionPoint extensionPoint;
 
-  private static final Hashtable CACHE = new Hashtable();
+  public  ProtocolFactory(NutchConf nutchConf) {
+      this.extensionPoint = nutchConf.getPluginRepository()
+      .getExtensionPoint(Protocol.X_POINT_ID);
+      if (this.extensionPoint == null) {
+          throw new RuntimeException("x-point "+Protocol.X_POINT_ID+" not found.");
+        }
+  }                      
 
-  private ProtocolFactory() {}                      // no public ctor
-
   /** Returns the appropriate {@link Protocol} implementation for a url. */
-  public static Protocol getProtocol(String urlString)
+  public Protocol getProtocol(String urlString)
     throws ProtocolNotFound {
     try {
       URL url = new URL(urlString);
@@ -67,7 +67,7 @@
     }
   }
 
-  private static Extension getExtension(String name)
+  private Extension getExtension(String name)
     throws PluginRuntimeException {
 
     if (CACHE.containsKey(name))
@@ -80,10 +80,10 @@
     return extension;
   }
 
-  private static Extension findExtension(String name)
+  private Extension findExtension(String name)
     throws PluginRuntimeException {
 
-    Extension[] extensions = X_POINT.getExtensions();
+    Extension[] extensions = this.extensionPoint.getExtensions();
 
     for (int i = 0; i < extensions.length; i++) {
       Extension extension = extensions[i];
Index: src/java/org/apache/nutch/protocol/Content.java
===================================================================
--- src/java/org/apache/nutch/protocol/Content.java	(revision 367309)
+++ src/java/org/apache/nutch/protocol/Content.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.nutch.util.mime.MimeType;
 import org.apache.nutch.util.mime.MimeTypes;
 import org.apache.nutch.util.mime.MimeTypeException;
+import org.apache.tools.ant.taskdefs.Sync.MyCopy;
 
 public final class Content extends CompressedWritable {
 
@@ -32,25 +33,19 @@
 
   private final static byte VERSION = 1;
 
-  /** A flag that tells if magic resolution must be performed */
-  private final static boolean MAGIC =
-    NutchConf.get().getBoolean("mime.type.magic", true);
-  
-  /** Get the MimeTypes resolver instance. */
-  private final static MimeTypes MIME = 
-    MimeTypes.get(NutchConf.get().get("mime.types.file"));
-
   private byte version;
   private String url;
   private String base;
   private byte[] content;
   private String contentType;
   private ContentProperties metadata;
+  private boolean mimeTypeMagic;
+  private MimeTypes mimeTypes;
 
   public Content() {}
     
   public Content(String url, String base, byte[] content, String contentType,
-                 ContentProperties metadata){
+                 ContentProperties metadata, NutchConf nutchConf){
 
     if (url == null) throw new IllegalArgumentException("null url");
     if (base == null) throw new IllegalArgumentException("null base");
@@ -60,8 +55,10 @@
     this.url = url;
     this.base = base;
     this.content = content;
-    this.contentType = getContentType(contentType, url, content);
     this.metadata = metadata;
+    this.mimeTypeMagic = nutchConf.getBoolean("mime.type.magic", true);
+    this.mimeTypes = MimeTypes.get(nutchConf.get("mime.types.file"));
+    this.contentType = getContentType(contentType, url, content);
   }
 
   protected final void readFieldsCompressed(DataInput in) throws IOException {
@@ -192,8 +189,8 @@
       System.out.println("usage:" + usage);
       return;
     }
-
-    NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, 0);
+   NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, 0, nutchConf);
     try {
       int recno = Integer.parseInt(argv[0]);
       String segment = argv[1];
@@ -201,7 +198,7 @@
       File file = new File(segment, DIR_NAME);
       System.out.println("Reading from file: " + file);
 
-      ArrayFile.Reader contents = new ArrayFile.Reader(nfs, file.toString());
+      ArrayFile.Reader contents = new ArrayFile.Reader(nfs, file.toString(), nutchConf);
 
       Content content = new Content();
       contents.get(recno, content);
@@ -216,11 +213,10 @@
   }
 
   private String getContentType(String typeName, String url, byte[] data) {
-    
     MimeType type = null;
     try {
         typeName = MimeType.clean(typeName);
-        type = typeName == null ? null : MIME.forName(typeName);
+        type = typeName == null ? null : this.mimeTypes.forName(typeName);
     } catch (MimeTypeException mte) {
         // Seems to be a malformed mime type name...
     }
@@ -229,15 +225,15 @@
       // If no mime-type header, or cannot find a corresponding registered
       // mime-type, or the one found doesn't match the url pattern
       // it shouldbe, then guess a mime-type from the url pattern
-      type = MIME.getMimeType(url);
+      type = this.mimeTypes.getMimeType(url);
       typeName = type == null ? typeName : type.getName();
     }
     if (typeName == null || type == null ||
-        (MAGIC && type.hasMagic() && !type.matches(data))) {
+        (this.mimeTypeMagic && type.hasMagic() && !type.matches(data))) {
       // If no mime-type already found, or the one found doesn't match
       // the magic bytes it should be, then, guess a mime-type from the
       // document content (magic bytes)
-      type = MIME.getMimeType(data);
+      type = this.mimeTypes.getMimeType(data);
       typeName = type == null ? typeName : type.getName();
     }
     return typeName;
Index: src/java/org/apache/nutch/segment/SegmentReader.java
===================================================================
--- src/java/org/apache/nutch/segment/SegmentReader.java	(revision 367309)
+++ src/java/org/apache/nutch/segment/SegmentReader.java	(working copy)
@@ -68,7 +68,7 @@
       throws IOException {
       reporter.setStatus(split.toString());
 
-      return new SequenceFileRecordReader(fs, split) {
+      return new SequenceFileRecordReader(job, split) {
           public synchronized boolean next(Writable key, Writable value)
             throws IOException {
             ObjectWritable wrapper = (ObjectWritable)value;
@@ -219,7 +219,8 @@
   }
   
   public static void main(String[] args) throws Exception {
-    SegmentReader segmentReader = new SegmentReader(NutchConf.get());
+    NutchConf nutchConf = new NutchConf();
+    SegmentReader segmentReader = new SegmentReader(nutchConf);
 
     String usage = "Usage: SegmentReader <segment>";
 
Index: src/java/org/apache/nutch/io/SequenceFile.java
===================================================================
--- src/java/org/apache/nutch/io/SequenceFile.java	(revision 359225)
+++ src/java/org/apache/nutch/io/SequenceFile.java	(working copy)
@@ -222,10 +222,12 @@
     private byte[] inflateIn = new byte[1024];
     private DataOutputBuffer inflateOut = new DataOutputBuffer();
     private Inflater inflater = new Inflater();
+    private NutchConf nutchConf;
 
     /** Open the named file. */
-    public Reader(NutchFileSystem nfs, String file) throws IOException {
-      this(nfs, file, NutchConf.get().getInt("io.file.buffer.size", 4096));
+    public Reader(NutchFileSystem nfs, String file, NutchConf nutchConf) throws IOException {
+      this(nfs, file, nutchConf.getInt("io.file.buffer.size", 4096));
+      this.nutchConf = nutchConf;
     }
 
     private Reader(NutchFileSystem nfs, String name, int bufferSize) throws IOException {
@@ -386,9 +388,9 @@
 
     private void handleChecksumException(ChecksumException e)
       throws IOException {
-      if (NutchConf.get().getBoolean("io.skip.checksum.errors", false)) {
+      if (this.nutchConf.getBoolean("io.skip.checksum.errors", false)) {
         LOG.warning("Bad checksum at "+getPosition()+". Skipping entries.");
-        sync(getPosition()+NutchConf.get().getInt("io.bytes.per.checksum", 512));
+        sync(getPosition()+this.nutchConf.getInt("io.bytes.per.checksum", 512));
       } else {
         throw e;
       }
@@ -449,37 +451,38 @@
    * very efficient.  In particular, it should avoid allocating memory.
    */
   public static class Sorter {
-    private static final int FACTOR =
-      NutchConf.get().getInt("io.sort.factor", 100); 
-    private static final int MEGABYTES =
-      NutchConf.get().getInt("io.sort.mb", 100); 
 
-    private WritableComparator comparator;
+      private WritableComparator comparator;
 
     private String inFile;                        // when sorting
     private String[] inFiles;                     // when merging
 
     private String outFile;
 
-    private int memory = MEGABYTES * 1024*1024;   // bytes
-    private int factor = FACTOR;                  // merged per pass
+    private int memory;// bytes
+    private int factor; // merged per pass
 
     private NutchFileSystem nfs = null;
 
     private Class keyClass;
     private Class valClass;
 
+    private NutchConf nutchConf;
+
     /** Sort and merge files containing the named classes. */
-    public Sorter(NutchFileSystem nfs, Class keyClass, Class valClass)  {
-      this(nfs, new WritableComparator(keyClass), valClass);
+    public Sorter(NutchFileSystem nfs, Class keyClass, Class valClass, NutchConf nutchConf)  {
+      this(nfs, new WritableComparator(keyClass), valClass, nutchConf);
     }
 
     /** Sort and merge using an arbitrary {@link WritableComparator}. */
-    public Sorter(NutchFileSystem nfs, WritableComparator comparator, Class valClass) {
+    public Sorter(NutchFileSystem nfs, WritableComparator comparator, Class valClass, NutchConf nutchConf) {
       this.nfs = nfs;
       this.comparator = comparator;
       this.keyClass = comparator.getKeyClass();
       this.valClass = valClass;
+      this.memory = nutchConf.getInt("io.sort.mb", 100) * 1024 * 1024;
+      this.factor = nutchConf.getInt("io.sort.factor", 100);
+      this.nutchConf = nutchConf;
     }
 
     /** Set the number of streams to merge at once.*/
@@ -513,7 +516,7 @@
 
     private int sortPass() throws IOException {
       LOG.fine("running sort pass");
-      SortPass sortPass = new SortPass();         // make the SortPass
+      SortPass sortPass = new SortPass(this.nutchConf);         // make the SortPass
       try {
         return sortPass.run();                    // run it
       } finally {
@@ -536,8 +539,8 @@
       private NFSDataOutputStream out;
         private String outName;
 
-      public SortPass() throws IOException {
-        in = new Reader(nfs, inFile);
+      public SortPass(NutchConf nutchConf) throws IOException {
+        in = new Reader(nfs, inFile, nutchConf);
       }
       
       public int run() throws IOException {
Index: src/java/org/apache/nutch/io/MapFile.java
===================================================================
--- src/java/org/apache/nutch/io/MapFile.java	(revision 359225)
+++ src/java/org/apache/nutch/io/MapFile.java	(working copy)
@@ -44,12 +44,9 @@
   /** The name of the data file. */
   public static final String DATA_FILE_NAME = "data";
 
-  /** Number of index entries to skip between each entry.  Zero by default.
-   * Setting this to values larger than zero can facilitate opening large map
-   * files using less memory. */
-  public static final int INDEX_SKIP =
-    NutchConf.get().getInt("io.map.index.skip", 0);
 
+
+
   protected MapFile() {}                          // no public ctor
 
   /** Writes a new map. */
@@ -160,6 +157,12 @@
   
   /** Provide access to an existing map. */
   public static class Reader {
+      
+    /** Number of index entries to skip between each entry.  Zero by default.
+    * Setting this to values larger than zero can facilitate opening large map
+    * files using less memory. */
+     private   int INDEX_SKIP =0;
+      
     private WritableComparator comparator;
 
     private DataOutputBuffer keyBuf = new DataOutputBuffer();
@@ -190,19 +193,20 @@
     public Class getValueClass() { return data.getValueClass(); }
 
     /** Construct a map reader for the named map.*/
-    public Reader(NutchFileSystem nfs, String dirName) throws IOException {
-      this(nfs, dirName, null);
+    public Reader(NutchFileSystem nfs, String dirName, NutchConf nutchConf) throws IOException {
+      this(nfs, dirName, null, nutchConf);
+      INDEX_SKIP = nutchConf.getInt("io.map.index.skip", 0);
     }
 
     /** Construct a map reader for the named map using the named comparator.*/
-    public Reader(NutchFileSystem nfs, String dirName, WritableComparator comparator)
+    public Reader(NutchFileSystem nfs, String dirName, WritableComparator comparator, NutchConf nutchConf)
       throws IOException {
       File dir = new File(dirName);
       File dataFile = new File(dir, DATA_FILE_NAME);
       File indexFile = new File(dir, INDEX_FILE_NAME);
 
       // open the data
-      this.data = new SequenceFile.Reader(nfs, dataFile.getPath());
+      this.data = new SequenceFile.Reader(nfs, dataFile.getPath(),  nutchConf);
       this.firstPosition = data.getPosition();
 
       if (comparator == null)
@@ -213,7 +217,7 @@
       this.getKey = this.comparator.newKey();
 
       // open the index
-      this.index = new SequenceFile.Reader(nfs, indexFile.getPath());
+      this.index = new SequenceFile.Reader(nfs, indexFile.getPath(), nutchConf);
     }
 
     private void readIndex() throws IOException {
@@ -416,7 +420,7 @@
    * @throws Exception
    */
   public static long fix(NutchFileSystem nfs, File dir,
-          Class keyClass, Class valueClass, boolean dryrun) throws Exception {
+          Class keyClass, Class valueClass, boolean dryrun, NutchConf nutchConf) throws Exception {
     String dr = (dryrun ? "[DRY RUN ] " : "");
     File data = new File(dir, DATA_FILE_NAME);
     File index = new File(dir, INDEX_FILE_NAME);
@@ -429,7 +433,7 @@
       // no fixing needed
       return -1;
     }
-    SequenceFile.Reader dataReader = new SequenceFile.Reader(nfs, data.toString());
+    SequenceFile.Reader dataReader = new SequenceFile.Reader(nfs, data.toString(), nutchConf);
     if (!dataReader.getKeyClass().equals(keyClass)) {
       throw new Exception(dr + "Wrong key class in " + dir + ", expected" + keyClass.getName() +
               ", got " + dataReader.getKeyClass().getName());
@@ -474,8 +478,10 @@
     String in = args[0];
     String out = args[1];
 
-    NutchFileSystem nfs = new LocalFileSystem();
-    MapFile.Reader reader = new MapFile.Reader(nfs, in);
+    NutchConf conf = new NutchConf();
+    int ioFileBufferSize = conf.getInt("io.file.buffer.size", 4096);
+    NutchFileSystem nfs = new LocalFileSystem(conf);
+    MapFile.Reader reader = new MapFile.Reader(nfs, in, conf);
     MapFile.Writer writer =
       new MapFile.Writer(nfs, out, reader.getKeyClass(), reader.getValueClass());
 
Index: src/java/org/apache/nutch/io/ArrayFile.java
===================================================================
--- src/java/org/apache/nutch/io/ArrayFile.java	(revision 359225)
+++ src/java/org/apache/nutch/io/ArrayFile.java	(working copy)
@@ -46,8 +46,8 @@
     private LongWritable key = new LongWritable();
 
     /** Construct an array reader for the named file.*/
-    public Reader(NutchFileSystem nfs, String file) throws IOException {
-      super(nfs, file);
+    public Reader(NutchFileSystem nfs, String file, NutchConf nutchConf) throws IOException {
+      super(nfs, file, nutchConf);
     }
 
     /** Positions the reader before its <code>n</code>th value. */
Index: src/java/org/apache/nutch/io/SetFile.java
===================================================================
--- src/java/org/apache/nutch/io/SetFile.java	(revision 359225)
+++ src/java/org/apache/nutch/io/SetFile.java	(working copy)
@@ -51,14 +51,14 @@
   public static class Reader extends MapFile.Reader {
 
     /** Construct a set reader for the named set.*/
-    public Reader(NutchFileSystem nfs, String dirName) throws IOException {
-      super(nfs, dirName);
+    public Reader(NutchFileSystem nfs, String dirName, NutchConf nutchConf) throws IOException {
+      super(nfs, dirName, nutchConf);
     }
 
     /** Construct a set reader for the named set using the named comparator.*/
-    public Reader(NutchFileSystem nfs, String dirName, WritableComparator comparator)
+    public Reader(NutchFileSystem nfs, String dirName, WritableComparator comparator, NutchConf nutchConf)
       throws IOException {
-      super(nfs, dirName, comparator);
+      super(nfs, dirName, comparator, nutchConf);
     }
 
     // javadoc inherited
Index: src/java/org/apache/nutch/mapred/SequenceFileOutputFormat.java
===================================================================
--- src/java/org/apache/nutch/mapred/SequenceFileOutputFormat.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/SequenceFileOutputFormat.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.io.SequenceFile;
 import org.apache.nutch.io.WritableComparable;
 import org.apache.nutch.io.Writable;
+import org.apache.nutch.util.NutchConf;
 
 public class SequenceFileOutputFormat implements OutputFormat {
 
@@ -53,8 +54,9 @@
   }
 
   /** Open the output generated by this format. */
-  public static SequenceFile.Reader[] getReaders(NutchFileSystem fs, File dir)
+  public static SequenceFile.Reader[] getReaders(NutchConf nutchConf, File dir)
     throws IOException {
+    NutchFileSystem fs = NutchFileSystem.get(nutchConf);
     File[] names = fs.listFiles(dir);
     
     // sort names, so that hash partitioning works
@@ -62,7 +64,7 @@
     
     SequenceFile.Reader[] parts = new SequenceFile.Reader[names.length];
     for (int i = 0; i < names.length; i++) {
-      parts[i] = new SequenceFile.Reader(fs, names[i].toString());
+      parts[i] = new SequenceFile.Reader(fs, names[i].toString(), nutchConf);
     }
     return parts;
   }
Index: src/java/org/apache/nutch/mapred/demo/Grep.java
===================================================================
--- src/java/org/apache/nutch/mapred/demo/Grep.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/demo/Grep.java	(working copy)
@@ -45,7 +45,7 @@
       System.exit(-1);
     }
 
-    NutchConf defaults = NutchConf.get();
+    NutchConf defaults = new NutchConf();
 
     File tempDir =
       new File("grep-temp-"+
Index: src/java/org/apache/nutch/mapred/TaskTracker.java
===================================================================
--- src/java/org/apache/nutch/mapred/TaskTracker.java	(revision 367309)
+++ src/java/org/apache/nutch/mapred/TaskTracker.java	(working copy)
@@ -33,14 +33,10 @@
  * @author Mike Cafarella
  *******************************************************/
 public class TaskTracker implements MRConstants, TaskUmbilicalProtocol, MapOutputProtocol, Runnable {
-    private static final int MAX_CURRENT_TASKS = 
-    NutchConf.get().getInt("mapred.tasktracker.tasks.maximum", 2);
-
+    private  int maxCurrentTask; 
     static final long WAIT_FOR_DONE = 3 * 1000;
+   private long taskTimeout; 
 
-    static final long TASK_TIMEOUT = 
-      NutchConf.get().getInt("mapred.task.timeout", 10* 60 * 1000);
-
     static final int STALE_STATE = 1;
 
     public static final Logger LOG =
@@ -82,6 +78,8 @@
     public TaskTracker(InetSocketAddress jobTrackAddr, NutchConf conf) throws IOException {
         this.fConf = conf;
         this.jobTrackAddr = jobTrackAddr;
+        this.maxCurrentTask = conf.getInt("mapred.tasktracker.tasks.maximum", 2);
+        this.taskTimeout = conf.getInt("mapred.task.timeout", 10* 60 * 1000);
         initialize();
     }
 
@@ -94,7 +92,7 @@
         this.taskTrackerName = "tracker_" + (Math.abs(r.nextInt()) % 100000);
         this.localHostname = InetAddress.getLocalHost().getHostName();
 
-        JobConf.deleteLocalFiles(SUBDIR);
+        new JobConf(this.fConf).deleteLocalFiles(SUBDIR);
 
         // Clear out state tables
         this.tasks = new TreeMap();
@@ -107,7 +105,7 @@
         // RPC initialization
         while (true) {
             try {
-                this.taskReportServer = RPC.getServer(this, this.taskReportPort, MAX_CURRENT_TASKS, false);
+                this.taskReportServer = RPC.getServer(this, this.taskReportPort, this.maxCurrentTask, false, this.fConf);
                 this.taskReportServer.start();
                 break;
             } catch (BindException e) {
@@ -118,7 +116,7 @@
         }
         while (true) {
             try {
-                this.mapOutputServer = RPC.getServer(this, this.mapOutputPort, MAX_CURRENT_TASKS, false);
+                this.mapOutputServer = RPC.getServer(this, this.mapOutputPort, this.maxCurrentTask, false, this.fConf);
                 this.mapOutputServer.start();
                 break;
             } catch (BindException e) {
@@ -131,7 +129,7 @@
         MapOutputFile.cleanupStorage();
         this.justStarted = true;
 
-        this.jobClient = (InterTrackerProtocol) RPC.getProxy(InterTrackerProtocol.class, jobTrackAddr);
+        this.jobClient = (InterTrackerProtocol) RPC.getProxy(InterTrackerProtocol.class, jobTrackAddr, this.fConf);
     }
 
     /**
@@ -213,7 +211,7 @@
             // Xmit the heartbeat
             //
             if (justStarted) {
-                this.fs = NutchFileSystem.getNamed(jobClient.getFilesystemName());
+                this.fs = NutchFileSystem.getNamed(jobClient.getFilesystemName(),this.fConf);
             }
             
             int resultCode = jobClient.emitHeartbeat(new TaskTrackerStatus(taskTrackerName, localHostname, mapOutputPort, taskReports), justStarted);
@@ -226,7 +224,7 @@
             //
             // Check if we should create a new Task
             //
-            if (runningTasks.size() < MAX_CURRENT_TASKS) {
+            if (runningTasks.size() < this.maxCurrentTask) {
                 Task t = jobClient.pollForNewTask(taskTrackerName);
                 if (t != null) {
                     TaskInProgress tip = new TaskInProgress(t);
@@ -245,7 +243,7 @@
                 for (Iterator it = runningTasks.values().iterator(); it.hasNext(); ) {
                     TaskInProgress tip = (TaskInProgress) it.next();
                     if ((tip.getRunState() == TaskStatus.RUNNING) &&
-                        (System.currentTimeMillis() - tip.getLastProgressReport() > TASK_TIMEOUT)) {
+                        (System.currentTimeMillis() - tip.getLastProgressReport() > this.taskTimeout)) {
                         LOG.info("Task " + tip.getTask().getTaskId() + " timed out.  Killing.");
                         tip.reportDiagnosticInfo("Timed out.");
                         tip.killAndCleanup();
@@ -327,7 +325,7 @@
         public TaskInProgress(Task task) throws IOException {
             this.task = task;
             this.lastProgressReport = System.currentTimeMillis();
-            JobConf.deleteLocalFiles(SUBDIR+File.separator+task.getTaskId());
+            new JobConf().deleteLocalFiles(SUBDIR+File.separator+task.getTaskId());
             localizeTask(task);
         }
 
@@ -337,9 +335,9 @@
          */
         void localizeTask(Task t) throws IOException {
             File localJobFile =
-              JobConf.getLocalFile(SUBDIR+File.separator+t.getTaskId(), "job.xml");
+              new JobConf().getLocalFile(SUBDIR+File.separator+t.getTaskId(), "job.xml");
             File localJarFile =
-              JobConf.getLocalFile(SUBDIR+File.separator+t.getTaskId(), "job.jar");
+              new JobConf().getLocalFile(SUBDIR+File.separator+t.getTaskId(), "job.jar");
 
             String jobFile = t.getJobFile();
             fs.copyToLocalFile(new File(jobFile), localJobFile);
@@ -501,7 +499,7 @@
                 runner.close();
             } catch (IOException ie) {
             }
-            JobConf.deleteLocalFiles(SUBDIR+File.separator+task.getTaskId());
+            new JobConf().deleteLocalFiles(SUBDIR+File.separator+task.getTaskId());
         }
     }
 
@@ -510,7 +508,7 @@
     /////////////////////////////////////////////////////////////////
     public MapOutputFile getFile(String mapTaskId, String reduceTaskId,
                                  IntWritable partition) {
-        return new MapOutputFile(mapTaskId, reduceTaskId, partition.get());
+        return new MapOutputFile(mapTaskId, reduceTaskId, partition.get(), this.fConf);
     }
 
     /////////////////////////////////////////////////////////////////
@@ -586,16 +584,17 @@
           LogFormatter.showTime(false);
           LOG.info("Child starting");
 
+          NutchConf nutchConf = new NutchConf();
           int port = Integer.parseInt(args[0]);
           String taskid = args[1];
           TaskUmbilicalProtocol umbilical =
             (TaskUmbilicalProtocol)RPC.getProxy(TaskUmbilicalProtocol.class,
-                                                new InetSocketAddress(port));
+                                                new InetSocketAddress(port), nutchConf);
             
           Task task = umbilical.getTask(taskid);
           JobConf job = new JobConf(task.getJobFile());
 
-          NutchConf.get().addConfResource(new File(task.getJobFile()));
+          nutchConf.addConfResource(new File(task.getJobFile()));
 
           startPinging(umbilical, taskid);        // start pinging parent
 
@@ -646,7 +645,7 @@
             System.exit(-1);
         }
 
-        TaskTracker tt = new TaskTracker(NutchConf.get());
+        TaskTracker tt = new TaskTracker(new NutchConf());
         tt.run();
     }
 }
Index: src/java/org/apache/nutch/mapred/JobConf.java
===================================================================
--- src/java/org/apache/nutch/mapred/JobConf.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/JobConf.java	(working copy)
@@ -50,6 +50,10 @@
  * of input files, and where the output files should be written. */
 public class JobConf extends NutchConf {
 
+    public JobConf(){
+        super();
+    }
+    
   /** Construct a map/reduce job configuration.
    *
    * @param conf a NutchConf whose settings will be inherited.
@@ -81,32 +85,32 @@
   public String getJar() { return get("mapred.jar"); }
   public void setJar(String jar) { set("mapred.jar", jar); }
 
-  public static File getSystemDir() {
-    return new File(NutchConf.get().get("mapred.system.dir",
+  public File getSystemDir() {
+    return new File(get("mapred.system.dir",
                                         "/tmp/nutch/mapred/system"));
   }
 
-  public static String[] getLocalDirs() throws IOException {
-    return NutchConf.get().getStrings("mapred.local.dir");
+  public String[] getLocalDirs() throws IOException {
+    return getStrings("mapred.local.dir");
   }
 
-  public static void deleteLocalFiles() throws IOException {
+  public void deleteLocalFiles() throws IOException {
     String[] localDirs = getLocalDirs();
     for (int i = 0; i < localDirs.length; i++) {
-      FileUtil.fullyDelete(new File(localDirs[i]));
+      FileUtil.fullyDelete(new File(localDirs[i]), this);
     }
   }
 
-  public static void deleteLocalFiles(String subdir) throws IOException {
+  public void deleteLocalFiles(String subdir) throws IOException {
     String[] localDirs = getLocalDirs();
     for (int i = 0; i < localDirs.length; i++) {
-      FileUtil.fullyDelete(new File(localDirs[i], subdir));
+      FileUtil.fullyDelete(new File(localDirs[i], subdir), this);
     }
   }
 
   /** Constructs a local file name.  Files are distributed among configured
    * local directories.*/
-  public static File getLocalFile(String subdir, String name)
+  public File getLocalFile(String subdir, String name)
     throws IOException {
     String[] localDirs = getLocalDirs();
     String path = subdir + File.separator + name;
Index: src/java/org/apache/nutch/mapred/JobTracker.java
===================================================================
--- src/java/org/apache/nutch/mapred/JobTracker.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/JobTracker.java	(working copy)
@@ -210,25 +210,29 @@
     NutchFileSystem fs;
     File systemDir;
 
+    private NutchConf nutchConf;
+
     /**
      * Start the JobTracker process, listen on the indicated port
      */
     JobTracker(NutchConf conf) throws IOException {
         // This is a directory of temporary submission files.  We delete it
         // on startup, and can delete any files that we're done with
-        this.systemDir = JobConf.getSystemDir();
-        this.fs = NutchFileSystem.get();
+        JobConf jobConf = new JobConf(conf);
+        this.systemDir = jobConf.getSystemDir();
+        this.nutchConf = conf;
+        this.fs = NutchFileSystem.get(conf);
         FileUtil.fullyDelete(fs, systemDir);
         fs.mkdirs(systemDir);
 
         // Same with 'localDir' except it's always on the local disk.
-        JobConf.deleteLocalFiles(SUBDIR);
+        jobConf.deleteLocalFiles(SUBDIR);
 
         // Set ports, start RPC servers, etc.
         InetSocketAddress addr = getAddress(conf);
         this.localMachine = addr.getHostName();
         this.port = addr.getPort();
-        this.interTrackerServer = RPC.getServer(this,addr.getPort(),10,false);
+        this.interTrackerServer = RPC.getServer(this,addr.getPort(),10,false, conf);
         this.interTrackerServer.start();
 	Properties p = System.getProperties();
 	for (Iterator it = p.keySet().iterator(); it.hasNext(); ) {
@@ -529,7 +533,7 @@
      * task allocation.)
      */
     JobInProgress createJob(String jobFile) throws IOException {
-        JobInProgress job = new JobInProgress(jobFile);
+        JobInProgress job = new JobInProgress(jobFile, this.nutchConf);
         jobs.put(job.getProfile().getJobId(), job);
 
         boolean error = true;
@@ -576,6 +580,7 @@
         long startTime;
         long finishTime;
         String deleteUponCompletion = null;
+        private NutchConf nutchConf;
 
         /**
          * Create a 'JobInProgress' object, which contains both JobProfile
@@ -583,13 +588,13 @@
          * of the JobTracker.  But JobInProgress adds info that's useful for
          * the JobTracker alone.
          */
-        public JobInProgress(String jobFile) throws IOException {
+        public JobInProgress(String jobFile, NutchConf nutchConf) throws IOException {
             String jobid = createJobId();
             String url = "http://" + localMachine + ":" + infoPort + "/jobdetails.jsp?jobid=" + jobid;
             this.profile = new JobProfile(jobid, jobFile, url);
             this.status = new JobStatus(jobid, 0.0f, 0.0f, JobStatus.RUNNING);
 
-            this.localJobFile = JobConf.getLocalFile(SUBDIR, jobid+".xml");
+            this.localJobFile = new JobConf(nutchConf).getLocalFile(SUBDIR, jobid+".xml");
             fs.copyToLocalFile(new File(jobFile), localJobFile);
 
             JobConf jd = new JobConf(localJobFile);
@@ -602,6 +607,7 @@
             if (jobFile.startsWith(systemDir.getPath())) {
                 this.deleteUponCompletion = jobFile;
             }
+            this.nutchConf = nutchConf;
         }
 
         /**
@@ -613,7 +619,7 @@
 
             // construct input splits
             JobConf jd = new JobConf(localJobFile);
-            NutchFileSystem fs = NutchFileSystem.get();
+            NutchFileSystem fs = NutchFileSystem.get(nutchConf);
             FileSplit[] splits =
               jd.getInputFormat().getSplits(fs, jd, numMapTasks);
 
@@ -642,7 +648,7 @@
             // Create reduce tasks
             for (int i = 0; i < numReduceTasks; i++) {
                 String taskid = createReduceTaskId();
-                Task t = new ReduceTask(jobFile, taskid, mapIds, i);
+                Task t = new ReduceTask(jobFile, taskid, mapIds, i, this.nutchConf);
                 reducesToLaunch.add(t);
                 taskToJobMap.put(taskid, jobid);
             }
@@ -1067,6 +1073,6 @@
           System.exit(-1);
         }
 
-        startTracker(NutchConf.get());
+        startTracker(new NutchConf());
     }
 }
Index: src/java/org/apache/nutch/mapred/JobTrackerInfoServer.java
===================================================================
--- src/java/org/apache/nutch/mapred/JobTrackerInfoServer.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/JobTrackerInfoServer.java	(working copy)
@@ -63,7 +63,7 @@
     public JobTrackerInfoServer(JobTracker jobTracker, int port) throws IOException {
         this.jobTracker = jobTracker;
         this.server = new org.mortbay.jetty.Server();
-	URL url = JobTrackerInfoServer.class.getClassLoader().getResource("webapps");
+	URL url = JobTrackerInfoServer.class.getClassLoader().getResource(".");
 	String path = url.getPath();
 	if (WINDOWS && path.startsWith("/")) {
 	    path = path.substring(1);
Index: src/java/org/apache/nutch/mapred/ReduceTask.java
===================================================================
--- src/java/org/apache/nutch/mapred/ReduceTask.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/ReduceTask.java	(working copy)
@@ -37,18 +37,22 @@
   private Progress appendPhase = getProgress().addPhase("append");
   private Progress sortPhase  = getProgress().addPhase("sort");
   private Progress reducePhase = getProgress().addPhase("reduce");
+  private NutchConf nutchConf;
 
-  public ReduceTask() {}
+  public ReduceTask(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+  }
 
   public ReduceTask(String jobFile, String taskId,
-                    String[] mapTaskIds, int partition) {
+                    String[] mapTaskIds, int partition, NutchConf nutchConf) {
     super(jobFile, taskId);
     this.mapTaskIds = mapTaskIds;
     this.partition = partition;
+    this.nutchConf = nutchConf;
   }
 
   public TaskRunner createRunner(TaskTracker tracker) {
-    return new ReduceTaskRunner(this, tracker);
+    return new ReduceTaskRunner(this, tracker, this.nutchConf);
   }
 
   public String[] getMapTaskIds() { return mapTaskIds; }
@@ -157,7 +161,7 @@
     Class keyClass = job.getOutputKeyClass();
     Class valueClass = job.getOutputValueClass();
     Reducer reducer = (Reducer)job.newInstance(job.getReducerClass());
-    NutchFileSystem lfs = NutchFileSystem.getNamed("local");
+    NutchFileSystem lfs = NutchFileSystem.getNamed("local", job);
 
     copyPhase.complete();                         // copy is already complete
 
@@ -180,7 +184,7 @@
         Progress phase = appendPhase.phase();
         phase.setStatus(partFile.toString());
         SequenceFile.Reader in =
-          new SequenceFile.Reader(lfs, partFile.toString());
+          new SequenceFile.Reader(lfs, partFile.toString(), job);
         try {
           int keyLen;
           while((keyLen = in.next(buffer)) > 0) {
@@ -227,7 +231,7 @@
 
       // sort the input file
       SequenceFile.Sorter sorter =
-        new SequenceFile.Sorter(lfs, comparator, valueClass);
+        new SequenceFile.Sorter(lfs, comparator, valueClass, job);
       sorter.sort(file, sortedFile);              // sort
       lfs.delete(new File(file));                 // remove unsorted
 
@@ -240,7 +244,7 @@
     // make output collector
     String name = getOutputName(getPartition());
     final RecordWriter out =
-      job.getOutputFormat().getRecordWriter(NutchFileSystem.get(), job, name);
+      job.getOutputFormat().getRecordWriter(NutchFileSystem.get(job), job, name);
     OutputCollector collector = new OutputCollector() {
         public void collect(WritableComparable key, Writable value)
           throws IOException {
@@ -250,7 +254,7 @@
       };
     
     // apply reduce function
-    SequenceFile.Reader in = new SequenceFile.Reader(lfs, sortedFile);
+    SequenceFile.Reader in = new SequenceFile.Reader(lfs, sortedFile, job);
     Reporter reporter = getReporter(umbilical, getProgress());
     long length = lfs.getLength(new File(sortedFile));
     try {
Index: src/java/org/apache/nutch/mapred/MapTask.java
===================================================================
--- src/java/org/apache/nutch/mapred/MapTask.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/MapTask.java	(working copy)
@@ -62,7 +62,7 @@
     try {
       for (int i = 0; i < partitions; i++) {
         outs[i] =
-          new SequenceFile.Writer(NutchFileSystem.getNamed("local"),
+          new SequenceFile.Writer(NutchFileSystem.getNamed("local", job),
                                   MapOutputFile.getOutputFile(getTaskId(), i).toString(),
                                   job.getOutputKeyClass(),
                                   job.getOutputValueClass());
@@ -91,7 +91,7 @@
 
       final RecordReader rawIn =                  // open input
         job.getInputFormat().getRecordReader
-        (NutchFileSystem.get(), split, job, reporter);
+        (NutchFileSystem.get(job), split, job, reporter);
 
       RecordReader in = new RecordReader() {      // wrap in progress reporter
           private float perByte = 1.0f /(float)split.getLength();
Index: src/java/org/apache/nutch/mapred/SequenceFileInputFormat.java
===================================================================
--- src/java/org/apache/nutch/mapred/SequenceFileInputFormat.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/SequenceFileInputFormat.java	(working copy)
@@ -54,7 +54,7 @@
 
     reporter.setStatus(split.toString());
 
-    return new SequenceFileRecordReader(fs, split);
+    return new SequenceFileRecordReader(job, split);
   }
 
 }
Index: src/java/org/apache/nutch/mapred/MapFileOutputFormat.java
===================================================================
--- src/java/org/apache/nutch/mapred/MapFileOutputFormat.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/MapFileOutputFormat.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.nutch.io.MapFile;
 import org.apache.nutch.io.WritableComparable;
 import org.apache.nutch.io.Writable;
+import org.apache.nutch.util.NutchConf;
 
 public class MapFileOutputFormat implements OutputFormat {
 
@@ -52,7 +53,7 @@
   }
 
   /** Open the output generated by this format. */
-  public static MapFile.Reader[] getReaders(NutchFileSystem fs, File dir)
+  public static MapFile.Reader[] getReaders(NutchFileSystem fs, File dir, NutchConf nutchConf)
     throws IOException {
     File[] names = fs.listFiles(dir);
     
@@ -61,7 +62,7 @@
     
     MapFile.Reader[] parts = new MapFile.Reader[names.length];
     for (int i = 0; i < names.length; i++) {
-      parts[i] = new MapFile.Reader(fs, names[i].toString());
+      parts[i] = new MapFile.Reader(fs, names[i].toString(), nutchConf);
     }
     return parts;
   }
Index: src/java/org/apache/nutch/mapred/JobClient.java
===================================================================
--- src/java/org/apache/nutch/mapred/JobClient.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/JobClient.java	(working copy)
@@ -166,28 +166,30 @@
     JobSubmissionProtocol jobSubmitClient;
     NutchFileSystem fs = null;
 
+    private NutchConf nutchConf;
     static Random r = new Random();
 
     /**
      * Build a job client, connect to the default job tracker
      */
     public JobClient(NutchConf conf) throws IOException {
+      this.nutchConf = conf;
       String tracker = conf.get("mapred.job.tracker", "local");
       if ("local".equals(tracker)) {
-        this.jobSubmitClient = new LocalJobRunner();
+        this.jobSubmitClient = new LocalJobRunner(conf);
       } else {
         this.jobSubmitClient = (JobSubmissionProtocol) 
           RPC.getProxy(JobSubmissionProtocol.class,
-                       JobTracker.getAddress(conf));
+                       JobTracker.getAddress(conf), conf);
       }
     }
   
     /**
      * Build a job client, connect to the indicated job tracker.
      */
-    public JobClient(InetSocketAddress jobTrackAddr) throws IOException {
+    public JobClient(InetSocketAddress jobTrackAddr, NutchConf nutchConf) throws IOException {
         this.jobSubmitClient = (JobSubmissionProtocol) 
-            RPC.getProxy(JobSubmissionProtocol.class, jobTrackAddr);
+            RPC.getProxy(JobSubmissionProtocol.class, jobTrackAddr, nutchConf);
     }
 
 
@@ -207,7 +209,7 @@
     public synchronized NutchFileSystem getFs() throws IOException {
       if (this.fs == null) {
         String fsName = jobSubmitClient.getFilesystemName();
-        this.fs = NutchFileSystem.getNamed(fsName);
+        this.fs = NutchFileSystem.getNamed(fsName, this.nutchConf);
       }
       return fs;
     }
@@ -234,7 +236,7 @@
         //
 
         // Create a number of filenames in the JobTracker's fs namespace
-        File submitJobDir = new File(JobConf.getSystemDir(), "submit_" + Integer.toString(Math.abs(r.nextInt()),36));
+        File submitJobDir = new File(new JobConf(job).getSystemDir(), "submit_" + Integer.toString(Math.abs(r.nextInt()),36));
         File submitJobFile = new File(submitJobDir, "job.xml");
         File submitJarFile = new File(submitJobDir, "job.jar");
 
@@ -349,7 +351,7 @@
         }
 
         // Submit the request
-        JobClient jc = new JobClient(NutchConf.get());
+        JobClient jc = new JobClient(new NutchConf());
         try {
             if (submitJobFile != null) {
                 RunningJob job = jc.submitJob(submitJobFile);
Index: src/java/org/apache/nutch/mapred/CombiningCollector.java
===================================================================
--- src/java/org/apache/nutch/mapred/CombiningCollector.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/CombiningCollector.java	(working copy)
@@ -28,8 +28,7 @@
  * then invokes the combiner's reduce method to merge some values before
  * they're transferred to a reduce node. */
 class CombiningCollector implements OutputCollector {
-  private static final int LIMIT
-    = NutchConf.get().getInt("mapred.combine.buffer.size", 100000);
+  private  int limit;
 
   private int count = 0;
   private Map keyToValues;                        // the buffer
@@ -46,6 +45,7 @@
     this.reporter = reporter;
     this.combiner = (Reducer)job.newInstance(job.getCombinerClass());
     this.keyToValues = new TreeMap(job.getOutputKeyComparator());
+    this.limit = job.getInt("mapred.combine.buffer.size", 100000);
   }
 
   public synchronized void collect(WritableComparable key, Writable value)
@@ -63,7 +63,7 @@
 
     count++;
 
-    if (count >= LIMIT) {                         // time to flush
+    if (count >= this.limit) {                         // time to flush
       flush();
     }
   }
Index: src/java/org/apache/nutch/mapred/LocalJobRunner.java
===================================================================
--- src/java/org/apache/nutch/mapred/LocalJobRunner.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/LocalJobRunner.java	(working copy)
@@ -45,10 +45,11 @@
       this.file = file;
       this.id = "job_" + newId();
 
-      File localFile = JobConf.getLocalFile("localRunner", id+".xml");
+      File localFile = new JobConf().getLocalFile("localRunner", id+".xml");
       fs.copyToLocalFile(new File(file), localFile);
       this.job = new JobConf(localFile);
-
+      
+      
       this.status.jobid = id;
       this.status.runState = JobStatus.RUNNING;
 
@@ -77,7 +78,7 @@
           File mapOut = MapOutputFile.getOutputFile(mapId, 0);
           File reduceIn = MapOutputFile.getInputFile(mapId, reduceId);
           reduceIn.getParentFile().mkdirs();
-          if (!NutchFileSystem.getNamed("local").rename(mapOut, reduceIn))
+          if (!NutchFileSystem.getNamed("local", this.job).rename(mapOut, reduceIn))
             throw new IOException("Couldn't rename " + mapOut);
           MapOutputFile.removeAll(mapId);
         }
@@ -86,7 +87,7 @@
         ReduceTask reduce =
           new ReduceTask(file, reduceId,
                          (String[])mapIds.toArray(new String[0]),
-                         0);
+                         0, this.job);
         reduce.run(job, this);
         MapOutputFile.removeAll(reduceId);
         
@@ -138,8 +139,8 @@
 
   }
 
-  public LocalJobRunner() throws IOException {
-    this.fs = NutchFileSystem.get();
+  public LocalJobRunner(NutchConf nutchConf) throws IOException {
+    this.fs = NutchFileSystem.get(nutchConf);
   }
 
   // JobSubmissionProtocol methods
Index: src/java/org/apache/nutch/mapred/ReduceTaskRunner.java
===================================================================
--- src/java/org/apache/nutch/mapred/ReduceTaskRunner.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/ReduceTaskRunner.java	(working copy)
@@ -28,9 +28,11 @@
 class ReduceTaskRunner extends TaskRunner {
   private static final Logger LOG =
     LogFormatter.getLogger("org.apache.nutch.mapred.ReduceTaskRunner");
+  private NutchConf nutchConf;
 
-  public ReduceTaskRunner(Task task, TaskTracker tracker) {
+  public ReduceTaskRunner(Task task, TaskTracker tracker, NutchConf nutchConf) {
     super(task, tracker);
+    this.nutchConf = nutchConf;
   }
 
   /** Assemble all of the map output files. */
@@ -74,7 +76,7 @@
         InetSocketAddress addr =
           new InetSocketAddress(loc.getHost(), loc.getPort());
         MapOutputProtocol client =
-          (MapOutputProtocol)RPC.getProxy(MapOutputProtocol.class, addr);
+          (MapOutputProtocol)RPC.getProxy(MapOutputProtocol.class, addr, this.nutchConf);
 
         MapOutputFile.setProgressReporter(new MapOutputFile.ProgressReporter(){
             public void progress(float progress) {
Index: src/java/org/apache/nutch/mapred/SequenceFileRecordReader.java
===================================================================
--- src/java/org/apache/nutch/mapred/SequenceFileRecordReader.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/SequenceFileRecordReader.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.io.WritableComparable;
 import org.apache.nutch.io.LongWritable;
 import org.apache.nutch.io.UTF8;
+import org.apache.nutch.util.NutchConf;
 
 /** An {@link RecordReader} for {@link SequenceFile}s. */
 public class SequenceFileRecordReader implements RecordReader {
@@ -33,9 +34,10 @@
   private long end;
   private boolean more = true;
 
-  public SequenceFileRecordReader(NutchFileSystem fs, FileSplit split)
+  public SequenceFileRecordReader(NutchConf nutchConf, FileSplit split)
     throws IOException {
-    this.in = new SequenceFile.Reader(fs, split.getFile().toString());
+    NutchFileSystem fs = NutchFileSystem.get(nutchConf);
+    this.in = new SequenceFile.Reader(fs, split.getFile().toString(), nutchConf);
     this.end = split.getStart() + split.getLength();
 
     if (split.getStart() > in.getPosition())
Index: src/java/org/apache/nutch/mapred/MapOutputFile.java
===================================================================
--- src/java/org/apache/nutch/mapred/MapOutputFile.java	(revision 359225)
+++ src/java/org/apache/nutch/mapred/MapOutputFile.java	(working copy)
@@ -28,6 +28,7 @@
   private String mapTaskId;
   private String reduceTaskId;
   private int partition;
+private NutchConf nutchConf;
   
   /** Permits reporting of file copy progress. */
   public static interface ProgressReporter {
@@ -46,7 +47,7 @@
    */
   public static File getOutputFile(String mapTaskId, int partition)
     throws IOException {
-    return JobConf.getLocalFile(mapTaskId, "part-"+partition+".out");
+    return new JobConf().getLocalFile(mapTaskId, "part-"+partition+".out");
   }
 
   /** Create a local reduce input file name.
@@ -55,12 +56,12 @@
    */
   public static File getInputFile(String mapTaskId, String reduceTaskId)
     throws IOException {
-    return JobConf.getLocalFile(reduceTaskId, mapTaskId+".out");
+    return new JobConf().getLocalFile(reduceTaskId, mapTaskId+".out");
   }
 
   /** Removes all of the files related to a task. */
   public static void removeAll(String taskId) throws IOException {
-    JobConf.deleteLocalFiles(taskId);
+    new JobConf().deleteLocalFiles(taskId);
   }
 
   /** 
@@ -68,16 +69,18 @@
    * startup, to remove any leftovers from previous run.
    */
   public static void cleanupStorage() throws IOException {
-    JobConf.deleteLocalFiles();
+    new JobConf().deleteLocalFiles();
   }
 
   /** Construct a file for transfer. */
-  public MapOutputFile() {
+  public MapOutputFile(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
   }
-  public MapOutputFile(String mapTaskId, String reduceTaskId, int partition) {
+  public MapOutputFile(String mapTaskId, String reduceTaskId, int partition, NutchConf nutchConf) {
     this.mapTaskId = mapTaskId;
     this.reduceTaskId = reduceTaskId;
     this.partition = partition;
+    this.nutchConf = nutchConf;
   }
 
   public void write(DataOutput out) throws IOException {
@@ -88,7 +91,7 @@
     // write the length-prefixed file content to the wire
     File file = getOutputFile(mapTaskId, partition);
     out.writeLong(file.length());
-    NFSDataInputStream in = NutchFileSystem.getNamed("local").open(file);
+    NFSDataInputStream in = NutchFileSystem.getNamed("local", this.nutchConf).open(file);
     try {
       byte[] buffer = new byte[8192];
       int l;
@@ -112,7 +115,7 @@
     long length = in.readLong();
     float progPerByte = 1.0f / length;
     long unread = length;
-    NFSDataOutputStream out = NutchFileSystem.getNamed("local").create(file);
+    NFSDataOutputStream out = NutchFileSystem.getNamed("local", this.nutchConf).create(file);
     try {
       byte[] buffer = new byte[8192];
       while (unread > 0) {
Index: src/java/org/apache/nutch/fs/LocalFileSystem.java
===================================================================
--- src/java/org/apache/nutch/fs/LocalFileSystem.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/LocalFileSystem.java	(working copy)
@@ -23,6 +23,7 @@
 import org.apache.nutch.ndfs.NDFSFile;
 import org.apache.nutch.ndfs.DF;
 import org.apache.nutch.ndfs.NDFSFileInfo;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.io.UTF8;
 
 /****************************************************************
@@ -38,11 +39,11 @@
     TreeMap lockObjSet = new TreeMap();
     // by default use copy/delete instead of rename
     boolean useCopyForRename = true;
-
+    
     /**
      */
-    public LocalFileSystem() throws IOException {
-        super();
+    public LocalFileSystem(NutchConf nutchConf) throws IOException {
+        super(nutchConf);
         // if you find an OS which reliably supports non-POSIX
         // rename(2) across filesystems / volumes, you can
         // uncomment this.
@@ -175,7 +176,7 @@
      */
     public boolean renameRaw(File src, File dst) throws IOException {
         if (useCopyForRename) {
-            FileUtil.copyContents(this, src, dst, true);
+            FileUtil.copyContents(this, src, dst, true, nutchConf);
             return fullyDelete(src);
         } else return src.renameTo(dst);
     }
@@ -288,7 +289,7 @@
     public void moveFromLocalFile(File src, File dst) throws IOException {
         if (! src.equals(dst)) {
             if (useCopyForRename) {
-                FileUtil.copyContents(this, src, dst, true);
+                FileUtil.copyContents(this, src, dst, true, this.nutchConf);
                 fullyDelete(src);
             } else src.renameTo(dst);
         }
@@ -299,7 +300,7 @@
      */
     public void copyFromLocalFile(File src, File dst) throws IOException {
         if (! src.equals(dst)) {
-            FileUtil.copyContents(this, src, dst, true);
+            FileUtil.copyContents(this, src, dst, true, this.nutchConf);
         }
     }
 
@@ -308,7 +309,7 @@
      */
     public void copyToLocalFile(File src, File dst) throws IOException {
         if (! src.equals(dst)) {
-            FileUtil.copyContents(this, src, dst, true);
+            FileUtil.copyContents(this, src, dst, true, this.nutchConf);
         }
     }
 
Index: src/java/org/apache/nutch/fs/NDFSFileSystem.java
===================================================================
--- src/java/org/apache/nutch/fs/NDFSFileSystem.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/NDFSFileSystem.java	(working copy)
@@ -43,8 +43,9 @@
      * Create the ShareSet automatically, and then go on to
      * the regular constructor.
      */
-    public NDFSFileSystem(InetSocketAddress namenode) throws IOException {
-      this.ndfs = new NDFSClient(namenode);
+    public NDFSFileSystem(InetSocketAddress namenode, NutchConf nutchConf) throws IOException {
+      super(nutchConf);
+      this.ndfs = new NDFSClient(namenode, nutchConf);
       this.name = namenode.getHostName() + ":" + namenode.getPort();
     }
 
@@ -172,7 +173,7 @@
                 doFromLocalFile(contents[i], new File(dst, contents[i].getName()), deleteSource);
             }
         } else {
-            byte buf[] = new byte[NutchConf.get().getInt("io.file.buffer.size", 4096)];
+            byte buf[] = new byte[this.nutchConf.getInt("io.file.buffer.size", 4096)];
             InputStream in = new BufferedInputStream(new FileInputStream(src));
             try {
                 OutputStream out = create(dst);
@@ -217,10 +218,10 @@
                 copyToLocalFile(contents[i], new File(dst, contents[i].getName()));
             }
         } else {
-            byte buf[] = new byte[NutchConf.get().getInt("io.file.buffer.size", 4096)];
+            byte buf[] = new byte[this.nutchConf.getInt("io.file.buffer.size", 4096)];
             InputStream in = open(src);
             try {
-                OutputStream out = NutchFileSystem.getNamed("local").create(dst);
+                OutputStream out = NutchFileSystem.getNamed("local", this.nutchConf).create(dst);
                 try {
                     int bytesRead = in.read(buf);
                     while (bytesRead >= 0) {
@@ -267,7 +268,7 @@
      */
     public void completeLocalInput(File localFile) throws IOException {
         // Get rid of the local copy - we don't need it anymore.
-        FileUtil.fullyDelete(localFile);
+        FileUtil.fullyDelete(localFile, this.nutchConf);
     }
 
     /**
Index: src/java/org/apache/nutch/fs/NDFSShell.java
===================================================================
--- src/java/org/apache/nutch/fs/NDFSShell.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/NDFSShell.java	(working copy)
@@ -122,8 +122,8 @@
     /**
      * Copy an NDFS file
      */
-    public void copy(String srcf, String dstf) throws IOException {
-        if (FileUtil.copyContents(nfs, new File(srcf), new File(dstf), true)) {
+    public void copy(String srcf, String dstf, NutchConf nutchConf) throws IOException {
+        if (FileUtil.copyContents(nfs, new File(srcf), new File(dstf), true, nutchConf)) {
             System.out.println("Copied " + srcf + " to " + dstf);
         } else {
             System.out.println("Copy failed");
@@ -224,8 +224,9 @@
             return;
         }
 
+        NutchConf nutchConf = new NutchConf();
         int i = 0;
-        NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, i);
+        NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, i, nutchConf);
         try {
             NDFSShell tc = new NDFSShell(nfs);
 
@@ -244,7 +245,7 @@
             } else if ("-mv".equals(cmd)) {
                 tc.rename(argv[i++], argv[i++]);
             } else if ("-cp".equals(cmd)) {
-                tc.copy(argv[i++], argv[i++]);
+                tc.copy(argv[i++], argv[i++], nutchConf);
             } else if ("-rm".equals(cmd)) {
                 tc.delete(argv[i++]);
             } else if ("-du".equals(cmd)) {
Index: src/java/org/apache/nutch/fs/NutchFileSystem.java
===================================================================
--- src/java/org/apache/nutch/fs/NutchFileSystem.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/NutchFileSystem.java	(working copy)
@@ -45,7 +45,6 @@
     public static final Logger LOG = LogFormatter.getLogger("org.apache.nutch.util.NutchFileSystem");
 
     private static final HashMap NAME_TO_FS = new HashMap();
-  
     /**
      * Parse the cmd-line args, starting at i.  Remove consumed args
      * from array.  We expect param in the form:
@@ -53,7 +52,7 @@
      *
      * @deprecated use fs.default.name config option instead
      */
-    public static NutchFileSystem parseArgs(String argv[], int i) throws IOException {
+    public static NutchFileSystem parseArgs(String argv[], int i, NutchConf nutchConf) throws IOException {
         /**
         if (argv.length - i < 1) {
             throw new IOException("Must indicate filesystem type for NDFS");
@@ -65,12 +64,12 @@
         if ("-ndfs".equals(cmd)) {
             i++;
             InetSocketAddress addr = DataNode.createSocketAddr(argv[i++]);
-            nfs = new NDFSFileSystem(addr);
+            nfs = new NDFSFileSystem(addr, nutchConf);
         } else if ("-local".equals(cmd)) {
             i++;
-            nfs = new LocalFileSystem();
+            nfs = new LocalFileSystem(nutchConf);
         } else {
-            nfs = get();                          // using default
+            nfs = get(nutchConf);                          // using default
             LOG.info("No FS indicated, using default:"+nfs.getName());
 
         }
@@ -81,30 +80,26 @@
         return nfs;
     }
 
-
-    /** Returns the default filesystem implementation.*/
-    public static NutchFileSystem get() throws IOException {
-      return get(NutchConf.get());
-    }
-
     /** Returns the configured filesystem implementation.*/
     public static NutchFileSystem get(NutchConf conf) throws IOException {
-      return getNamed(conf.get("fs.default.name", "local"));
+      return getNamed(conf.get("fs.default.name", "local"),conf);
     }
 
+    protected NutchConf nutchConf;
     /** Returns a name for this filesystem, suitable to pass to {@link
      * NutchFileSystem#getNamed(String).*/
     public abstract String getName();
   
     /** Returns a named filesystem.  Names are either the string "local" or a
      * host:port pair, naming an NDFS name server.*/
-    public static NutchFileSystem getNamed(String name) throws IOException {
+    public static NutchFileSystem getNamed(String name, NutchConf nutchConf) throws IOException {
       NutchFileSystem fs = (NutchFileSystem)NAME_TO_FS.get(name);
+      int ioFileBufferSize = nutchConf.getInt("io.file.buffer.size", 4096);
       if (fs == null) {
         if ("local".equals(name)) {
-          fs = new LocalFileSystem();
+          fs = new LocalFileSystem(nutchConf);
         } else {
-          fs = new NDFSFileSystem(DataNode.createSocketAddr(name));
+          fs = new NDFSFileSystem(DataNode.createSocketAddr(name), nutchConf);
         }
         NAME_TO_FS.put(name, fs);
       }
@@ -127,7 +122,8 @@
     ///////////////////////////////////////////////////////////////
     /**
      */
-    public NutchFileSystem() {
+    public NutchFileSystem(NutchConf nutchConf) {
+        this.nutchConf = nutchConf;
     }
 
     /**
@@ -143,12 +139,16 @@
     public abstract String[][] getFileCacheHints(File f, long start, long len) throws IOException;
 
     /**
-     * Opens an NFSDataInputStream for the indicated File.
+     * Opens an NFSDataInputStream at the indicated File.
+     * @param f the file name to open
+     * @param overwrite if a file with this name already exists, then if true,
+     *   the file will be overwritten, and if false an error will be thrown.
+     * @param bufferSize the size of the buffer to be used.
      */
-    public NFSDataInputStream open(File f) throws IOException {
-      return open(f, NutchConf.get().getInt("io.file.buffer.size", 4096));
+    public NFSDataInputStream open(File f, int bufferSize) throws IOException {
+      return new NFSDataInputStream(this, f, bufferSize, this.nutchConf);
     }
-
+    
     /**
      * Opens an NFSDataInputStream at the indicated File.
      * @param f the file name to open
@@ -156,8 +156,8 @@
      *   the file will be overwritten, and if false an error will be thrown.
      * @param bufferSize the size of the buffer to be used.
      */
-    public NFSDataInputStream open(File f, int bufferSize) throws IOException {
-      return new NFSDataInputStream(this, f, bufferSize);
+    public NFSDataInputStream open(File f) throws IOException {
+      return new NFSDataInputStream(this, f, nutchConf);
     }
 
     /**
@@ -171,8 +171,7 @@
      * Files are overwritten by default.
      */
     public NFSDataOutputStream create(File f) throws IOException {
-      return create(f, true,
-                    NutchConf.get().getInt("io.file.buffer.size", 4096));
+      return create(f, true,this.nutchConf.getInt("io.file.buffer.size", 4096));
     }
 
     /**
@@ -184,7 +183,7 @@
      */
     public NFSDataOutputStream create(File f, boolean overwrite,
                                       int bufferSize) throws IOException {
-      return new NFSDataOutputStream(this, f, overwrite, bufferSize);
+      return new NFSDataOutputStream(this, f, overwrite, this.nutchConf);
     }
 
     /** Opens an OutputStream at the indicated File.
Index: src/java/org/apache/nutch/fs/NFSDataInputStream.java
===================================================================
--- src/java/org/apache/nutch/fs/NFSDataInputStream.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/NFSDataInputStream.java	(working copy)
@@ -40,7 +40,7 @@
     private Checksum sum = new CRC32();
     private int inSum;
 
-    public Checker(NutchFileSystem fs, File file)
+    public Checker(NutchFileSystem fs, File file, NutchConf nutchConf)
       throws IOException {
       super(fs.openRaw(file));
       
@@ -48,7 +48,7 @@
       this.file = file;
       File sumFile = fs.getChecksumFile(file);
       try {
-        this.sums = new NFSDataInputStream(fs.openRaw(sumFile));
+        this.sums = new NFSDataInputStream(fs.openRaw(sumFile), nutchConf);
         byte[] version = new byte[VERSION.length];
         sums.readFully(version);
         if (!Arrays.equals(version, VERSION))
@@ -210,20 +210,25 @@
     }
 
 }
-
-  public NFSDataInputStream(NutchFileSystem fs, File file) throws IOException {
-    this(fs, file, NutchConf.get().getInt("io.file.buffer.size", 4096));
-  }
-
-  public NFSDataInputStream(NutchFileSystem fs, File file, int bufferSize)
+  
+  
+  public NFSDataInputStream(NutchFileSystem fs, File file, int bufferSize, NutchConf nutchConf)
+  throws IOException {
+  super(null);
+  this.in = new Buffer(new PositionCache(new Checker(fs, file, nutchConf)), bufferSize);
+}
+  
+  
+  public NFSDataInputStream(NutchFileSystem fs, File file, NutchConf nutchConf)
     throws IOException {
     super(null);
-    this.in = new Buffer(new PositionCache(new Checker(fs, file)), bufferSize);
+    int bufferSize = nutchConf.getInt("io.file.buffer.size", 4096);
+    this.in = new Buffer(new PositionCache(new Checker(fs, file, nutchConf)), bufferSize);
   }
     
   /** Construct without checksums. */
-  public NFSDataInputStream(NFSInputStream in) throws IOException {
-    this(in, NutchConf.get().getInt("io.file.buffer.size", 4096));
+  public NFSDataInputStream(NFSInputStream in, NutchConf nutchConf) throws IOException {
+    this(in, nutchConf.getInt("io.file.buffer.size", 4096));
   }
   /** Construct without checksums. */
   public NFSDataInputStream(NFSInputStream in, int bufferSize)
Index: src/java/org/apache/nutch/fs/FileUtil.java
===================================================================
--- src/java/org/apache/nutch/fs/FileUtil.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/FileUtil.java	(working copy)
@@ -28,8 +28,8 @@
      * Delete a directory and all its contents.  If
      * we return false, the directory may be partially-deleted.
      */
-    public static boolean fullyDelete(File dir) throws IOException {
-        return fullyDelete(new LocalFileSystem(), dir);
+    public static boolean fullyDelete(File dir, NutchConf nutchConf) throws IOException {
+        return fullyDelete(new LocalFileSystem(nutchConf), dir);
     }
     public static boolean fullyDelete(NutchFileSystem nfs, File dir) throws IOException {
         // 20041022, xing.
@@ -43,7 +43,7 @@
      * Copy a file's contents to a new location.
      * Returns whether a target file was overwritten
      */
-    public static boolean copyContents(NutchFileSystem nfs, File src, File dst, boolean overwrite) throws IOException {
+    public static boolean copyContents(NutchFileSystem nfs, File src, File dst, boolean overwrite, NutchConf nutchConf) throws IOException {
         if (nfs.exists(dst) && !overwrite) {
             return false;
         }
@@ -57,7 +57,7 @@
             NFSInputStream in = nfs.openRaw(src);
             try {
                 NFSOutputStream out = nfs.createRaw(dst, true);
-                byte buf[] = new byte[NutchConf.get().getInt("io.file.buffer.size", 4096)];
+                byte buf[] = new byte[nutchConf.getInt("io.file.buffer.size", 4096)];
                 try {
                     int readBytes = in.read(buf);
 
@@ -77,7 +77,7 @@
             if (contents != null) {
                 for (int i = 0; i < contents.length; i++) {
                     File newDst = new File(dst, contents[i].getName());
-                    if (! copyContents(nfs, contents[i], newDst, overwrite)) {
+                    if (! copyContents(nfs, contents[i], newDst, overwrite, nutchConf)) {
                         return false;
                     }
                 }
@@ -90,7 +90,7 @@
      * Copy a file and/or directory and all its contents (whether
      * data or other files/dirs)
      */
-    public static void recursiveCopy(NutchFileSystem nfs, File src, File dst) throws IOException {
+    public static void recursiveCopy(NutchFileSystem nfs, File src, File dst, NutchConf nutchConf) throws IOException {
         //
         // Resolve the real target.
         //
@@ -107,7 +107,7 @@
             //
             // If the source is a file, then just copy the contents
             //
-            copyContents(nfs, src, dst, true);
+            copyContents(nfs, src, dst, true, nutchConf);
         } else {
             //
             // If the source is a dir, then we need to copy all the subfiles.
@@ -115,7 +115,7 @@
             nfs.mkdirs(dst);
             File contents[] = nfs.listFiles(src);
             for (int i = 0; i < contents.length; i++) {
-                recursiveCopy(nfs, contents[i], new File(dst, contents[i].getName()));
+                recursiveCopy(nfs, contents[i], new File(dst, contents[i].getName()), nutchConf);
             }
         }
     }
Index: src/java/org/apache/nutch/fs/NFSDataOutputStream.java
===================================================================
--- src/java/org/apache/nutch/fs/NFSDataOutputStream.java	(revision 359225)
+++ src/java/org/apache/nutch/fs/NFSDataOutputStream.java	(working copy)
@@ -29,29 +29,27 @@
   /** Store checksums for data. */
   private static class Summer extends FilterOutputStream {
 
-    private final int bytesPerSum
-      = NutchConf.get().getInt("io.bytes.per.checksum", 512);
-
     private NFSDataOutputStream sums;
     private Checksum sum = new CRC32();
     private int inSum;
+    private int bytesPerSum;
 
-    public Summer(NutchFileSystem fs, File file, boolean overwrite)
+    public Summer(NutchFileSystem fs, File file, boolean overwrite, NutchConf nutchConf)
       throws IOException {
       super(fs.createRaw(file, overwrite));
-
+      this.bytesPerSum = nutchConf.getInt("io.bytes.per.checksum", 512);
       this.sums =
-        new NFSDataOutputStream(fs.createRaw(fs.getChecksumFile(file), true));
+        new NFSDataOutputStream(fs.createRaw(fs.getChecksumFile(file), true), nutchConf);
 
       sums.write(CHECKSUM_VERSION, 0, CHECKSUM_VERSION.length);
-      sums.writeInt(bytesPerSum);
+      sums.writeInt(this.bytesPerSum);
     }
 
     public void write(byte b[], int off, int len) throws IOException {
       int summed = 0;
       while (summed < len) {
 
-        int goal = bytesPerSum - inSum;
+        int goal = this.bytesPerSum - inSum;
         int inBuf = len - summed;
         int toSum = inBuf <= goal ? inBuf : goal;
 
@@ -59,7 +57,7 @@
         summed += toSum;
 
         inSum += toSum;
-        if (inSum == bytesPerSum) {
+        if (inSum == this.bytesPerSum) {
           writeSum();
         }
       }
@@ -124,15 +122,15 @@
   }
 
   public NFSDataOutputStream(NutchFileSystem fs, File file,
-                             boolean overwrite, int bufferSize)
+                             boolean overwrite, NutchConf nutchConf)
     throws IOException {
-    super(new Buffer(new PositionCache(new Summer(fs, file, overwrite)),
-                     bufferSize));
+    super(new Buffer(new PositionCache(new Summer(fs, file, overwrite, nutchConf)),
+            nutchConf.getInt("io.file.buffer.size", 4096)));
   }
 
   /** Construct without checksums. */
-  public NFSDataOutputStream(NFSOutputStream out) throws IOException {
-    this(out, NutchConf.get().getInt("io.file.buffer.size", 4096));
+  public NFSDataOutputStream(NFSOutputStream out, NutchConf nutchConf) throws IOException {
+    this(out, nutchConf.getInt("io.file.buffer.size", 4096));
   }
 
   /** Construct without checksums. */
Index: src/java/org/apache/nutch/crawl/CrawlDbReader.java
===================================================================
--- src/java/org/apache/nutch/crawl/CrawlDbReader.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/CrawlDbReader.java	(working copy)
@@ -157,8 +157,8 @@
     JobClient.runJob(job);
 
     // reading the result
-    NutchFileSystem fileSystem = NutchFileSystem.get();
-    SequenceFile.Reader[] readers = SequenceFileOutputFormat.getReaders(fileSystem, tmpFolder);
+    NutchFileSystem fileSystem = NutchFileSystem.get(config);
+    SequenceFile.Reader[] readers = SequenceFileOutputFormat.getReaders(config, tmpFolder);
 
     UTF8 key = new UTF8();
     LongWritable value = new LongWritable();
@@ -210,7 +210,7 @@
     NutchFileSystem fs = NutchFileSystem.get(config);
     UTF8 key = new UTF8(url);
     CrawlDatum val = new CrawlDatum();
-    MapFile.Reader[] readers = MapFileOutputFormat.getReaders(fs, new File(crawlDb, CrawlDatum.DB_DIR_NAME));
+    MapFile.Reader[] readers = MapFileOutputFormat.getReaders(fs, new File(crawlDb, CrawlDatum.DB_DIR_NAME), config);
     Writable res = MapFileOutputFormat.getEntry(readers, new HashPartitioner(), key, val);
     System.out.println("URL: " + url);
     if (res != null) {
@@ -254,7 +254,7 @@
     }
     String param = null;
     String crawlDb = args[0];
-    NutchConf conf = NutchConf.get();
+    NutchConf conf = new NutchConf();
     for (int i = 1; i < args.length; i++) {
       if (args[i].equals("-stats")) {
         dbr.processStatJob(crawlDb, conf);
Index: src/java/org/apache/nutch/crawl/LinkDb.java
===================================================================
--- src/java/org/apache/nutch/crawl/LinkDb.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/LinkDb.java	(working copy)
@@ -182,7 +182,7 @@
   }
 
   public static void main(String[] args) throws Exception {
-    LinkDb linkDb = new LinkDb(NutchConf.get());
+    LinkDb linkDb = new LinkDb(new NutchConf());
     
     if (args.length < 2) {
       System.err.println("Usage: <linkdb> <segments>");
Index: src/java/org/apache/nutch/crawl/Crawl.java
===================================================================
--- src/java/org/apache/nutch/crawl/Crawl.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/Crawl.java	(working copy)
@@ -22,6 +22,7 @@
 import java.text.*;
 import java.util.logging.*;
 
+import org.apache.lucene.index.IndexWriter;
 import org.apache.nutch.io.*;
 import org.apache.nutch.fetcher.Fetcher;
 import org.apache.nutch.fs.*;
@@ -41,9 +42,6 @@
       (new Date(System.currentTimeMillis()));
   }
 
-  static {
-    NutchConf.get().addConfResource("crawl-tool.xml");
-  }
 
   /* Perform complete crawling and indexing given a set of root urls. */
   public static void main(String args[]) throws Exception {
@@ -53,7 +51,9 @@
       return;
     }
 
-    JobConf conf = new JobConf(NutchConf.get());
+    NutchConf nutchConf = new NutchConf();
+    nutchConf.addConfResource("crawl-tool.xml");
+    JobConf conf = new JobConf(nutchConf);
     //conf.addConfResource("crawl-tool.xml");
 
     File rootUrlDir = null;
@@ -120,7 +120,7 @@
     // index, dedup & merge
     new Indexer(conf).index(indexes, crawlDb, linkDb, fs.listFiles(segments));
     new DeleteDuplicates(conf).dedup(new File[] { indexes });
-    new IndexMerger(fs, fs.listFiles(indexes), index, tmpDir).merge();
+    new IndexMerger(fs, fs.listFiles(indexes), index, tmpDir, nutchConf).merge();
 
     LOG.info("crawl finished: " + dir);
   }
Index: src/java/org/apache/nutch/crawl/Injector.java
===================================================================
--- src/java/org/apache/nutch/crawl/Injector.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/Injector.java	(working copy)
@@ -35,11 +35,14 @@
 
   /** Normalize and filter injected urls. */
   public static class InjectMapper implements Mapper {
-    private UrlNormalizer urlNormalizer = UrlNormalizerFactory.getNormalizer();
+    private UrlNormalizer urlNormalizer;
     private float interval;
+    private JobConf jobConf;
 
     public void configure(JobConf job) {
+      urlNormalizer = UrlNormalizerFactory.getNormalizer(job);
       interval = job.getFloat("db.default.fetch.interval", 30f);
+      this.jobConf = job;
     }
 
     public void map(WritableComparable key, Writable val,
@@ -47,9 +50,10 @@
       throws IOException {
       UTF8 value = (UTF8)val;
       String url = value.toString();              // value is line of text
+      System.out.println("url: " +url);
       try {
         url = urlNormalizer.normalize(url);       // normalize the url
-        url = URLFilters.filter(url);             // filter the url
+        url = new URLFilters(this.jobConf).filter(url);             // filter the url
       } catch (Exception e) {
         LOG.warning("Skipping " +url+":"+e);
         url = null;
@@ -116,7 +120,7 @@
   }
 
   public static void main(String[] args) throws Exception {
-    Injector injector = new Injector(NutchConf.get());
+    Injector injector = new Injector(new NutchConf());
     
     if (args.length < 2) {
       System.err.println("Usage: Injector <crawldb> <url_dir>");
Index: src/java/org/apache/nutch/crawl/CrawlDb.java
===================================================================
--- src/java/org/apache/nutch/crawl/CrawlDb.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/CrawlDb.java	(working copy)
@@ -89,7 +89,7 @@
   }
 
   public static void main(String[] args) throws Exception {
-    CrawlDb crawlDb = new CrawlDb(NutchConf.get());
+    CrawlDb crawlDb = new CrawlDb(new NutchConf());
     
     if (args.length < 2) {
       System.err.println("Usage: <crawldb> <segment>");
Index: src/java/org/apache/nutch/crawl/LinkDbReader.java
===================================================================
--- src/java/org/apache/nutch/crawl/LinkDbReader.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/LinkDbReader.java	(working copy)
@@ -37,10 +37,12 @@
   private NutchFileSystem fs;
   private File directory;
   private MapFile.Reader[] readers;
+  private NutchConf nutchConf;
 
-  public LinkDbReader(NutchFileSystem fs, File directory) {
+  public LinkDbReader(NutchFileSystem fs, File directory, NutchConf nutchConf) {
     this.fs = fs;
     this.directory = directory;
+    this.nutchConf = nutchConf;
   }
 
   public String[] getAnchors(UTF8 url) throws IOException {
@@ -55,7 +57,7 @@
     synchronized (this) {
       if (readers == null) {
         readers = MapFileOutputFormat.getReaders
-          (fs, new File(directory, LinkDb.CURRENT_NAME));
+          (fs, new File(directory, LinkDb.CURRENT_NAME), this.nutchConf);
       }
     }
     
@@ -90,11 +92,11 @@
       System.err.println("\t-url <url>\tprint information about <url> to System.out");
       return;
     }
-    
+    NutchConf nutchConf = new NutchConf();
     if (args[1].equals("-dump")) {
-      LinkDbReader.processDumpJob(args[0], args[2], NutchConf.get());
+      LinkDbReader.processDumpJob(args[0], args[2], nutchConf);
     } else if (args[1].equals("-url")) {
-      LinkDbReader dbr = new LinkDbReader(NutchFileSystem.get(), new File(args[0]));
+      LinkDbReader dbr = new LinkDbReader(NutchFileSystem.get(new NutchConf()), new File(args[0]), nutchConf);
       Inlinks links = dbr.getInlinks(new UTF8(args[2]));
       if (links == null) {
         System.out.println(" - no link information.");
Index: src/java/org/apache/nutch/crawl/Generator.java
===================================================================
--- src/java/org/apache/nutch/crawl/Generator.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/Generator.java	(working copy)
@@ -259,7 +259,7 @@
 
     if (topN != Long.MAX_VALUE)
       LOG.info("topN: " + topN);
-    Generator gen = new Generator(NutchConf.get());
+    Generator gen = new Generator(new NutchConf());
     gen.generate(dbDir, segmentsDir, numFetchers, topN, curTime);
   }
 }
Index: src/java/org/apache/nutch/crawl/TextProfileSignature.java
===================================================================
--- src/java/org/apache/nutch/crawl/TextProfileSignature.java	(revision 367309)
+++ src/java/org/apache/nutch/crawl/TextProfileSignature.java	(working copy)
@@ -157,7 +157,7 @@
   
   public static void main(String[] args) throws Exception {
     TextProfileSignature sig = new TextProfileSignature();
-    sig.setConf(NutchConf.get());
+    sig.setConf(new NutchConf());
     HashMap res = new HashMap();
     File[] files = new File(args[0]).listFiles();
     for (int i = 0; i < files.length; i++) {
Index: src/java/org/apache/nutch/parse/ParsePluginsReader.java
===================================================================
--- src/java/org/apache/nutch/parse/ParsePluginsReader.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParsePluginsReader.java	(working copy)
@@ -74,7 +74,7 @@
    * @throws Exception
    *             If any parsing error occurs.
    */
-  public ParsePluginList parse() {
+  public ParsePluginList parse(NutchConf nutchConf) {
     
     ParsePluginList pList = new ParsePluginList();
     
@@ -96,8 +96,8 @@
         return pList;
       }
     } else {
-      ppInputStream = NutchConf.get().getConfResourceAsInputStream(
-                          NutchConf.get().get(PP_FILE_PROP));
+      ppInputStream = nutchConf.getConfResourceAsInputStream(
+                          nutchConf.get(PP_FILE_PROP));
     }
     
     inputSource = new InputSource(ppInputStream);
@@ -197,7 +197,7 @@
       reader.setFParsePluginsFile(parsePluginFile);
     }
     
-    ParsePluginList prefs = reader.parse();
+    ParsePluginList prefs = reader.parse(new NutchConf());
     
     for (Iterator i = prefs.getSupportedMimeTypes().iterator(); i.hasNext();) {
       String mimeType = (String) i.next();
Index: src/java/org/apache/nutch/parse/ParseOutputFormat.java
===================================================================
--- src/java/org/apache/nutch/parse/ParseOutputFormat.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParseOutputFormat.java	(working copy)
@@ -31,11 +31,14 @@
 /* Parse content in a segment. */
 public class ParseOutputFormat implements OutputFormat {
 
-  private UrlNormalizer urlNormalizer = UrlNormalizerFactory.getNormalizer();
+  private UrlNormalizer urlNormalizer;
+  private JobConf jobConf;
 
   public RecordWriter getRecordWriter(NutchFileSystem fs, JobConf job,
                                       String name) throws IOException {
 
+    this.jobConf = job;
+    urlNormalizer = UrlNormalizerFactory.getNormalizer(job);
     final float interval = job.getFloat("db.default.fetch.interval", 30f);
     final float extscore = job.getFloat("db.score.link.external", 1.0f);
     
@@ -92,7 +95,7 @@
             String toUrl = links[i].getToUrl();
             try {
               toUrl = urlNormalizer.normalize(toUrl); // normalize the url
-              toUrl = URLFilters.filter(toUrl);   // filter the url
+              toUrl = new URLFilters(jobConf).filter(toUrl);   // filter the url
             } catch (Exception e) {
               toUrl = null;
             }
Index: src/java/org/apache/nutch/parse/ParseData.java
===================================================================
--- src/java/org/apache/nutch/parse/ParseData.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParseData.java	(working copy)
@@ -37,14 +37,16 @@
   private Outlink[] outlinks;
   private ContentProperties metadata;
   private ParseStatus status;
-
+  private int maxOutlinkPerPage;
+  
   public ParseData() {}
 
-  public ParseData(ParseStatus status, String title, Outlink[] outlinks, ContentProperties metadata) {
+  public ParseData(ParseStatus status, String title, Outlink[] outlinks, ContentProperties metadata, NutchConf nutchConf) {
     this.status = status;
     this.title = title;
     this.outlinks = outlinks;
     this.metadata = metadata;
+    this.maxOutlinkPerPage = nutchConf.getInt("db.max.outlinks.per.page", 100);
   }
 
   //
@@ -85,14 +87,12 @@
 
     int totalOutlinks = in.readInt();             // read outlinks
     // XXX remove the dependency on static NutchConf.get(). How?
-    int outlinksToRead =
-      Math.min(NutchConf.get().getInt("db.max.outlinks.per.page", 100),
-                                  totalOutlinks);
-    outlinks = new Outlink[outlinksToRead];
-    for (int i = 0; i < outlinksToRead; i++) {
+
+    outlinks = new Outlink[totalOutlinks];
+    for (int i = 0; i < totalOutlinks; i++) {
       outlinks[i] = Outlink.read(in);
     }
-    for (int i = outlinksToRead; i < totalOutlinks; i++) {
+    for (int i = totalOutlinks; i < totalOutlinks; i++) {
       Outlink.skip(in);
     }
     
@@ -168,7 +168,8 @@
       return;
     }
 
-    NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, 0);
+    NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, 0, nutchConf);
     try {
       int recno = Integer.parseInt(argv[0]);
       String segment = argv[1];
@@ -176,7 +177,7 @@
       File file = new File(segment, DIR_NAME);
       System.out.println("Reading from file: " + file);
 
-      ArrayFile.Reader parses = new ArrayFile.Reader(nfs, file.toString());
+      ArrayFile.Reader parses = new ArrayFile.Reader(nfs, file.toString(), nutchConf);
 
       ParseData parseDatum = new ParseData();
       parses.get(recno, parseDatum);
Index: src/java/org/apache/nutch/parse/HtmlParseFilter.java
===================================================================
--- src/java/org/apache/nutch/parse/HtmlParseFilter.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/HtmlParseFilter.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.nutch.parse;
 
 import org.apache.nutch.protocol.Content;
+import org.apache.nutch.util.NutchConfigurable;
 
 import org.w3c.dom.DocumentFragment;
 
@@ -24,7 +25,7 @@
  * metadata to HTML parses.  All plugins found which implement this extension
  * point are run sequentially on the parse.
  */
-public interface HtmlParseFilter {
+public interface HtmlParseFilter extends NutchConfigurable {
   /** The name of the extension point. */
   final static String X_POINT_ID = HtmlParseFilter.class.getName();
 
Index: src/java/org/apache/nutch/parse/ParseUtil.java
===================================================================
--- src/java/org/apache/nutch/parse/ParseUtil.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParseUtil.java	(working copy)
@@ -21,6 +21,7 @@
 // Nutch Imports
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 
 /**
@@ -37,9 +38,12 @@
   /* our log stream */
   public static final Logger LOG = LogFormatter.getLogger(ParseUtil.class
           .getName());
+  private NutchConf nutchConf;
   
   /** No public constructor */
-  private ParseUtil() { }
+  public ParseUtil(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+  }
   
   /**
    * Performs a parse by iterating through a List of preferred {@Parser}s
@@ -51,11 +55,11 @@
    * @return A {@link Parse} object containing the parsed data.
    * @throws ParseException If no suitable parser is found to perform the parse.
    */
-  public final static Parse parse(Content content) throws ParseException {
+  public  Parse parse(Content content) throws ParseException {
     Parser[] parsers = null;
     
     try {
-      parsers = ParserFactory.getParsers(content.getContentType(), "");
+      parsers = new ParserFactory(this.nutchConf).getParsers(content.getContentType(), "");
     } catch (ParserNotFound e) {
       LOG.warning("No suitable parser found when trying to parse content " +
                   content);
@@ -74,7 +78,7 @@
     LOG.warning("Unable to successfully parse content " + content.getUrl() +
                 " of type " + content.getContentType());
 
-    return new ParseStatus().getEmptyParse();
+    return new ParseStatus().getEmptyParse(this.nutchConf);
   }
   
   /**
@@ -94,13 +98,13 @@
    * @throws ParseException If there is no suitable {@link Parser} found
    *                        to perform the parse.
    */
-  public final static Parse parseByParserId(String parserId, Content content)
+  public Parse parseByParserId(String parserId, Content content)
   throws ParseException {
     Parse parse = null;
     Parser p = null;
     
     try {
-      p = ParserFactory.getParserById(parserId);
+      p = new ParserFactory(this.nutchConf).getParserById(parserId);
     } catch (ParserNotFound e) {
       LOG.warning("No suitable parser found when trying to parse content " +
                   content);
@@ -114,7 +118,7 @@
     } else {
       LOG.warning("Unable to successfully parse content " + content.getUrl() +
                   " of type " + content.getContentType());
-      return new ParseStatus().getEmptyParse();
+      return new ParseStatus().getEmptyParse(this.nutchConf);
     }
   }
   
Index: src/java/org/apache/nutch/parse/ParseStatus.java
===================================================================
--- src/java/org/apache/nutch/parse/ParseStatus.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParseStatus.java	(working copy)
@@ -13,6 +13,7 @@
 import org.apache.nutch.io.VersionedWritable;
 import org.apache.nutch.io.WritableUtils;
 import org.apache.nutch.protocol.ContentProperties;
+import org.apache.nutch.util.NutchConf;
 
 /**
  * @author Andrzej Bialecki &lt;ab@getopt.org&gt;
@@ -163,8 +164,8 @@
   /** A convenience method. Creates an empty Parse instance,
    * which returns this status.
    */
-  public Parse getEmptyParse() {
-    return new EmptyParseImpl(this);
+  public Parse getEmptyParse(NutchConf nutchConf) {
+    return new EmptyParseImpl(this, nutchConf);
   }
   
   public String toString() {
@@ -230,8 +231,9 @@
     
     private ParseData data = null;
     
-    public EmptyParseImpl(ParseStatus status) {
-      data = new ParseData(status, "", new Outlink[0], new ContentProperties());
+    public EmptyParseImpl(ParseStatus status, NutchConf nutchConf) {
+        //TODO mb: empty parse - 0 outlinks per page or default.xml
+      data = new ParseData(status, "", new Outlink[0], new ContentProperties(), nutchConf);
     }
     
     public ParseData getData() {
Index: src/java/org/apache/nutch/parse/ParseText.java
===================================================================
--- src/java/org/apache/nutch/parse/ParseText.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParseText.java	(working copy)
@@ -80,14 +80,15 @@
       return;
     }
 
-    NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, 0);
+    NutchConf nutchConf = new NutchConf();
+    NutchFileSystem nfs = NutchFileSystem.parseArgs(argv, 0, nutchConf);
     try {
       int recno = Integer.parseInt(argv[0]);
       String segment = argv[1];
       String filename = new File(segment, ParseText.DIR_NAME).getPath();
 
       ParseText parseText = new ParseText();
-      ArrayFile.Reader parseTexts = new ArrayFile.Reader(nfs, filename);
+      ArrayFile.Reader parseTexts = new ArrayFile.Reader(nfs, filename, nutchConf);
 
       parseTexts.get(recno, parseText);
       System.out.println("Retrieved " + recno + " from file " + filename);
Index: src/java/org/apache/nutch/parse/OutlinkExtractor.java
===================================================================
--- src/java/org/apache/nutch/parse/OutlinkExtractor.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/OutlinkExtractor.java	(working copy)
@@ -21,6 +21,7 @@
 import java.util.logging.Logger;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.oro.text.regex.MatchResult;
 import org.apache.oro.text.regex.Pattern;
 import org.apache.oro.text.regex.PatternCompiler;
@@ -65,8 +66,8 @@
    * 
    * @return Array of <code>Outlink</code>s within found in plainText
    */
-  public static Outlink[] getOutlinks(final String plainText) {
-    return OutlinkExtractor.getOutlinks(plainText, "");
+  public static Outlink[] getOutlinks(final String plainText, NutchConf nutchConf) {
+    return OutlinkExtractor.getOutlinks(plainText, "", nutchConf);
   }
 
   /**
@@ -78,7 +79,7 @@
    * 
    * @return Array of <code>Outlink</code>s within found in plainText
    */
-  public static Outlink[] getOutlinks(final String plainText, String anchor) {
+  public static Outlink[] getOutlinks(final String plainText, String anchor, NutchConf nutchConf) {
     long start = System.currentTimeMillis();
     final List outlinks = new ArrayList();
 
@@ -105,7 +106,7 @@
         }
         result = matcher.getMatch();
         url = result.group(0);
-        outlinks.add(new Outlink(url, anchor));
+        outlinks.add(new Outlink(url, anchor, nutchConf));
       }
     } catch (Exception ex) {
       // if the matcher fails (perhaps a malformed URL) we just log it and move on
Index: src/java/org/apache/nutch/parse/ParserChecker.java
===================================================================
--- src/java/org/apache/nutch/parse/ParserChecker.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParserChecker.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.nutch.parse;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.io.UTF8;
@@ -70,7 +71,8 @@
 
     LOG.info("fetching: "+url);
 
-    Protocol protocol = ProtocolFactory.getProtocol(url);
+    NutchConf nutchConf = new NutchConf();
+    Protocol protocol = new ProtocolFactory(nutchConf).getProtocol(url);
     Content content = protocol.getProtocolOutput(new UTF8(url), new CrawlDatum()).getContent();
 
     if (force) {
@@ -87,7 +89,7 @@
     LOG.info("parsing: "+url);
     LOG.info("contentType: "+contentType);
 
-    Parse parse = ParseUtil.parse(content);
+    Parse parse = new ParseUtil(nutchConf).parse(content);
 
     System.out.print("---------\nParseData\n---------\n");
     System.out.print(parse.getData().toString());
Index: src/java/org/apache/nutch/parse/ParserFactory.java
===================================================================
--- src/java/org/apache/nutch/parse/ParserFactory.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParserFactory.java	(working copy)
@@ -29,10 +29,11 @@
 import org.apache.nutch.plugin.PluginRepository;
 import org.apache.nutch.plugin.PluginRuntimeException;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.util.mime.MimeType;
 import org.apache.nutch.util.mime.MimeTypeException;
 
-
+//TODO mb: complete refactoring
 /** Creates and caches {@link Parser} plugins.*/
 public final class ParserFactory {
   
@@ -40,35 +41,35 @@
           LogFormatter.getLogger(ParserFactory.class.getName());
   
   /** Wildcard for default plugins. */
-  public static final String DEFAULT_PLUGIN = "*";
-
-  /** Extension point. */
-  private static final ExtensionPoint X_POINT =
-          PluginRepository.getInstance().getExtensionPoint(Parser.X_POINT_ID);
+  public  final String DEFAULT_PLUGIN = "*";
   
-  /** List of parser plugins. */
-  private static final ParsePluginList PARSE_PLUGIN_LIST =
-          new ParsePluginsReader().parse();
-  
   /** Empty extension list for caching purposes. */
-  private static final List EMPTY_EXTENSION_LIST = Collections.EMPTY_LIST;
+  private final List EMPTY_EXTENSION_LIST = Collections.EMPTY_LIST;
   
-  static {
-    if (X_POINT == null) {
-      throw new RuntimeException("x point "+Parser.X_POINT_ID+" not found.");
-    }
-    if (PARSE_PLUGIN_LIST == null) {
-      throw new RuntimeException("Parse Plugins preferences could not be loaded.");
-    }
-  }
-  
   //cache mapping mimeType->List of Extensions
-  private static final Hashtable CACHE = new Hashtable();
+  private Hashtable CACHE = new Hashtable();
   
   //cache mapping parser plugin id->Parser instance
-  private static final Hashtable PARSER_CACHE = new Hashtable();
+  private Hashtable PARSER_CACHE = new Hashtable();
+
+  private NutchConf nutchConf;
+
+ private ExtensionPoint extensionPoint;
+
+ private ParsePluginList parsePluginList;
   
-  private ParserFactory() {}                      // no public ctor
+  public ParserFactory(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+      this.extensionPoint = nutchConf.getPluginRepository().getExtensionPoint(Parser.X_POINT_ID);
+      this.parsePluginList = new ParsePluginsReader().parse(nutchConf);
+      
+      if (this.extensionPoint == null) {
+          throw new RuntimeException("x point "+Parser.X_POINT_ID+" not found.");
+        }
+        if (this.parsePluginList == null) {
+          throw new RuntimeException("Parse Plugins preferences could not be loaded.");
+        }
+  }                      
   
 
   /**
@@ -86,7 +87,7 @@
    * the end of the url's path is used.  If neither of these match, then the
    * first plugin whose "pathSuffix" is the empty string is used.
    */
-  public static Parser getParser(String contentType, String url)
+  public  Parser getParser(String contentType, String url)
   throws ParserNotFound {
     
     Parser[] parsers = getParsers(contentType, url);
@@ -132,7 +133,7 @@
    *         consist of two {@link Parser} interfaces,
    *         <code>[parse-html, parse-rtf]</code>.
    */
-  public static Parser[] getParsers(String contentType, String url)
+  public  Parser[] getParsers(String contentType, String url)
   throws ParserNotFound {
     
     List parsers = null;
@@ -165,6 +166,7 @@
         }
         parsers.add(p);
       } catch (PluginRuntimeException e) {
+          e.printStackTrace();
         LOG.warning("ParserFactory:PluginRuntimeException when "
                   + "initializing parser plugin "
                   + ext.getDescriptor().getPluginId()
@@ -187,7 +189,7 @@
    * @throws ParserNotFound If the Parser is not found (i.e., registered with the extension point), or if the there a {@link PluginRuntimeException}
    * instantiating the {@link Parser}.
    */
-  public static Parser getParserById(String parserId) throws ParserNotFound{
+  public  Parser getParserById(String parserId) throws ParserNotFound{
       //first check the cache
       
       if(PARSER_CACHE.get(parserId) != null){
@@ -197,7 +199,7 @@
           //get the list of registered parsing extensions
           //then find the right one by Id
           
-          Extension[] extensions = X_POINT.getExtensions();
+          Extension[] extensions = this.extensionPoint.getExtensions();
           Extension parserExt = getExtensionById(extensions,parserId);
           
           if (parserExt == null) {
@@ -230,7 +232,7 @@
    * @return List - List of extensions to be used for this contentType.
    *                If none, returns null.
    */
-  protected static List getExtensions(String contentType) {
+  protected  List getExtensions(String contentType) {
     
     // First of all, tries to clean the content-type
     String type = null;
@@ -272,19 +274,19 @@
    * @return List - List of extensions to be used for this contentType.
    *                If none, returns null.
    */
-  private static List findExtensions(String contentType){
+  private  List findExtensions(String contentType){
     
-    Extension[] extensions = X_POINT.getExtensions();
+    Extension[] extensions = this.extensionPoint.getExtensions();
     
     // Look for a preferred plugin.
-    List parsePluginList = PARSE_PLUGIN_LIST.getPluginList(contentType);
+    List parsePluginList = this.parsePluginList.getPluginList(contentType);
     List extensionList = matchExtensions(parsePluginList, extensions, contentType);
     if (extensionList != null) {
       return extensionList;
     }
     
     // If none found, look for a default plugin.
-    parsePluginList = PARSE_PLUGIN_LIST.getPluginList(DEFAULT_PLUGIN);
+    parsePluginList = this.parsePluginList.getPluginList(DEFAULT_PLUGIN);
     return matchExtensions(parsePluginList, extensions, DEFAULT_PLUGIN);
   }
   
@@ -302,7 +304,7 @@
    * @return List - List of extensions to be used for this contentType.
    *                If none, returns null.
    */
-  private static List matchExtensions(List plugins,
+  private  List matchExtensions(List plugins,
                                       Extension[] extensions,
                                       String contentType) {
     
@@ -390,13 +392,13 @@
     }
   }
 
-  private static boolean match(Extension extension, String id, String type) {
+  private  boolean match(Extension extension, String id, String type) {
     return (id.equals(extension.getDescriptor().getPluginId())) &&
     (type.equals(extension.getAttribute("contentType")) ||
         (type.equals(DEFAULT_PLUGIN))); 
   }
   
-  private static Extension getExtensionByIdAndType(Extension[] extList,
+  private  Extension getExtensionByIdAndType(Extension[] extList,
                                                    String plugId,
                                                    String contentType) {
     for (int i = 0; i < extList.length; i++) {
@@ -407,7 +409,7 @@
     return null;
   }
   
-  private static Extension getExtensionById(Extension[] extList, String plugId) {
+  private  Extension getExtensionById(Extension[] extList, String plugId) {
     for(int i = 0; i < extList.length; i++){
       if(plugId.equals(extList[i].getDescriptor().getPluginId())){
         return extList[i];
Index: src/java/org/apache/nutch/parse/Outlink.java
===================================================================
--- src/java/org/apache/nutch/parse/Outlink.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/Outlink.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.nutch.io.*;
 import org.apache.nutch.net.UrlNormalizerFactory;
+import org.apache.nutch.util.NutchConf;
 
 /* An outgoing link from a page. */
 public class Outlink implements Writable {
@@ -30,8 +31,8 @@
 
   public Outlink() {}
 
-  public Outlink(String toUrl, String anchor) throws MalformedURLException {
-    this.toUrl = UrlNormalizerFactory.getNormalizer().normalize(toUrl);
+  public Outlink(String toUrl, String anchor, NutchConf nutchConf) throws MalformedURLException {
+    this.toUrl = UrlNormalizerFactory.getNormalizer(nutchConf).normalize(toUrl);
     this.anchor = anchor;
   }
 
Index: src/java/org/apache/nutch/parse/HtmlParseFilters.java
===================================================================
--- src/java/org/apache/nutch/parse/HtmlParseFilters.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/HtmlParseFilters.java	(working copy)
@@ -18,34 +18,37 @@
 
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.plugin.*;
+import org.apache.nutch.util.NutchConf;
 
 import org.w3c.dom.DocumentFragment;
 
 /** Creates and caches {@link HtmlParseFilter} implementing plugins.*/
 public class HtmlParseFilters {
 
-  private static final HtmlParseFilter[] CACHE;
-  static {
-    try {
-      ExtensionPoint point = PluginRepository.getInstance()
-        .getExtensionPoint(HtmlParseFilter.X_POINT_ID);
-      if (point == null)
-        throw new RuntimeException(HtmlParseFilter.X_POINT_ID+" not found.");
-      Extension[] extensions = point.getExtensions();
-      CACHE = new HtmlParseFilter[extensions.length];
-      for (int i = 0; i < extensions.length; i++) {
-        Extension extension = extensions[i];
-        CACHE[i] = (HtmlParseFilter)extension.getExtensionInstance();
-      }
-    } catch (PluginRuntimeException e) {
-      throw new RuntimeException(e);
-    }
-  }
+  private HtmlParseFilter[] CACHE;
+  
+  private NutchConf nutchConf;
 
-  private  HtmlParseFilters() {}                  // no public ctor
+  public  HtmlParseFilters(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+      try {
+          ExtensionPoint point = nutchConf.getPluginRepository()
+            .getExtensionPoint(HtmlParseFilter.X_POINT_ID);
+          if (point == null)
+            throw new RuntimeException(HtmlParseFilter.X_POINT_ID+" not found.");
+          Extension[] extensions = point.getExtensions();
+          CACHE = new HtmlParseFilter[extensions.length];
+          for (int i = 0; i < extensions.length; i++) {
+            Extension extension = extensions[i];
+            CACHE[i] = (HtmlParseFilter)extension.getExtensionInstance();
+          }
+        } catch (PluginRuntimeException e) {
+          throw new RuntimeException(e);
+        }
+  }                  
 
   /** Run all defined filters. */
-  public static Parse filter(Content content, Parse parse, HTMLMetaTags metaTags, DocumentFragment doc) {
+  public  Parse filter(Content content, Parse parse, HTMLMetaTags metaTags, DocumentFragment doc) {
 
     for (int i = 0 ; i < CACHE.length; i++) {
       parse = CACHE[i].filter(content, parse, metaTags, doc);
Index: src/java/org/apache/nutch/parse/Parser.java
===================================================================
--- src/java/org/apache/nutch/parse/Parser.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/Parser.java	(working copy)
@@ -17,12 +17,13 @@
 package org.apache.nutch.parse;
 
 import org.apache.nutch.protocol.Content;
+import org.apache.nutch.util.NutchConfigurable;
 
 /** A parser for content generated by a {@link org.apache.nutch.protocol.Protocol}
  * implementation.  This interface is implemented by extensions.  Nutch's core
  * contains no page parsing code.
  */
-public interface Parser {
+public interface Parser extends NutchConfigurable{
   /** The name of the extension point. */
   public final static String X_POINT_ID = Parser.class.getName();
 
Index: src/java/org/apache/nutch/parse/ParseSegment.java
===================================================================
--- src/java/org/apache/nutch/parse/ParseSegment.java	(revision 367309)
+++ src/java/org/apache/nutch/parse/ParseSegment.java	(working copy)
@@ -33,9 +33,9 @@
 
   public static final Logger LOG =
     LogFormatter.getLogger(Parser.class.getName());
+//TODO mb delete?
+  //public ParseSegment() { super(NutchConf.get()); }
 
-  public ParseSegment() { super(NutchConf.get()); }
-
   public ParseSegment(NutchConf conf) {
     super(conf);
   }
@@ -52,7 +52,7 @@
     Parse parse = null;
     ParseStatus status;
     try {
-      parse = ParseUtil.parse(content);
+      parse = new ParseUtil(getConf()).parse(content);
       status = parse.getData().getStatus();
     } catch (Exception e) {
       status = new ParseStatus(e);
@@ -109,7 +109,7 @@
       
     segment = new File(args[0]);
 
-    ParseSegment parseSegment = new ParseSegment(NutchConf.get());
+    ParseSegment parseSegment = new ParseSegment(new NutchConf());
     parseSegment.parse(segment);
   }
 }
Index: src/java/org/apache/nutch/ontology/OntologyFactory.java
===================================================================
--- src/java/org/apache/nutch/ontology/OntologyFactory.java	(revision 359225)
+++ src/java/org/apache/nutch/ontology/OntologyFactory.java	(working copy)
@@ -31,11 +31,8 @@
   public final static Logger LOG =
     LogFormatter.getLogger(OntologyFactory.class.getName());
 
-  private final static ExtensionPoint X_POINT =
-    PluginRepository.getInstance().getExtensionPoint(Ontology.X_POINT_ID);
+  private ExtensionPoint extensionPoint;  
 
-  private OntologyFactory() {}
-
   /**
   * @return Returns the online ontology extension specified
   * in nutch configuration's key
@@ -43,14 +40,15 @@
   * If the name is  empty (no preference),
   * the first available ontology extension is returned.
   */
-  public static Ontology getOntology() throws PluginRuntimeException {
+  public Ontology getOntology(NutchConf nutchConf) throws PluginRuntimeException {
 
-    if (X_POINT == null) {
+    this.extensionPoint = nutchConf.getPluginRepository().getExtensionPoint(Ontology.X_POINT_ID); 
+    if (this.extensionPoint == null) {
       // not even an extension point defined.
       return null;
     }
 
-    String extensionName = NutchConf.get().get("extension.ontology.extension-name");
+    String extensionName = nutchConf.get("extension.ontology.extension-name");
     if (extensionName != null) {
       Extension extension = findExtension(extensionName);
       if (extension != null) {
@@ -62,7 +60,7 @@
       // not found, fallback to the default, if available.
     }
 
-    Extension[] extensions = X_POINT.getExtensions();
+    Extension[] extensions = this.extensionPoint.getExtensions();
     if (extensions.length > 0) {
       LOG.info("Using the first ontology extension found: "
         + extensions[0].getId());
@@ -73,10 +71,10 @@
 
   }
 
-  private static Extension findExtension(String name)
+  private Extension findExtension(String name)
     throws PluginRuntimeException {
 
-    Extension[] extensions = X_POINT.getExtensions();
+    Extension[] extensions = this.extensionPoint.getExtensions();
 
     for (int i = 0; i < extensions.length; i++) {
       Extension extension = extensions[i];
Index: src/java/org/apache/nutch/ipc/RPC.java
===================================================================
--- src/java/org/apache/nutch/ipc/RPC.java	(revision 359225)
+++ src/java/org/apache/nutch/ipc/RPC.java	(working copy)
@@ -113,13 +113,18 @@
 
   }
 
-  private static Client CLIENT = new Client(ObjectWritable.class);
+  //TODO mb: static client
+  private static Client CLIENT;//TODO  = new Client(ObjectWritable.class);
 
   private static class Invoker implements InvocationHandler {
     private InetSocketAddress address;
 
-    public Invoker(InetSocketAddress address) {
+    public Invoker(InetSocketAddress address, NutchConf nutchConf) {
       this.address = address;
+      if(CLIENT==null){
+          CLIENT = new Client(ObjectWritable.class, nutchConf);
+      }
+          
     }
 
     public Object invoke(Object proxy, Method method, Object[] args)
@@ -132,21 +137,24 @@
 
   /** Construct a client-side proxy object that implements the named protocol,
    * talking to a server at the named address. */
-  public static Object getProxy(Class protocol, InetSocketAddress addr) {
+  public static Object getProxy(Class protocol, InetSocketAddress addr, NutchConf nutchConf) {
     return Proxy.newProxyInstance(protocol.getClassLoader(),
                                   new Class[] { protocol },
-                                  new Invoker(addr));
+                                  new Invoker(addr, nutchConf));
   }
 
   /** Expert: Make multiple, parallel calls to a set of servers. */
   public static Object[] call(Method method, Object[][] params,
-                              InetSocketAddress[] addrs)
+                              InetSocketAddress[] addrs, NutchConf  nutchConf)
     throws IOException {
 
     Invocation[] invocations = new Invocation[params.length];
     for (int i = 0; i < params.length; i++)
       invocations[i] = new Invocation(method, params[i]);
     
+    if(CLIENT==null){
+        CLIENT = new Client(ObjectWritable.class, nutchConf);
+    }
     Writable[] wrappedValues = CLIENT.call(invocations, addrs);
     
     Object[] values =
@@ -161,16 +169,16 @@
 
   /** Construct a server for a protocol implementation instance listening on a
    * port. */
-  public static Server getServer(final Object instance, final int port) {
-    return getServer(instance, port, 1, false);
+  public static Server getServer(final Object instance, final int port, NutchConf nutchConf) {
+    return getServer(instance, port, 1, false, nutchConf);
   }
 
   /** Construct a server for a protocol implementation instance listening on a
    * port. */
   public static Server getServer(final Object instance, final int port,
                                  final int numHandlers,
-                                 final boolean verbose) {
-    return new Server(port, Invocation.class, numHandlers) {
+                                 final boolean verbose, NutchConf nutchConf) {
+    return new Server(port, Invocation.class, numHandlers, nutchConf) {
         
         Class implementation = instance.getClass();
 
Index: src/java/org/apache/nutch/ipc/Server.java
===================================================================
--- src/java/org/apache/nutch/ipc/Server.java	(revision 359225)
+++ src/java/org/apache/nutch/ipc/Server.java	(working copy)
@@ -53,7 +53,7 @@
   private int maxQueuedCalls;                     // max number of queued calls
   private Class paramClass;                       // class of call parameters
 
-  private int timeout = NutchConf.get().getInt("ipc.client.timeout",10000);
+  private int timeout;
 
   private boolean running = true;                 // true while server runs
   private LinkedList callQueue = new LinkedList(); // queued calls
@@ -228,11 +228,12 @@
    * be of the named class.  The <code>handlerCount</handlerCount> determines
    * the number of handler threads that will be used to process calls.
    */
-  protected Server(int port, Class paramClass, int handlerCount) {
+  protected Server(int port, Class paramClass, int handlerCount, NutchConf nutchConf) {
     this.port = port;
     this.paramClass = paramClass;
     this.handlerCount = handlerCount;
     this.maxQueuedCalls = handlerCount;
+    this.timeout = nutchConf.getInt("ipc.client.timeout",10000); 
   }
 
   /** Sets the timeout used for network i/o. */
Index: src/java/org/apache/nutch/ipc/Client.java
===================================================================
--- src/java/org/apache/nutch/ipc/Client.java	(revision 367309)
+++ src/java/org/apache/nutch/ipc/Client.java	(working copy)
@@ -52,7 +52,7 @@
   private Hashtable connections = new Hashtable();
 
   private Class valueClass;                       // class of call values
-  private int timeout = NutchConf.get().getInt("ipc.client.timeout",10000);                    // timeout for calls
+  private int timeout ;// timeout for calls
   private int counter;                            // counter for call ids
   private boolean running = true;                 // true while client runs
 
@@ -256,8 +256,9 @@
 
   /** Construct an IPC client whose values are of the given {@link Writable}
    * class. */
-  public Client(Class valueClass) {
+  public Client(Class valueClass, NutchConf nutchConf) {
     this.valueClass = valueClass;
+    this.timeout = nutchConf.getInt("ipc.client.timeout",10000);
   }
 
   /** Stop all threads related to this client.  No further calls may be made
Index: src/java/org/apache/nutch/util/NutchConf.java
===================================================================
--- src/java/org/apache/nutch/util/NutchConf.java	(revision 367309)
+++ src/java/org/apache/nutch/util/NutchConf.java	(working copy)
@@ -23,6 +23,8 @@
 import java.io.*;
 import java.util.logging.Logger;
 import javax.xml.parsers.*;
+
+import org.apache.nutch.plugin.PluginRepository;
 import org.w3c.dom.*;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.Transformer;
@@ -47,14 +49,16 @@
 
   private static final NutchConf DEFAULT = new NutchConf();
 
-  /** Return the default configuration. */
-  public static NutchConf get() { return DEFAULT; }
+//  /** Return the default configuration. */
+//  public static NutchConf get() { return DEFAULT; }
 
   private ArrayList resourceNames = new ArrayList();
   private Properties properties;
   private ClassLoader classLoader = 
     Thread.currentThread().getContextClassLoader();
 
+private PluginRepository pluginRepository;
+
   /** A new configuration. */
   public NutchConf() {
     resourceNames.add("nutch-default.xml");
@@ -89,6 +93,16 @@
     resourceNames.add(resourceNames.size()-1, name); // add second to last
     properties = null;                            // trigger reload
   }
+  
+  /**
+ * @return a cached instance of the plugin repository
+ */
+public PluginRepository getPluginRepository() {
+        if (this.pluginRepository == null) {
+            this.pluginRepository = new PluginRepository(this);
+        }
+        return this.pluginRepository;
+    }
 
   /** Returns the value of the <code>name</code> property, or null if no
    * such property exists. */
@@ -437,7 +451,7 @@
 
   /** For debugging.  List non-default properties to the terminal and exit. */
   public static void main(String[] args) throws Exception {
-    get().write(System.out);
+    new NutchConf().write(System.out);
   }
 
 }
Index: src/plugin/parse-msword/src/test/org/apache/nutch/parse/msword/TestMSWordParser.java
===================================================================
--- src/plugin/parse-msword/src/test/org/apache/nutch/parse/msword/TestMSWordParser.java	(revision 367309)
+++ src/plugin/parse-msword/src/test/org/apache/nutch/parse/msword/TestMSWordParser.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.nutch.parse.Parse;
 import org.apache.nutch.parse.ParseUtil;
 import org.apache.nutch.parse.ParseException;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.crawl.CrawlDatum;
@@ -61,12 +62,13 @@
     Content content;
     Parse parse;
 
+    NutchConf nutchConf = new NutchConf();
     for (int i=0; i<sampleFiles.length; i++) {
       urlString = "file:" + sampleDir + fileSeparator + sampleFiles[i];
 
-      protocol = ProtocolFactory.getProtocol(urlString);
+      protocol = new ProtocolFactory(nutchConf).getProtocol(urlString);
       content = protocol.getProtocolOutput(new UTF8(urlString), new CrawlDatum()).getContent();
-      parse = ParseUtil.parseByParserId("parse-msword",content);
+      parse = new ParseUtil(nutchConf).parseByParserId("parse-msword",content);
 
       assertTrue(parse.getText().startsWith(expectedText));
     }
Index: src/plugin/parse-msword/src/java/org/apache/nutch/parse/msword/MSWordParser.java
===================================================================
--- src/plugin/parse-msword/src/java/org/apache/nutch/parse/msword/MSWordParser.java	(revision 359225)
+++ src/plugin/parse-msword/src/java/org/apache/nutch/parse/msword/MSWordParser.java	(working copy)
@@ -19,6 +19,7 @@
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.parse.ParseStatus;
 import org.apache.nutch.parse.Parser;
 import org.apache.nutch.parse.Parse;
@@ -50,6 +51,8 @@
  */
 
 public class MSWordParser implements Parser {
+private NutchConf nutchConf;
+
 //  public static final Logger LOG =
 //    LogFormatter.getLogger("org.apache.nutch.parse.msword");
 
@@ -70,7 +73,7 @@
             && raw.length != Integer.parseInt(contentLength)) {
           return new ParseStatus(ParseStatus.FAILED, ParseStatus.FAILED_TRUNCATED,
                   "Content truncated at " + raw.length
-            +" bytes. Parser can't handle incomplete msword file.").getEmptyParse();
+            +" bytes. Parser can't handle incomplete msword file.").getEmptyParse(this.nutchConf);
       }
 
       WordExtractor extractor = new WordExtractor();
@@ -84,14 +87,14 @@
       extractor = null;
 
     } catch (ParseException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(this.nutchConf);
     } catch (FastSavedException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(this.nutchConf);
     } catch (PasswordProtectedException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(this.nutchConf);
     } catch (Exception e) { // run time exception
       return new ParseStatus(ParseStatus.FAILED,
-              "Can't be handled as msword document. " + e).getEmptyParse();
+              "Can't be handled as msword document. " + e).getEmptyParse(this.nutchConf);
     } finally {
       // nothing so far
     }
@@ -113,12 +116,31 @@
       title = "";
 
     // collect outlink
-    Outlink[] outlinks = OutlinkExtractor.getOutlinks(text);
+    Outlink[] outlinks = OutlinkExtractor.getOutlinks(text, this.nutchConf);
 
-    ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metadata);
+    ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metadata, this.nutchConf);
     return new ParseImpl(text, parseData);
     // any filter?
     //return HtmlParseFilters.filter(content, parse, root);
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/parse-js/src/java/org/apache/nutch/parse/js/JSParseFilter.java
===================================================================
--- src/plugin/parse-js/src/java/org/apache/nutch/parse/js/JSParseFilter.java	(revision 359225)
+++ src/plugin/parse-js/src/java/org/apache/nutch/parse/js/JSParseFilter.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.oro.text.regex.MatchResult;
 import org.apache.oro.text.regex.Pattern;
 import org.apache.oro.text.regex.PatternCompiler;
@@ -50,6 +51,8 @@
     LogFormatter.getLogger("org.apache.nutch.parse.js.JSParseFilter");
 
   private static final int MAX_TITLE_LEN = 80;
+
+private NutchConf nutchConf;
   
   public Parse filter(Content content, Parse parse, HTMLMetaTags metaTags, DocumentFragment doc) {
     String url = content.getBaseUrl();
@@ -64,7 +67,7 @@
       ParseStatus status = parse.getData().getStatus();
       String text = parse.getText();
       Outlink[] newlinks = (Outlink[])outlinks.toArray(new Outlink[outlinks.size()]);
-      parse = new ParseImpl(text, new ParseData(status, title, newlinks, metadata));
+      parse = new ParseImpl(text, new ParseData(status, title, newlinks, metadata, getConf()));
     }
     return parse;
   }
@@ -123,7 +126,7 @@
     String type = c.getContentType();
     if (type != null && !type.trim().equals("") && !type.toLowerCase().startsWith("application/x-javascript"))
       return new ParseStatus(ParseStatus.FAILED_INVALID_FORMAT,
-              "Content not JavaScript: '" + type + "'").getEmptyParse();
+              "Content not JavaScript: '" + type + "'").getEmptyParse(getConf());
     String script = new String(c.getContent());
     Outlink[] outlinks = getJSLinks(script, c.getUrl(), c.getUrl());
     if (outlinks == null) outlinks = new Outlink[0];
@@ -140,7 +143,7 @@
     ContentProperties metadata = new ContentProperties();
     metadata.putAll(c.getMetadata());
     ParseData pd = new ParseData(ParseStatus.STATUS_SUCCESS, title,
-            outlinks, metadata);
+            outlinks, metadata, getConf());
     Parse parse = new ParseImpl(script, pd);
     return parse;
   }
@@ -154,7 +157,7 @@
   /**
    *  This method extracts URLs from literals embedded in JavaScript.
    */
-  private static Outlink[] getJSLinks(String plainText, String anchor, String base) {
+  private  Outlink[] getJSLinks(String plainText, String anchor, String base) {
 
     final List outlinks = new ArrayList();
     URL baseURL = null;
@@ -195,7 +198,7 @@
         } else url = new URL(baseURL, url).toString();
         url = url.replaceAll("&amp;", "&");
         LOG.fine(" - outlink from JS: '" + url + "'");
-        outlinks.add(new Outlink(url, anchor));
+        outlinks.add(new Outlink(url, anchor, getConf()));
       }
     } catch (Exception ex) {
       // if it is a malformed URL we just throw it away and continue with
@@ -225,9 +228,29 @@
     StringBuffer sb = new StringBuffer();
     String line = null;
     while ((line = br.readLine()) != null) sb.append(line + "\n");
-    Outlink[] links = getJSLinks(sb.toString(), args[1], args[1]);
+    JSParseFilter parseFilter = new JSParseFilter();
+    parseFilter.setConf(new NutchConf());
+    Outlink[] links = parseFilter.getJSLinks(sb.toString(), args[1], args[1]);
     System.out.println("Outlinks extracted: " + links.length);
     for (int i = 0; i < links.length; i++)
       System.out.println(" - " + links[i]);
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
Index: src/plugin/index-basic/src/java/org/apache/nutch/indexer/basic/BasicIndexingFilter.java
===================================================================
--- src/plugin/index-basic/src/java/org/apache/nutch/indexer/basic/BasicIndexingFilter.java	(revision 367309)
+++ src/plugin/index-basic/src/java/org/apache/nutch/indexer/basic/BasicIndexingFilter.java	(working copy)
@@ -40,8 +40,8 @@
   public static final Logger LOG
     = LogFormatter.getLogger(BasicIndexingFilter.class.getName());
 
-  private static final int MAX_TITLE_LENGTH =
-    NutchConf.get().getInt("indexer.max.title.length", 100);
+  private int MAX_TITLE_LENGTH;
+  private NutchConf nutchConf;
 
   public Document filter(Document doc, Parse parse, UTF8 url, CrawlDatum datum, Inlinks inlinks)
     throws IndexingException {
@@ -89,4 +89,19 @@
     return doc;
   }
 
+/* (non-Javadoc)
+ * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+ */
+public void setConf(NutchConf conf) {
+    this.nutchConf = conf;
+    this.MAX_TITLE_LENGTH = conf.getInt("indexer.max.title.length", 100);
 }
+
+/* (non-Javadoc)
+ * @see org.apache.nutch.util.NutchConfigurable#getConf()
+ */
+public NutchConf getConf() {
+    return this.nutchConf;
+}
+
+}
Index: src/plugin/languageidentifier/src/test/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java
===================================================================
--- src/plugin/languageidentifier/src/test/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java	(revision 359225)
+++ src/plugin/languageidentifier/src/test/org/apache/nutch/analysis/lang/TestHTMLLanguageParser.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.parse.ParserFactory;
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
+import org.apache.nutch.util.NutchConf;
 
 
 public class TestHTMLLanguageParser extends TestCase {
@@ -52,7 +53,7 @@
       for (int t = 0; t < docs.length; t++) {
 
         Content content = getContent(docs[t]);
-        Parser parser = ParserFactory.getParser("text/html", URL);
+        Parser parser = new ParserFactory(new NutchConf()).getParser("text/html", URL);
         Parse parse = parser.getParse(content);
 
         assertEquals(metalanguages[t], (String) parse.getData().get(
@@ -125,7 +126,7 @@
     ContentProperties p = new ContentProperties();
     p.put("Content-Type", "text/html");
 
-    Content content = new Content(URL, BASE, text.getBytes(), "text/html", p);
+    Content content = new Content(URL, BASE, text.getBytes(), "text/html", p, new NutchConf());
     return content;
   }
 
Index: src/plugin/languageidentifier/src/test/org/apache/nutch/analysis/lang/TestLanguageIdentifier.java
===================================================================
--- src/plugin/languageidentifier/src/test/org/apache/nutch/analysis/lang/TestLanguageIdentifier.java	(revision 359225)
+++ src/plugin/languageidentifier/src/test/org/apache/nutch/analysis/lang/TestLanguageIdentifier.java	(working copy)
@@ -32,6 +32,7 @@
 
 // Lucene imports
 import org.apache.lucene.analysis.Token;
+import org.apache.nutch.util.NutchConf;
 
 
 /**
@@ -204,7 +205,7 @@
     public void testIdentify() {
         try {
             long total = 0;
-            LanguageIdentifier idfr = LanguageIdentifier.getInstance();
+            LanguageIdentifier idfr = LanguageIdentifier.getInstance(new NutchConf());
             BufferedReader in = new BufferedReader(new InputStreamReader(
                         this.getClass().getResourceAsStream("test-referencial.txt")));
             String line = null;
Index: src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageQueryFilter.java
===================================================================
--- src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageQueryFilter.java	(revision 359225)
+++ src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageQueryFilter.java	(working copy)
@@ -17,11 +17,33 @@
 package org.apache.nutch.analysis.lang;
 
 import org.apache.nutch.searcher.RawFieldQueryFilter;
+import org.apache.nutch.util.NutchConf;
 
 /** Handles "lang:" query clauses, causing them to search the "lang" field
  * indexed by LanguageIdentifier. */
 public class LanguageQueryFilter extends RawFieldQueryFilter {
-  public LanguageQueryFilter() {
+  private NutchConf nutchConf;
+
+public LanguageQueryFilter() {
     super("lang");
   }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+   */
+  public void setConf(NutchConf conf) {
+      this.nutchConf = conf;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#getConf()
+   */
+  public NutchConf getConf() {
+      return this.nutchConf;
+  }
+
 }
Index: src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageIndexingFilter.java
===================================================================
--- src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageIndexingFilter.java	(revision 359225)
+++ src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageIndexingFilter.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.nutch.indexer.IndexingException;
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.parse.Parse;
+import org.apache.nutch.util.NutchConf;
 
 // Lucene imports
 import org.apache.lucene.document.Field;
@@ -49,7 +50,9 @@
 public class LanguageIndexingFilter implements IndexingFilter {
   
 
-  /**
+  private NutchConf nutchConf;
+
+/**
    * Constructs a new Language Indexing Filter.
    */
   public LanguageIndexingFilter() {
@@ -77,7 +80,7 @@
       text.append(parse.getData().getTitle())
           .append(" ")
           .append(parse.getText());
-      lang = LanguageIdentifier.getInstance().identify(text);
+      lang = LanguageIdentifier.getInstance(getConf()).identify(text);
     }
 
     if (lang == null) {
@@ -88,5 +91,24 @@
 
     return doc;
   }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+   */
+  public void setConf(NutchConf conf) {
+      this.nutchConf = conf;
+  }
 
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#getConf()
+   */
+  public NutchConf getConf() {
+      return this.nutchConf;
+  }
+
+
 }
Index: src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/HTMLLanguageParser.java
===================================================================
--- src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/HTMLLanguageParser.java	(revision 359225)
+++ src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/HTMLLanguageParser.java	(working copy)
@@ -28,6 +28,7 @@
 import org.apache.nutch.parse.HtmlParseFilter;
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 // DOM imports
 import org.w3c.dom.DocumentFragment;
@@ -67,6 +68,8 @@
       LOG.severe(e.toString());
     }
   }
+
+private NutchConf nutchConf;
   
 
   
@@ -195,5 +198,23 @@
     
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
       
 }
Index: src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageIdentifier.java
===================================================================
--- src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageIdentifier.java	(revision 367309)
+++ src/plugin/languageidentifier/src/java/org/apache/nutch/analysis/lang/LanguageIdentifier.java	(working copy)
@@ -95,12 +95,12 @@
   /**
    * Constructs a new Language Identifier.
    */
-  private LanguageIdentifier() {
+  private LanguageIdentifier(NutchConf nutchConf) {
 
     // Gets ngram sizes to take into account from the Nutch Config
-    minLength = NutchConf.get().getInt("lang.ngram.min.length",
+    minLength = nutchConf.getInt("lang.ngram.min.length",
                                        NGramProfile.DEFAULT_MIN_NGRAM_LENGTH);
-    maxLength = NutchConf.get().getInt("lang.ngram.max.length",
+    maxLength = nutchConf.getInt("lang.ngram.max.length",
                                        NGramProfile.DEFAULT_MAX_NGRAM_LENGTH);
     // Ensure the min and max values are in an acceptale range
     // (ie min >= DEFAULT_MIN_NGRAM_LENGTH and max <= DEFAULT_MAX_NGRAM_LENGTH)
@@ -110,7 +110,7 @@
     minLength = Math.min(minLength, maxLength);
 
     // Gets the value of the maximum size of data to analyze
-    analyzeLength = NutchConf.get().getInt("lang.analyze.max.length",
+    analyzeLength = nutchConf.getInt("lang.analyze.max.length",
                                            DEFAULT_ANALYSIS_LENGTH);
     
     Properties p = new Properties();
@@ -178,11 +178,11 @@
    * Get a LanguageIdentifier instance.
    * @return the LanguageIdentifier singleton instance.
    */
-  public static LanguageIdentifier getInstance() {
+  public static LanguageIdentifier getInstance(NutchConf nutchConf) {
     if (identifier == null) {
         synchronized(LanguageIdentifier.class) {
             if (identifier == null) {
-                identifier = new LanguageIdentifier();
+                identifier = new LanguageIdentifier(nutchConf);
             }
         }
     }
@@ -272,9 +272,10 @@
 
     }
 
+    NutchConf nutchConf = new NutchConf();
     String lang = null;
     //LanguageIdentifier idfr = LanguageIdentifier.getInstance();
-    LanguageIdentifier idfr = new LanguageIdentifier();
+    LanguageIdentifier idfr = new LanguageIdentifier(nutchConf);
     File f;
     FileInputStream fis;
     try {
@@ -292,7 +293,7 @@
           break;
 
         case IDURL:
-          text = getUrlContent(filename);
+          text = getUrlContent(filename, nutchConf);
           lang = idfr.identify(text);
           break;
 
@@ -348,13 +349,13 @@
    * @param url
    * @return contents of url
    */
-  private static String getUrlContent(String url) {
+  private static String getUrlContent(String url, NutchConf nutchConf) {
     Protocol protocol;
     try {
-      protocol = ProtocolFactory.getProtocol(url);
+      protocol = new ProtocolFactory(nutchConf).getProtocol(url);
       Content content = protocol.getProtocolOutput(new UTF8(url), new CrawlDatum()).getContent();
       String contentType = content.getContentType();
-      Parser parser = ParserFactory.getParser(contentType, url);
+      Parser parser = new ParserFactory(nutchConf).getParser(contentType, url);
       Parse parse = parser.getParse(content);
       System.out.println("text:" + parse.getText());
       return parse.getText();
Index: src/plugin/urlfilter-prefix/src/java/org/apache/nutch/net/PrefixURLFilter.java
===================================================================
--- src/plugin/urlfilter-prefix/src/java/org/apache/nutch/net/PrefixURLFilter.java	(revision 359225)
+++ src/plugin/urlfilter-prefix/src/java/org/apache/nutch/net/PrefixURLFilter.java	(working copy)
@@ -52,40 +52,13 @@
 
   // read in attribute "file" of this plugin.
   private static String attributeFile = null;
-  static {
-    String pluginName = "urlfilter-prefix";
-    Extension[] extensions = PluginRepository.getInstance()
-      .getExtensionPoint(URLFilter.class.getName()).getExtensions();
-    for (int i=0; i < extensions.length; i++) {
-      Extension extension = extensions[i];
-      if (extension.getDescriptor().getPluginId().equals(pluginName)) {
-        attributeFile = extension.getAttribute("file");
-        break;
-      }
-    }
-    if (attributeFile != null && attributeFile.trim().equals(""))
-      attributeFile = null;
-    if (attributeFile != null) {
-      LOG.info("Attribute \"file\" is defined for plugin "+pluginName+" as "+attributeFile);
-    } else {
-      //LOG.warning("Attribute \"file\" is not defined in plugin.xml for plugin "+pluginName);
-    }
-  }
 
   private TrieStringMatcher trie;
 
+private NutchConf nutchConf;
+
   public PrefixURLFilter() throws IOException {
-    String file = NutchConf.get().get("urlfilter.prefix.file");
-    // attribute "file" takes precedence if defined
-    if (attributeFile != null)
-      file = attributeFile;
-    Reader reader = NutchConf.get().getConfResourceAsReader(file);
-
-    if (reader == null) {
-      trie = new PrefixStringMatcher(new String[0]);
-    } else {
-      trie = readConfigurationFile(reader);
-    }
+   
   }
 
   public PrefixURLFilter(String filename) throws IOException {
@@ -99,7 +72,7 @@
       return url;
   }
 
-  private static TrieStringMatcher readConfigurationFile(Reader reader)
+  private  TrieStringMatcher readConfigurationFile(Reader reader)
     throws IOException {
     
     BufferedReader in=new BufferedReader(reader);
@@ -140,5 +113,60 @@
       }
     }
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+
+        String pluginName = "urlfilter-prefix";
+        Extension[] extensions = conf.getPluginRepository().getExtensionPoint(URLFilter.class.getName())
+                .getExtensions();
+        for (int i = 0; i < extensions.length; i++) {
+            Extension extension = extensions[i];
+            if (extension.getDescriptor().getPluginId().equals(pluginName)) {
+                attributeFile = extension.getAttribute("file");
+                break;
+            }
+        }
+        if (attributeFile != null && attributeFile.trim().equals(""))
+            attributeFile = null;
+        if (attributeFile != null) {
+            LOG.info("Attribute \"file\" is defined for plugin " + pluginName + " as " + attributeFile);
+        } else {
+            // LOG.warning("Attribute \"file\" is not defined in plugin.xml for
+            // plugin "+pluginName);
+        }
+
+        String file = conf.get("urlfilter.prefix.file");
+        // attribute "file" takes precedence if defined
+        if (attributeFile != null)
+            file = attributeFile;
+        Reader reader = conf.getConfResourceAsReader(file);
+
+        if (reader == null) {
+            trie = new PrefixStringMatcher(new String[0]);
+        } else {
+            try {
+                trie = readConfigurationFile(reader);
+            } catch (IOException e) {
+                LOG.severe(e.getMessage());
+                // TODO mb: throw Exception?
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
   
 }
Index: src/plugin/query-more/src/java/org/apache/nutch/searcher/more/DateQueryFilter.java
===================================================================
--- src/plugin/query-more/src/java/org/apache/nutch/searcher/more/DateQueryFilter.java	(revision 359225)
+++ src/plugin/query-more/src/java/org/apache/nutch/searcher/more/DateQueryFilter.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.nutch.searcher.QueryException;
 
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.RangeQuery;
@@ -47,6 +48,8 @@
 
   // query syntax is defined as date:yyyymmdd-yyyymmdd
   private static final Pattern pattern = Pattern.compile("^(\\d{8})-(\\d{8})$");
+
+private NutchConf nutchConf;
     
   public BooleanQuery filter(Query input, BooleanQuery output)
     throws QueryException {
@@ -84,4 +87,23 @@
     return output;
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/query-more/src/java/org/apache/nutch/searcher/more/TypeQueryFilter.java
===================================================================
--- src/plugin/query-more/src/java/org/apache/nutch/searcher/more/TypeQueryFilter.java	(revision 359225)
+++ src/plugin/query-more/src/java/org/apache/nutch/searcher/more/TypeQueryFilter.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.nutch.searcher.more;
 
 import org.apache.nutch.searcher.RawFieldQueryFilter;
+import org.apache.nutch.util.NutchConf;
 
 /**
  * Handles "type:" query clauses, causing them to search the field
@@ -26,7 +27,27 @@
  */
 
 public class TypeQueryFilter extends RawFieldQueryFilter {
-  public TypeQueryFilter() {
+  private NutchConf nutchConf;
+
+public TypeQueryFilter() {
     super("type");
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
Index: src/plugin/query-site/src/java/org/apache/nutch/searcher/site/SiteQueryFilter.java
===================================================================
--- src/plugin/query-site/src/java/org/apache/nutch/searcher/site/SiteQueryFilter.java	(revision 359225)
+++ src/plugin/query-site/src/java/org/apache/nutch/searcher/site/SiteQueryFilter.java	(working copy)
@@ -17,11 +17,32 @@
 package org.apache.nutch.searcher.site;
 
 import org.apache.nutch.searcher.RawFieldQueryFilter;
+import org.apache.nutch.util.NutchConf;
 
 /** Handles "site:" query clauses, causing them to search the field indexed by
  * SiteIndexingFilter. */
 public class SiteQueryFilter extends RawFieldQueryFilter {
-  public SiteQueryFilter() {
+  private NutchConf nutchConf;
+
+public SiteQueryFilter() {
     super("site");
   }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+   */
+  public void setConf(NutchConf conf) {
+      this.nutchConf = conf;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#getConf()
+   */
+  public NutchConf getConf() {
+      return this.nutchConf;
+  }
 }
Index: src/plugin/parse-zip/src/test/org/apache/nutch/parse/zip/TestZipParser.java
===================================================================
--- src/plugin/parse-zip/src/test/org/apache/nutch/parse/zip/TestZipParser.java	(revision 367309)
+++ src/plugin/parse-zip/src/test/org/apache/nutch/parse/zip/TestZipParser.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.nutch.parse.Parse;
 import org.apache.nutch.parse.ParseUtil;
 import org.apache.nutch.parse.ParseException;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.crawl.CrawlDatum;
@@ -61,12 +62,13 @@
     Content content;
     Parse parse;
 
+    NutchConf conf = new NutchConf();
     for (int i = 0; i < sampleFiles.length; i++) {
       urlString = "file:" + sampleDir + fileSeparator + sampleFiles[i];
 
-      protocol = ProtocolFactory.getProtocol(urlString);
+      protocol = new ProtocolFactory(conf).getProtocol(urlString);
       content = protocol.getProtocolOutput(new UTF8(urlString), new CrawlDatum()).getContent();
-      parse = ParseUtil.parseByParserId("parse-zip",content);
+      parse = new ParseUtil(conf).parseByParserId("parse-zip",content);
       assertTrue(parse.getText().equals(expectedText));
     }
   }
Index: src/plugin/parse-zip/src/java/org/apache/nutch/parse/zip/ZipParser.java
===================================================================
--- src/plugin/parse-zip/src/java/org/apache/nutch/parse/zip/ZipParser.java	(revision 359225)
+++ src/plugin/parse-zip/src/java/org/apache/nutch/parse/zip/ZipParser.java	(working copy)
@@ -33,6 +33,7 @@
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 /**
  * ZipParser class based on MSPowerPointParser class by Stephan Strittmatter.
@@ -42,6 +43,7 @@
 public class ZipParser implements Parser{
     
     private static final Logger LOG = LogFormatter.getLogger(ZipParser.class.getName());
+    private NutchConf nutchConf;
     /** Creates a new instance of ZipParser */
     public ZipParser() {
     }
@@ -66,10 +68,10 @@
                 return new ParseStatus(ParseStatus.FAILED,
                                        ParseStatus.FAILED_TRUNCATED,
                                        "Content truncated at " + contentInBytes.length +
-                                       " bytes. Parser can't handle incomplete pdf file.").getEmptyParse();
+                                       " bytes. Parser can't handle incomplete pdf file.").getEmptyParse(getConf());
             }
             
-            ZipTextExtractor extractor = new ZipTextExtractor();
+            ZipTextExtractor extractor = new ZipTextExtractor(getConf());
             
             // extract text
             resultText = extractor.extractText(new ByteArrayInputStream(contentInBytes),
@@ -77,7 +79,7 @@
             
         } catch (Exception e) {
             return new ParseStatus(ParseStatus.FAILED,
-                                   "Can't be handled as Zip document. " + e).getEmptyParse();
+                                   "Can't be handled as Zip document. " + e).getEmptyParse(getConf());
         }
         
         // collect meta data
@@ -96,10 +98,24 @@
         final ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS,
                                                   resultTitle, 
                                                   outlinks, 
-                                                  metadata);
+                                                  metadata, getConf());
         
         LOG.finest("Zip file parsed sucessfully !!");
         return new ParseImpl(resultText, parseData);
     }
+
+    /* (non-Javadoc)
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
     
 }
Index: src/plugin/parse-zip/src/java/org/apache/nutch/parse/zip/ZipTextExtractor.java
===================================================================
--- src/plugin/parse-zip/src/java/org/apache/nutch/parse/zip/ZipTextExtractor.java	(revision 359225)
+++ src/plugin/parse-zip/src/java/org/apache/nutch/parse/zip/ZipTextExtractor.java	(working copy)
@@ -46,14 +46,17 @@
 public class ZipTextExtractor {
   
   /** Get the MimeTypes resolver instance. */
-  private final static MimeTypes MIME =
-          MimeTypes.get(NutchConf.get().get("mime.types.file"));
+  private MimeTypes MIME;
   
   public static final Logger LOG = LogFormatter.getLogger(ZipTextExtractor.class.getName());
+
+private NutchConf nutchConf;
   
   
   /** Creates a new instance of ZipTextExtractor */
-  public ZipTextExtractor() {
+  public ZipTextExtractor(NutchConf nutchConf) {
+      this.nutchConf = nutchConf;
+      this.MIME = MimeTypes.get(nutchConf.get("mime.types.file"));
   }
   
   public String extractText(InputStream input, String url, List outLinksList) throws IOException {
@@ -88,13 +91,13 @@
             ContentProperties metadata = new ContentProperties();
             metadata.setProperty("Content-Length", Long.toString(entry.getSize()));
             metadata.setProperty("Content-Type", contentType);
-            Content content = new Content(newurl, base, b, contentType, metadata);
-            Parse parse = ParseUtil.parse(content);
+            Content content = new Content(newurl, base, b, contentType, metadata, this.nutchConf);
+            Parse parse = new ParseUtil(this.nutchConf).parse(content);
             ParseData theParseData = parse.getData();
             Outlink[] theOutlinks = theParseData.getOutlinks();
             
             for(int count = 0; count < theOutlinks.length; count++) {
-              outLinksList.add(new Outlink(theOutlinks[count].getToUrl(), theOutlinks[count].getAnchor()));
+              outLinksList.add(new Outlink(theOutlinks[count].getToUrl(), theOutlinks[count].getAnchor(), this.nutchConf));
             }
             
             resultText += entry.getName() + " " + parse.getText() + " ";
Index: src/plugin/protocol-file/src/java/org/apache/nutch/protocol/file/File.java
===================================================================
--- src/plugin/protocol-file/src/java/org/apache/nutch/protocol/file/File.java	(revision 367309)
+++ src/plugin/protocol-file/src/java/org/apache/nutch/protocol/file/File.java	(working copy)
@@ -50,7 +50,7 @@
 
   static final int MAX_REDIRECTS = 5;
 
-  static int maxContentLength = NutchConf.get().getInt("file.content.limit", 64 * 1024);
+   int maxContentLength;
 
   // 20040412, xing
   // the following three: HttpDateFormat, MimetypesFileTypeMap, MagicFile
@@ -59,6 +59,8 @@
   // http date format
   HttpDateFormat httpDateFormat = null;
 
+private NutchConf nutchConf;
+
   // constructor
   public File() {
     this.httpDateFormat = new HttpDateFormat();
@@ -76,7 +78,7 @@
   
       while (true) {
         FileResponse response;
-        response = new FileResponse(u, datum, this);   // make a request
+        response = new FileResponse(u, datum, this, getConf());   // make a request
   
         int code = response.getCode();
   
@@ -152,4 +154,23 @@
     file = null;
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        this.maxContentLength = conf.getInt("file.content.limit", 64 * 1024);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/protocol-file/src/java/org/apache/nutch/protocol/file/FileResponse.java
===================================================================
--- src/plugin/protocol-file/src/java/org/apache/nutch/protocol/file/FileResponse.java	(revision 367309)
+++ src/plugin/protocol-file/src/java/org/apache/nutch/protocol/file/FileResponse.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
+import org.apache.nutch.util.NutchConf;
 
 
 /************************************
@@ -63,6 +64,7 @@
   private ContentProperties headers = new ContentProperties();
 
   private final File file;
+private NutchConf nutchConf;
 
   /** Returns the response code. */
   public int getCode() { return code; }
@@ -77,15 +79,16 @@
   public Content toContent() {
     return new Content(orig, base, content,
                        getHeader("Content-Type"),
-                       headers);
+                       headers, this.nutchConf);
   }
 
-  public FileResponse(URL url, CrawlDatum datum, File file)
+  public FileResponse(URL url, CrawlDatum datum, File file, NutchConf nutchConf)
     throws FileException, IOException {
 
     this.orig = url.toString();
     this.base = url.toString();
     this.file = file;
+    this.nutchConf = nutchConf;
 
     if (!"file".equals(url.getProtocol()))
       throw new FileException("Not a file url:" + url);
Index: src/plugin/parse-rss/src/test/org/apache/nutch/parse/rss/TestRSSParser.java
===================================================================
--- src/plugin/parse-rss/src/test/org/apache/nutch/parse/rss/TestRSSParser.java	(revision 367309)
+++ src/plugin/parse-rss/src/test/org/apache/nutch/parse/rss/TestRSSParser.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.nutch.parse.ParseException;
 import org.apache.nutch.parse.ParseData;
 import org.apache.nutch.parse.Outlink;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.crawl.CrawlDatum;
@@ -79,12 +80,13 @@
         Content content;
         Parse parse;
 
+        NutchConf nutchConf = new NutchConf();
         for (int i = 0; i < sampleFiles.length; i++) {
             urlString = "file:" + sampleDir + fileSeparator + sampleFiles[i];
 
-            protocol = ProtocolFactory.getProtocol(urlString);
+            protocol = new ProtocolFactory(nutchConf).getProtocol(urlString);
             content = protocol.getProtocolOutput(new UTF8(urlString), new CrawlDatum()).getContent();
-            parse = ParseUtil.parseByParserId("parse-rss",content);
+            parse = new ParseUtil(nutchConf).parseByParserId("parse-rss",content);
 
             //check that there are 3 outlinks:
             //http://test.channel.com
Index: src/plugin/parse-rss/src/java/org/apache/nutch/parse/rss/RSSParser.java
===================================================================
--- src/plugin/parse-rss/src/java/org/apache/nutch/parse/rss/RSSParser.java	(revision 359225)
+++ src/plugin/parse-rss/src/java/org/apache/nutch/parse/rss/RSSParser.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.parse.Parser;
 import org.apache.nutch.parse.Parse;
 import org.apache.nutch.parse.ParseStatus;
@@ -63,6 +64,7 @@
 public class RSSParser implements Parser {
     public static final Logger LOG = LogFormatter
             .getLogger("org.apache.nutch.parse.rss");
+    private NutchConf nutchConf;
 
     /**
      * <p>
@@ -122,7 +124,7 @@
             e.printStackTrace();
             LOG.fine("nutch:parse-rss:RSSParser Exception: " + e.getMessage());
             return new ParseStatus(ParseStatus.FAILED,
-                    "Can't be handled as rss document. " + e).getEmptyParse();
+                    "Can't be handled as rss document. " + e).getEmptyParse(getConf());
         }
 
         StringBuffer contentTitle = new StringBuffer(), indexText = new StringBuffer();
@@ -149,9 +151,9 @@
                     try {
                         // get the outlink
 			if (r.getDescription()!= null ) {
-			    theOutlinks.add(new Outlink(r.getLink(), r.getDescription()));
+			    theOutlinks.add(new Outlink(r.getLink(), r.getDescription(), getConf()));
 			} else {
-			    theOutlinks.add(new Outlink(r.getLink(), ""));
+			    theOutlinks.add(new Outlink(r.getLink(), "", getConf()));
 			}
                     } catch (MalformedURLException e) {
                         LOG.info("nutch:parse-rss:RSSParser Exception: MalformedURL: "
@@ -179,9 +181,9 @@
                     if (whichLink != null) {
                         try {
 			    if (theRSSItem.getDescription()!=null) {
-				theOutlinks.add(new Outlink(whichLink, theRSSItem.getDescription()));
+				theOutlinks.add(new Outlink(whichLink, theRSSItem.getDescription(), getConf()));
 			    } else {
-				theOutlinks.add(new Outlink(whichLink, ""));
+				theOutlinks.add(new Outlink(whichLink, "", getConf()));
 			    }
                         } catch (MalformedURLException e) {
                             LOG.info("nutch:parse-rss:RSSParser Exception: MalformedURL: "
@@ -210,8 +212,22 @@
         // LOG.info("Outlinks: "+outlinks);
 
         ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS,
-                contentTitle.toString(), outlinks, content.getMetadata());
+                contentTitle.toString(), outlinks, content.getMetadata(), getConf());
         return new ParseImpl(indexText.toString(), parseData);
     }
 
+    /* (non-Javadoc)
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/urlfilter-regex/src/java/org/apache/nutch/net/RegexURLFilter.java
===================================================================
--- src/plugin/urlfilter-regex/src/java/org/apache/nutch/net/RegexURLFilter.java	(revision 359225)
+++ src/plugin/urlfilter-regex/src/java/org/apache/nutch/net/RegexURLFilter.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.nutch.plugin.Extension;
 import org.apache.nutch.plugin.PluginRepository;
+import org.apache.nutch.plugin.PluginRuntimeException;
 
 import java.io.Reader;
 import java.io.FileReader;
@@ -59,25 +60,6 @@
 
   // read in attribute "file" of this plugin.
   private static String attributeFile = null;
-  static {
-    String pluginName = "urlfilter-regex";
-    Extension[] extensions = PluginRepository.getInstance()
-      .getExtensionPoint(URLFilter.class.getName()).getExtensions();
-    for (int i=0; i < extensions.length; i++) {
-      Extension extension = extensions[i];
-      if (extension.getDescriptor().getPluginId().equals(pluginName)) {
-        attributeFile = extension.getAttribute("file");
-        break;
-      }
-    }
-    if (attributeFile != null && attributeFile.trim().equals(""))
-      attributeFile = null;
-    if (attributeFile != null) {
-      LOG.info("Attribute \"file\" is defined for plugin "+pluginName+" as "+attributeFile);
-    } else {
-      //LOG.warning("Attribute \"file\" is not defined in plugin.xml for plugin "+pluginName);
-    }
-  }
 
   private static class Rule {
     public Perl5Pattern pattern;
@@ -88,18 +70,10 @@
   private List rules;
   private PatternMatcher matcher = new Perl5Matcher();
 
+private NutchConf nutchConf;
+
   public RegexURLFilter() throws IOException, MalformedPatternException {
-    String file = NutchConf.get().get("urlfilter.regex.file");
-    // attribute "file" takes precedence if defined
-    if (attributeFile != null)
-      file = attributeFile;
-    Reader reader = NutchConf.get().getConfResourceAsReader(file);
-
-    if (reader == null) {
-      LOG.severe("Can't find resource: " + file);
-    } else {
-      rules=readConfigurationFile(reader);
-    }
+    
   }
 
   public RegexURLFilter(String filename)
@@ -128,7 +102,7 @@
   // where plus means go ahead and index it and minus means no.
   // 
 
-  private static List readConfigurationFile(Reader reader)
+  private  List readConfigurationFile(Reader reader)
     throws IOException, MalformedPatternException {
 
     BufferedReader in=new BufferedReader(reader);
@@ -184,4 +158,59 @@
     }
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        String pluginName = "urlfilter-regex";
+        Extension[] extensions = conf.getPluginRepository().getExtensionPoint(URLFilter.class.getName()).getExtensions();
+        for (int i=0; i < extensions.length; i++) {
+          Extension extension = extensions[i];
+          if (extension.getDescriptor().getPluginId().equals(pluginName)) {
+            attributeFile = extension.getAttribute("file");
+            break;
+          }
+        }
+        if (attributeFile != null && attributeFile.trim().equals(""))
+          attributeFile = null;
+        if (attributeFile != null) {
+          LOG.info("Attribute \"file\" is defined for plugin "+pluginName+" as "+attributeFile);
+        } else {
+          //LOG.warning("Attribute \"file\" is not defined in plugin.xml for plugin "+pluginName);
+        }
+        String file = conf.get("urlfilter.regex.file");
+        // attribute "file" takes precedence if defined
+        if (attributeFile != null)
+          file = attributeFile;
+        Reader reader = conf.getConfResourceAsReader(file);
+
+        if (reader == null) {
+          LOG.severe("Can't find resource: " + file);
+        } else {
+          try {
+            rules=readConfigurationFile(reader);
+        } catch (IOException e) {
+            LOG.severe(e.getMessage());
+            //TODO mb: throw Exception?
+            throw new RuntimeException(e.getMessage());
+        } catch (MalformedPatternException e) {
+            LOG.severe(e.getMessage());
+//          TODO mb: throw Exception?
+            throw new RuntimeException(e.getMessage());
+        }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/parse-pdf/src/test/org/apache/nutch/parse/pdf/TestPdfParser.java
===================================================================
--- src/plugin/parse-pdf/src/test/org/apache/nutch/parse/pdf/TestPdfParser.java	(revision 367309)
+++ src/plugin/parse-pdf/src/test/org/apache/nutch/parse/pdf/TestPdfParser.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.nutch.parse.Parse;
 import org.apache.nutch.parse.ParseUtil;
 import org.apache.nutch.parse.ParseException;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.crawl.CrawlDatum;
@@ -64,9 +65,10 @@
     for (int i=0; i<sampleFiles.length; i++) {
       urlString = "file:" + sampleDir + fileSeparator + sampleFiles[i];
 
-      protocol = ProtocolFactory.getProtocol(urlString);
+      NutchConf nutchConf = new NutchConf();
+      protocol = new ProtocolFactory(nutchConf).getProtocol(urlString);
       content = protocol.getProtocolOutput(new UTF8(urlString), new CrawlDatum()).getContent();
-      parse = ParseUtil.parseByParserId("parse-pdf",content);
+      parse = new ParseUtil(nutchConf).parseByParserId("parse-pdf",content);
 
       int index = parse.getText().indexOf(expectedText);
       assertTrue(index > 0);
Index: src/plugin/parse-pdf/src/java/org/apache/nutch/parse/pdf/PdfParser.java
===================================================================
--- src/plugin/parse-pdf/src/java/org/apache/nutch/parse/pdf/PdfParser.java	(revision 359225)
+++ src/plugin/parse-pdf/src/java/org/apache/nutch/parse/pdf/PdfParser.java	(working copy)
@@ -28,6 +28,7 @@
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 import org.apache.nutch.parse.ParseStatus;
 import org.apache.nutch.parse.Parser;
 import org.apache.nutch.parse.Parse;
@@ -62,6 +63,7 @@
 public class PdfParser implements Parser {
   public static final Logger LOG =
     LogFormatter.getLogger("org.apache.nutch.parse.pdf");
+private NutchConf nutchConf;
 
   public PdfParser () {
     // redirect org.apache.log4j.Logger to java's native logger, in order
@@ -99,7 +101,7 @@
             && raw.length != Integer.parseInt(contentLength)) {
           return new ParseStatus(ParseStatus.FAILED, ParseStatus.FAILED_TRUNCATED,
                   "Content truncated at "+raw.length
-            +" bytes. Parser can't handle incomplete pdf file.").getEmptyParse();
+            +" bytes. Parser can't handle incomplete pdf file.").getEmptyParse(getConf());
       }
 
       PDFParser parser = new PDFParser(
@@ -134,13 +136,13 @@
 
     } catch (CryptographyException e) {
       return new ParseStatus(ParseStatus.FAILED,
-              "Error decrypting document. " + e).getEmptyParse();
+              "Error decrypting document. " + e).getEmptyParse(getConf());
     } catch (InvalidPasswordException e) {
       return new ParseStatus(ParseStatus.FAILED,
-              "Can't decrypt document - invalid password. " + e).getEmptyParse();
+              "Can't decrypt document - invalid password. " + e).getEmptyParse(getConf());
     } catch (Exception e) { // run time exception
       return new ParseStatus(ParseStatus.FAILED,
-              "Can't be handled as pdf document. " + e).getEmptyParse();
+              "Can't be handled as pdf document. " + e).getEmptyParse(getConf());
     } finally {
       try {
         if (pdf != null)
@@ -157,13 +159,13 @@
       title = "";
 
     // collect outlink
-    Outlink[] outlinks = OutlinkExtractor.getOutlinks(text);
+    Outlink[] outlinks = OutlinkExtractor.getOutlinks(text, getConf());
 
     // collect meta data
     ContentProperties metadata = new ContentProperties();
     metadata.putAll(content.getMetadata()); // copy through
 
-    ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metadata);
+    ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metadata, getConf());
     return new ParseImpl(text, parseData);
     // any filter?
     //return HtmlParseFilters.filter(content, parse, root);
@@ -180,4 +182,22 @@
     return retval;
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/query-basic/src/java/org/apache/nutch/searcher/basic/BasicQueryFilter.java
===================================================================
--- src/plugin/query-basic/src/java/org/apache/nutch/searcher/basic/BasicQueryFilter.java	(revision 359225)
+++ src/plugin/query-basic/src/java/org/apache/nutch/searcher/basic/BasicQueryFilter.java	(working copy)
@@ -35,54 +35,51 @@
  * expanded to search the url, anchor and content document fields.*/
 public class BasicQueryFilter implements QueryFilter {
     
-  private static float URL_BOOST =
-    NutchConf.get().getFloat("query.url.boost", 4.0f);
+  private float URL_BOOST;
 
-  private static float ANCHOR_BOOST =
-    NutchConf.get().getFloat("query.anchor.boost", 2.0f);
+  private float ANCHOR_BOOST ;
 
-  private static float TITLE_BOOST =
-    NutchConf.get().getFloat("query.title.boost", 1.5f);
+  private float TITLE_BOOST;
 
-    private static float HOST_BOOST =
-      NutchConf.get().getFloat("query.host.boost", 2.0f);
+  private float HOST_BOOST;
 
   private static int SLOP = Integer.MAX_VALUE;
 
-  private static float PHRASE_BOOST =
-    NutchConf.get().getFloat("query.phrase.boost", 1.0f);
+  private float PHRASE_BOOST;
 
   private static final String[] FIELDS =
   { "url", "anchor", "content", "title", "host" };
 
-  private static final float[] FIELD_BOOSTS =
+  private final float[] FIELD_BOOSTS =
   { URL_BOOST, ANCHOR_BOOST, 1.0f, TITLE_BOOST, HOST_BOOST };
 
   /**
    * Set the boost factor for url matches, relative to content and anchor
    * matches
    */
-  public static void setUrlBoost(float boost) { URL_BOOST = boost; }
+  public  void setUrlBoost(float boost) { URL_BOOST = boost; }
 
   /** Set the boost factor for title/anchor matches, relative to url and
    * content matches. */
-  public static void setAnchorBoost(float boost) { ANCHOR_BOOST = boost; }
+  public  void setAnchorBoost(float boost) { ANCHOR_BOOST = boost; }
 
   /** Set the boost factor for sloppy phrase matches relative to unordered term
    * matches. */
-  public static void setPhraseBoost(float boost) { PHRASE_BOOST = boost; }
+  public  void setPhraseBoost(float boost) { PHRASE_BOOST = boost; }
 
   /** Set the maximum number of terms permitted between matching terms in a
    * sloppy phrase match. */
-  public static void setSlop(int slop) { SLOP = slop; }
+  public  void setSlop(int slop) { SLOP = slop; }
 
+private NutchConf nutchConf;
+
   public BooleanQuery filter(Query input, BooleanQuery output) {
     addTerms(input, output);
     addSloppyPhrases(input, output);
     return output;
   }
 
-  private static void addTerms(Query input, BooleanQuery output) {
+  private  void addTerms(Query input, BooleanQuery output) {
     Clause[] clauses = input.getClauses();
     for (int i = 0; i < clauses.length; i++) {
       Clause c = clauses[i];
@@ -95,11 +92,11 @@
 
         Clause o = c;
         if (c.isPhrase()) {                         // optimize phrase clauses
-          String[] opt = CommonGrams.optimizePhrase(c.getPhrase(), FIELDS[f]);
+          String[] opt = new CommonGrams(getConf()).optimizePhrase(c.getPhrase(), FIELDS[f]);
           if (opt.length==1) {
-            o = new Clause(new Term(opt[0]), c.isRequired(), c.isProhibited());
+            o = new Clause(new Term(opt[0]), c.isRequired(), c.isProhibited(), getConf());
           } else {
-            o = new Clause(new Phrase(opt), c.isRequired(), c.isProhibited());
+            o = new Clause(new Phrase(opt), c.isRequired(), c.isProhibited(), getConf());
           }
         }
 
@@ -112,7 +109,7 @@
     }
   }
 
-  private static void addSloppyPhrases(Query input, BooleanQuery output) {
+  private  void addSloppyPhrases(Query input, BooleanQuery output) {
     Clause[] clauses = input.getClauses();
     for (int f = 0; f < FIELDS.length; f++) {
 
@@ -145,7 +142,7 @@
   }
 
 
-  private static org.apache.lucene.search.Query
+  private  org.apache.lucene.search.Query
         termQuery(String field, Term term, float boost) {
     TermQuery result = new TermQuery(luceneTerm(field, term));
     result.setBoost(boost);
@@ -153,7 +150,7 @@
   }
 
   /** Utility to construct a Lucene exact phrase query for a Nutch phrase. */
-  private static org.apache.lucene.search.Query
+  private  org.apache.lucene.search.Query
        exactPhrase(Phrase nutchPhrase,
                    String field, float boost) {
     Term[] terms = nutchPhrase.getTerms();
@@ -170,4 +167,27 @@
                                                          Term term) {
     return new org.apache.lucene.index.Term(field, term.toString());
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        this.URL_BOOST  = conf.getFloat("query.url.boost", 4.0f);
+        this.ANCHOR_BOOST = conf.getFloat("query.anchor.boost", 2.0f);
+        this.TITLE_BOOST = conf.getFloat("query.title.boost", 1.5f);
+        this.HOST_BOOST  = conf.getFloat("query.host.boost", 2.0f);
+        this.PHRASE_BOOST  = conf.getFloat("query.phrase.boost", 1.0f);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
Index: src/plugin/protocol-ftp/src/java/org/apache/nutch/protocol/ftp/FtpResponse.java
===================================================================
--- src/plugin/protocol-ftp/src/java/org/apache/nutch/protocol/ftp/FtpResponse.java	(revision 367309)
+++ src/plugin/protocol-ftp/src/java/org/apache/nutch/protocol/ftp/FtpResponse.java	(working copy)
@@ -27,6 +27,7 @@
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
+import org.apache.nutch.util.NutchConf;
 
 import java.net.InetAddress;
 import java.net.URL;
@@ -64,6 +65,7 @@
   private ContentProperties headers = new ContentProperties();
 
   private final Ftp ftp;
+private NutchConf nutchConf;
 
   /** Returns the response code. */
   public int getCode() { return code; }
@@ -78,15 +80,16 @@
   public Content toContent() {
     return new Content(orig, base, content,
                        getHeader("Content-Type"),
-                       headers);
+                       headers, this.nutchConf);
   }
 
-  public FtpResponse(URL url, CrawlDatum datum, Ftp ftp)
+  public FtpResponse(URL url, CrawlDatum datum, Ftp ftp, NutchConf nutchConf)
     throws FtpException, IOException {
 
     this.orig = url.toString();
     this.base = url.toString();
     this.ftp = ftp;
+    this.nutchConf = nutchConf;
 
     if (!"ftp".equals(url.getProtocol()))
       throw new FtpException("Not a ftp url:" + url);
Index: src/plugin/protocol-ftp/src/java/org/apache/nutch/protocol/ftp/Ftp.java
===================================================================
--- src/plugin/protocol-ftp/src/java/org/apache/nutch/protocol/ftp/Ftp.java	(revision 367309)
+++ src/plugin/protocol-ftp/src/java/org/apache/nutch/protocol/ftp/Ftp.java	(working copy)
@@ -56,23 +56,23 @@
 
   static final int MAX_REDIRECTS = 5;
 
-  static int timeout = NutchConf.get().getInt("ftp.timeout", 10000);
+  int timeout;
 
-  static int maxContentLength = NutchConf.get().getInt("ftp.content.limit",64*1024);
+  int maxContentLength;
 
-  String userName = NutchConf.get().get("ftp.username", "anonymous");
-  String passWord = NutchConf.get().get("ftp.password", "anonymous@example.com");
+  String userName;
+  String passWord; 
 
   // typical/default server timeout is 120*1000 millisec.
   // better be conservative here
-  int serverTimeout = NutchConf.get().getInt("ftp.server.timeout", 60*1000);
+  int serverTimeout;
 
   // when to have client start anew
   long renewalTime = -1;
 
-  boolean keepConnection = NutchConf.get().getBoolean("ftp.keep.connection", false);
+  boolean keepConnection;
 
-  boolean followTalk = NutchConf.get().getBoolean("ftp.follow.talk", false);
+  boolean followTalk;
 
   // ftp client
   Client client = null;
@@ -86,7 +86,9 @@
   // http date format
   HttpDateFormat httpDateFormat = null;
 
+private NutchConf nutchConf;
 
+
   // constructor
   public Ftp() {
     this.httpDateFormat = new HttpDateFormat();
@@ -121,7 +123,7 @@
   
       while (true) {
         FtpResponse response;
-        response = new FtpResponse(u, datum, this);   // make a request
+        response = new FtpResponse(u, datum, this, getConf());   // make a request
   
         int code = response.getCode();
   
@@ -220,4 +222,30 @@
     ftp = null;
   }
 
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+   */
+  public void setConf(NutchConf conf) {
+      this.nutchConf = conf;
+      this.maxContentLength =  conf.getInt("ftp.content.limit",64*1024);
+      this.timeout =  conf.getInt("ftp.timeout", 10000);
+      this.userName =  conf.get("ftp.username", "anonymous");
+      this.passWord = conf.get("ftp.password", "anonymous@example.com");
+      this.serverTimeout =  conf.getInt("ftp.server.timeout", 60*1000);
+      this.keepConnection =  conf.getBoolean("ftp.keep.connection", false);
+      this.followTalk =  conf.getBoolean("ftp.follow.talk", false);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#getConf()
+   */
+  public NutchConf getConf() {
+      return this.nutchConf;
+  }
+
 }
Index: src/plugin/parse-text/src/java/org/apache/nutch/parse/text/TextParser.java
===================================================================
--- src/plugin/parse-text/src/java/org/apache/nutch/parse/text/TextParser.java	(revision 359225)
+++ src/plugin/parse-text/src/java/org/apache/nutch/parse/text/TextParser.java	(working copy)
@@ -24,7 +24,9 @@
 import org.apache.nutch.util.*;
 
 public class TextParser implements Parser {
-  public Parse getParse(Content content) {
+  private NutchConf nutchConf;
+
+public Parse getParse(Content content) {
     // copy content meta data through
     ContentProperties metadata = new ContentProperties();
     metadata.putAll(content.getMetadata());
@@ -38,7 +40,7 @@
       try {                                       // try to use named encoding
         text = new String(content.getContent(), encoding);
       } catch (java.io.UnsupportedEncodingException e) {
-        return new ParseStatus(e).getEmptyParse();
+        return new ParseStatus(e).getEmptyParse(getConf());
       }
     } else {
       // FIXME: implement charset detector. This code causes problem when 
@@ -48,7 +50,25 @@
 
     return new ParseImpl(text,
                          new ParseData(ParseStatus.STATUS_SUCCESS, "",
-                                       OutlinkExtractor.getOutlinks(text),
-                                       metadata));
+                                       OutlinkExtractor.getOutlinks(text, getConf()),
+                                       metadata, getConf()));
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
Index: src/plugin/creativecommons/src/test/org/creativecommons/nutch/TestCCParseFilter.java
===================================================================
--- src/plugin/creativecommons/src/test/org/creativecommons/nutch/TestCCParseFilter.java	(revision 359225)
+++ src/plugin/creativecommons/src/test/org/creativecommons/nutch/TestCCParseFilter.java	(working copy)
@@ -1,68 +1,70 @@
-/**
- * Copyright 2005 The Apache Software Foundation
- *
- * 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.creativecommons.nutch;
-
-import org.apache.nutch.parse.Parse;
-import org.apache.nutch.parse.ParseUtil;
-import org.apache.nutch.protocol.Content;
-import org.apache.nutch.protocol.ContentProperties;
-
-import java.util.Properties;
-import java.io.*;
-import java.net.URL;
-
-import junit.framework.TestCase;
-
-public class TestCCParseFilter extends TestCase {
-
-  private static final File testDir =
-    new File(System.getProperty("test.input"));
-
-  public void testPages() throws Exception {
-    pageTest(new File(testDir, "anchor.html"), "http://foo.com/",
-             "http://creativecommons.org/licenses/by-nc-sa/1.0", "a", null);
-    pageTest(new File(testDir, "rel.html"), "http://foo.com/",
-             "http://creativecommons.org/licenses/by-nc/2.0", "rel", null);
-    pageTest(new File(testDir, "rdf.html"), "http://foo.com/",
-             "http://creativecommons.org/licenses/by-nc/1.0", "rdf", "text");
-  }
-
-  public void pageTest(File file, String url,
-                       String license, String location, String type)
-    throws Exception {
-
-    String contentType = "text/html";
-    InputStream in = new FileInputStream(file);
-    ByteArrayOutputStream out = new ByteArrayOutputStream((int)file.length());
-    byte[] buffer = new byte[1024];
-    int i;
-    while ((i = in.read(buffer)) != -1) {
-      out.write(buffer, 0, i);
-    }
-    in.close();
-    byte[] bytes = out.toByteArray();
-
-    Content content =
-      new Content(url, url, bytes, contentType, new ContentProperties());
-    Parse parse = ParseUtil.parseByParserId("parse-html",content);
-
-    ContentProperties metadata = parse.getData().getMetadata();
-    assertEquals(license, metadata.get("License-Url"));
-    assertEquals(location, metadata.get("License-Location"));
-    assertEquals(type, metadata.get("Work-Type"));
-  }
-}
+/**
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * 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.creativecommons.nutch;
+
+import org.apache.nutch.parse.Parse;
+import org.apache.nutch.parse.ParseUtil;
+import org.apache.nutch.protocol.Content;
+import org.apache.nutch.protocol.ContentProperties;
+import org.apache.nutch.util.NutchConf;
+
+import java.util.Properties;
+import java.io.*;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+public class TestCCParseFilter extends TestCase {
+
+  private static final File testDir =
+    new File(System.getProperty("test.input"));
+
+  public void testPages() throws Exception {
+    pageTest(new File(testDir, "anchor.html"), "http://foo.com/",
+             "http://creativecommons.org/licenses/by-nc-sa/1.0", "a", null);
+    pageTest(new File(testDir, "rel.html"), "http://foo.com/",
+             "http://creativecommons.org/licenses/by-nc/2.0", "rel", null);
+    pageTest(new File(testDir, "rdf.html"), "http://foo.com/",
+             "http://creativecommons.org/licenses/by-nc/1.0", "rdf", "text");
+  }
+
+  public void pageTest(File file, String url,
+                       String license, String location, String type)
+    throws Exception {
+
+    String contentType = "text/html";
+    InputStream in = new FileInputStream(file);
+    ByteArrayOutputStream out = new ByteArrayOutputStream((int)file.length());
+    byte[] buffer = new byte[1024];
+    int i;
+    while ((i = in.read(buffer)) != -1) {
+      out.write(buffer, 0, i);
+    }
+    in.close();
+    byte[] bytes = out.toByteArray();
+
+    NutchConf nutchConf = new NutchConf();
+    Content content =
+      new Content(url, url, bytes, contentType, new ContentProperties(), nutchConf);
+    Parse parse = new ParseUtil(nutchConf).parseByParserId("parse-html",content);
+
+    ContentProperties metadata = parse.getData().getMetadata();
+    assertEquals(license, metadata.get("License-Url"));
+    assertEquals(location, metadata.get("License-Location"));
+    assertEquals(type, metadata.get("Work-Type"));
+  }
+}
Index: src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCIndexingFilter.java
===================================================================
--- src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCIndexingFilter.java	(revision 367309)
+++ src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCIndexingFilter.java	(working copy)
@@ -30,6 +30,7 @@
 
 import java.util.logging.Logger;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 import java.util.*;
 import java.net.URL;
@@ -43,6 +44,8 @@
   /** The name of the document field we use. */
   public static String FIELD = "cc";
 
+private NutchConf nutchConf;
+
   public Document filter(Document doc, Parse parse, UTF8 url, CrawlDatum datum, Inlinks inlinks)
     throws IndexingException {
     
@@ -100,4 +103,22 @@
     doc.add(Field.Keyword(FIELD, feature));
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCQueryFilter.java
===================================================================
--- src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCQueryFilter.java	(revision 359225)
+++ src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCQueryFilter.java	(working copy)
@@ -17,11 +17,28 @@
 package org.creativecommons.nutch;
 
 import org.apache.nutch.searcher.RawFieldQueryFilter;
+import org.apache.nutch.util.NutchConf;
 
 /** Handles "cc:" query clauses, causing them to search the "cc" field
  * indexed by CCIndexingFilter. */
 public class CCQueryFilter extends RawFieldQueryFilter {
-  public CCQueryFilter() {
+  private NutchConf nutchConf;
+
+public CCQueryFilter() {
     super(CCIndexingFilter.FIELD);
   }
+
+/* (non-Javadoc)
+ * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+ */
+public void setConf(NutchConf conf) {
+    this.nutchConf = conf;
 }
+
+/* (non-Javadoc)
+ * @see org.apache.nutch.util.NutchConfigurable#getConf()
+ */
+public NutchConf getConf() {
+    return this.nutchConf;
+}
+}
Index: src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCParseFilter.java
===================================================================
--- src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCParseFilter.java	(revision 359225)
+++ src/plugin/creativecommons/src/java/org/creativecommons/nutch/CCParseFilter.java	(working copy)
@@ -36,8 +36,6 @@
   public static final Logger LOG
     = LogFormatter.getLogger(CCParseFilter.class.getName());
 
-  private static final boolean EXCLUDE_UNLICENSED =
-    NutchConf.get().getBoolean("creativecommons.exclude.unlicensed", false);
 
   /** Walks DOM tree, looking for RDF in comments and licenses in anchors.*/
   public static class Walker {
@@ -52,7 +50,7 @@
     }
 
     /** Scan the document adding attributes to metadata.*/
-    public static void walk(Node doc, URL base, ContentProperties metadata)
+    public static void walk(Node doc, URL base, ContentProperties metadata, NutchConf nutchConf)
       throws ParseException {
 
       // walk the DOM tree, scanning for license data
@@ -71,7 +69,7 @@
       } else if (walker.anchorLicense != null) {  // 3rd: anchor w/ CC license
         licenseLocation = "a";
         licenseUrl = walker.anchorLicense.toString();
-      } else if (EXCLUDE_UNLICENSED) {
+      } else if (nutchConf.getBoolean("creativecommons.exclude.unlicensed", false)) {
         throw new ParseException("No CC license.  Excluding.");
       }
 
@@ -251,6 +249,8 @@
     WORK_TYPE_NAMES.put("http://purl.org/dc/dcmitype/Image", "image");
   }
 
+private NutchConf nutchConf;
+
   /** Adds metadata or otherwise modifies a parse of an HTML document, given
    * the DOM tree of a page. */
   public Parse filter(Content content, Parse parse, HTMLMetaTags metaTags, DocumentFragment doc) {
@@ -260,17 +260,31 @@
     try {
       base = new URL(content.getBaseUrl());
     } catch (MalformedURLException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     }
 
     try {
       // extract license metadata
-      Walker.walk(doc, base, parse.getData().getMetadata());
+      Walker.walk(doc, base, parse.getData().getMetadata(), getConf());
     } catch (ParseException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     }
 
     return parse;
   }
 
+/* (non-Javadoc)
+ * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+ */
+public void setConf(NutchConf conf) {
+   this.nutchConf = conf;
 }
+
+/* (non-Javadoc)
+ * @see org.apache.nutch.util.NutchConfigurable#getConf()
+ */
+public NutchConf getConf() {
+    return this.nutchConf;
+}
+
+}
Index: src/plugin/parse-rtf/src/test/org/apache/nutch/parse/rtf/TestRTFParser.java
===================================================================
--- src/plugin/parse-rtf/src/test/org/apache/nutch/parse/rtf/TestRTFParser.java	(revision 359225)
+++ src/plugin/parse-rtf/src/test/org/apache/nutch/parse/rtf/TestRTFParser.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.nutch.protocol.Protocol;
 import org.apache.nutch.protocol.ProtocolException;
 import org.apache.nutch.protocol.ProtocolFactory;
+import org.apache.nutch.util.NutchConf;
 
 import java.util.Properties;
 
@@ -60,11 +61,12 @@
     Content content;
     Parse parse;
 
+    NutchConf nutchConf = new NutchConf();
     urlString = "file:" + sampleDir + fileSeparator + rtfFile;
-    protocol = ProtocolFactory.getProtocol(urlString);
+    protocol = new ProtocolFactory(nutchConf).getProtocol(urlString);
     content = protocol.getContent(urlString);
 
-    parse = ParseUtil.parseByParserId("parse-rtf",content);
+    parse = new ParseUtil(nutchConf).parseByParserId("parse-rtf",content);
     String text = parse.getText();
     assertEquals("The quick brown fox jumps over the lazy dog", text.trim());
 
Index: src/plugin/parse-rtf/src/java/org/apache/nutch/parse/rtf/RTFParseFactory.java
===================================================================
--- src/plugin/parse-rtf/src/java/org/apache/nutch/parse/rtf/RTFParseFactory.java	(revision 359225)
+++ src/plugin/parse-rtf/src/java/org/apache/nutch/parse/rtf/RTFParseFactory.java	(working copy)
@@ -17,8 +17,8 @@
 package org.apache.nutch.parse.rtf;
 
 import org.apache.nutch.parse.*;
-import org.apache.nutch.parse.ParseException;
 import org.apache.nutch.protocol.Content;
+import org.apache.nutch.util.NutchConf;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStreamReader;
@@ -33,7 +33,9 @@
  */
 public class RTFParseFactory implements Parser {
 
-  public Parse getParse(Content content) throws ParseException {
+  private NutchConf nutchConf;
+
+public Parse getParse(Content content) throws ParseException {
     byte[] raw = content.getContent();
     Reader reader = new InputStreamReader(new ByteArrayInputStream(raw));
     RTFParserDelegateImpl delegate = new RTFParserDelegateImpl();
@@ -63,9 +65,29 @@
 
     return new ParseImpl(text, 
                          new ParseData(title,
-                                       OutlinkExtractor.getOutlinks(text),
+                                       OutlinkExtractor.getOutlinks(text, this.nutchConf),
                                        metadata));
   }
 
 
+/*
+ * (non-Javadoc)
+ * 
+ * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+ */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
+
 }
Index: src/plugin/query-url/src/java/org/apache/nutch/searcher/url/URLQueryFilter.java
===================================================================
--- src/plugin/query-url/src/java/org/apache/nutch/searcher/url/URLQueryFilter.java	(revision 359225)
+++ src/plugin/query-url/src/java/org/apache/nutch/searcher/url/URLQueryFilter.java	(working copy)
@@ -17,11 +17,32 @@
 package org.apache.nutch.searcher.url;
 
 import org.apache.nutch.searcher.FieldQueryFilter;
+import org.apache.nutch.util.NutchConf;
 
 /** Handles "url:" query clauses, causing them to search the field indexed by
  * BasicIndexingFilter. */
 public class URLQueryFilter extends FieldQueryFilter {
-  public URLQueryFilter() {
+  private NutchConf nutchConf;
+
+public URLQueryFilter() {
     super("url");
   }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+   */
+  public void setConf(NutchConf conf) {
+      this.nutchConf = conf;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.nutch.util.NutchConfigurable#getConf()
+   */
+  public NutchConf getConf() {
+      return this.nutchConf;
+  }
 }
Index: src/plugin/parse-mp3/src/java/org/apache/nutch/parse/mp3/MetadataCollector.java
===================================================================
--- src/plugin/parse-mp3/src/java/org/apache/nutch/parse/mp3/MetadataCollector.java	(revision 359225)
+++ src/plugin/parse-mp3/src/java/org/apache/nutch/parse/mp3/MetadataCollector.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.nutch.parse.mp3;
 
 import org.apache.nutch.parse.Outlink;
+import org.apache.nutch.util.NutchConf;
 
 import java.net.MalformedURLException;
 import java.util.ArrayList;
@@ -34,7 +35,12 @@
   private String album = null;
   private ArrayList links = new ArrayList();
   private String text = "";
+  private NutchConf nutchConf;
 
+  public MetadataCollector(NutchConf nutchConf){
+      this.nutchConf = nutchConf;
+  }
+  
   public void notifyProperty(String name, String value) throws MalformedURLException {
     if (name.equals("TIT2-Text"))
       setTitle(value);
@@ -44,7 +50,7 @@
       setArtist(value);
 
     if (name.indexOf("URL Link") > -1) {
-      links.add(new Outlink(value, ""));
+      links.add(new Outlink(value, "", this.nutchConf));
     } else if (name.indexOf("Text") > -1) {
       text += value + "\n";
     }
Index: src/plugin/parse-mp3/src/java/org/apache/nutch/parse/mp3/MP3Parser.java
===================================================================
--- src/plugin/parse-mp3/src/java/org/apache/nutch/parse/mp3/MP3Parser.java	(revision 359225)
+++ src/plugin/parse-mp3/src/java/org/apache/nutch/parse/mp3/MP3Parser.java	(working copy)
@@ -19,6 +19,7 @@
 
 import org.apache.nutch.parse.*;
 import org.apache.nutch.protocol.Content;
+import org.apache.nutch.util.NutchConf;
 import org.farng.mp3.MP3File;
 import org.farng.mp3.TagException;
 import org.farng.mp3.id3.AbstractID3v2;
@@ -39,7 +40,8 @@
 
 public class MP3Parser implements Parser {
 
-  private MetadataCollector metadataCollector = new MetadataCollector();
+  private MetadataCollector metadataCollector;
+private NutchConf nutchConf;
 
   public Parse getParse(Content content) throws ParseException {
     Parse parse = null;
@@ -84,7 +86,7 @@
     metadataCollector.notifyProperty("TYER-Text", tag.getYear());
     ParseData parseData = new ParseData(metadataCollector.getTitle(),
         metadataCollector.getOutlinks(),
-        metadataCollector.getData());
+        metadataCollector.getData(), getConf());
     return new ParseImpl(metadataCollector.getText(), parseData);
   }
 
@@ -113,4 +115,24 @@
   }
 
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        this.metadataCollector = new MetadataCollector(conf);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
+
 }
Index: src/plugin/index-more/src/java/org/apache/nutch/indexer/more/MoreIndexingFilter.java
===================================================================
--- src/plugin/index-more/src/java/org/apache/nutch/indexer/more/MoreIndexingFilter.java	(revision 367309)
+++ src/plugin/index-more/src/java/org/apache/nutch/indexer/more/MoreIndexingFilter.java	(working copy)
@@ -75,13 +75,10 @@
     = LogFormatter.getLogger(MoreIndexingFilter.class.getName());
 
   /** A flag that tells if magic resolution must be performed */
-  private final static boolean MAGIC =
-        NutchConf.get().getBoolean("mime.type.magic", true);
+  private boolean MAGIC;
 
   /** Get the MimeTypes resolver instance. */
-  private final static MimeTypes MIME = 
-        MimeTypes.get(NutchConf.get().get("mime.types.file"));
-
+  private MimeTypes MIME; 
   
   public Document filter(Document doc, Parse parse, UTF8 url, CrawlDatum datum, Inlinks inlinks)
     throws IndexingException {
@@ -247,6 +244,8 @@
   // HTTP header "Content-Disposition". Typically it looks like:
   // Content-Disposition: inline; filename="foo.ppt"
   private PatternMatcher matcher = new Perl5Matcher();
+
+private NutchConf nutchConf;
   static Perl5Pattern patterns[] = {null, null};
   static {
     Perl5Compiler compiler = new Perl5Compiler();
@@ -302,4 +301,24 @@
     return normalized;
   }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        MAGIC = conf.getBoolean("mime.type.magic", true);
+        MIME = MimeTypes.get(getConf().get("mime.types.file")); 
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
 }
Index: src/plugin/parse-ext/src/test/org/apache/nutch/parse/ext/TestExtParser.java
===================================================================
--- src/plugin/parse-ext/src/test/org/apache/nutch/parse/ext/TestExtParser.java	(revision 367309)
+++ src/plugin/parse-ext/src/test/org/apache/nutch/parse/ext/TestExtParser.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.nutch.parse.Parse;
 import org.apache.nutch.parse.ParseUtil;
 import org.apache.nutch.parse.ParseException;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.crawl.CrawlDatum;
@@ -79,7 +80,7 @@
     fos.close();
 
     // get nutch content
-    Protocol protocol = ProtocolFactory.getProtocol(urlString);
+    Protocol protocol = new ProtocolFactory(new NutchConf()).getProtocol(urlString);
     content = protocol.getProtocolOutput(new UTF8(urlString), new CrawlDatum()).getContent();
     protocol = null;
   }
@@ -103,18 +104,19 @@
       return;
     }
 
+    NutchConf nutchConf = new NutchConf();
     // loop alternately, total 10*2 times of invoking external command
     for (int i=0; i<10; i++) {
       // check external parser that does 'cat'
       contentType = "application/vnd.nutch.example.cat";
       content.setContentType(contentType);
-      parse = ParseUtil.parseByParserId("parse-ext", content);
+      parse = new ParseUtil(nutchConf).parseByParserId("parse-ext", content);
       assertEquals(expectedText,parse.getText());
 
       // check external parser that does 'md5sum'
       contentType = "application/vnd.nutch.example.md5sum";
       content.setContentType(contentType);
-      parse = ParseUtil.parseByParserId("parse-ext", content);
+      parse = new ParseUtil(nutchConf).parseByParserId("parse-ext", content);
       assertTrue(parse.getText().startsWith(expectedMD5sum));
     }
   }
Index: src/plugin/parse-ext/src/java/org/apache/nutch/parse/ext/ExtParser.java
===================================================================
--- src/plugin/parse-ext/src/java/org/apache/nutch/parse/ext/ExtParser.java	(revision 359225)
+++ src/plugin/parse-ext/src/java/org/apache/nutch/parse/ext/ExtParser.java	(working copy)
@@ -28,6 +28,7 @@
 
 import org.apache.nutch.util.LogFormatter;
 import org.apache.nutch.util.CommandRunner;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.plugin.Extension;
 import org.apache.nutch.plugin.PluginRepository;
@@ -57,38 +58,12 @@
   // handy map from String contentType to String[] {command, timeoutString}
   static Hashtable TYPE_PARAMS_MAP = new Hashtable();
 
-  // set TYPE_PARAMS_MAP using plugin.xml of this plugin
-  static {
-    Extension[] extensions = PluginRepository.getInstance()
-      .getExtensionPoint("org.apache.nutch.parse.Parser").getExtensions();
+private NutchConf nutchConf;
 
-    String contentType, command, timeoutString;
+private boolean loaded = false;
 
-    for (int i = 0; i < extensions.length; i++) {
-      Extension extension = extensions[i];
+  public ExtParser () { }
 
-      // only look for extensions defined by plugin parse-ext
-      if (!extension.getDescriptor().getPluginId().equals("parse-ext"))
-        continue;
-
-      contentType = extension.getAttribute("contentType");
-      if (contentType == null || contentType.equals(""))
-        continue;
-
-      command = extension.getAttribute("command");
-      if (command == null || command.equals(""))
-        continue;
-
-      timeoutString = extension.getAttribute("timeout");
-      if (timeoutString == null || timeoutString.equals(""))
-        timeoutString = "" + TIMEOUT_DEFAULT;
-
-      TYPE_PARAMS_MAP.put(contentType, new String[]{command, timeoutString});
-    }
-  }
-
-  public ExtParser () {}
-
   public Parse getParse(Content content) {
 
     String contentType = content.getContentType();
@@ -96,7 +71,7 @@
     String[] params = (String[]) TYPE_PARAMS_MAP.get(contentType);
     if (params == null)
       return new ParseStatus(ParseStatus.FAILED,
-                      "No external command defined for contentType: " + contentType).getEmptyParse();
+                      "No external command defined for contentType: " + contentType).getEmptyParse(getConf());
 
     String command = params[0];
     int timeout = Integer.parseInt(params[1]);
@@ -118,7 +93,7 @@
           return new ParseStatus(ParseStatus.FAILED, ParseStatus.FAILED_TRUNCATED,
                 "Content truncated at " + raw.length
             +" bytes. Parser can't handle incomplete "
-            + contentType + " file.").getEmptyParse();
+            + contentType + " file.").getEmptyParse(getConf());
       }
 
       ByteArrayOutputStream os = new ByteArrayOutputStream(BUFFER_SIZE);
@@ -138,12 +113,12 @@
       if (cr.getExitValue() != 0)
         return new ParseStatus(ParseStatus.FAILED,
                         "External command " + command
-                        + " failed with error: " + es.toString()).getEmptyParse();
+                        + " failed with error: " + es.toString()).getEmptyParse(getConf());
 
       text = os.toString();
 
     } catch (Exception e) { // run time exception
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     }
 
     if (text == null)
@@ -153,14 +128,61 @@
       title = "";
 
     // collect outlink
-    Outlink[] outlinks = OutlinkExtractor.getOutlinks(text);
+    Outlink[] outlinks = OutlinkExtractor.getOutlinks(text, getConf());
 
     // collect meta data
     ContentProperties metaData = new ContentProperties();
     metaData.putAll(content.getMetadata()); // copy through
 
-    ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metaData);
+    ParseData parseData = new ParseData(ParseStatus.STATUS_SUCCESS, title, outlinks, metaData, getConf());
     return new ParseImpl(text, parseData);
   }
+  
+  
 
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        Extension[] extensions = conf.getPluginRepository().getExtensionPoint("org.apache.nutch.parse.Parser")
+                .getExtensions();
+
+        String contentType, command, timeoutString;
+
+        for (int i = 0; i < extensions.length; i++) {
+            Extension extension = extensions[i];
+
+            // only look for extensions defined by plugin parse-ext
+            if (!extension.getDescriptor().getPluginId().equals("parse-ext"))
+                continue;
+
+            contentType = extension.getAttribute("contentType");
+            if (contentType == null || contentType.equals(""))
+                continue;
+
+            command = extension.getAttribute("command");
+            if (command == null || command.equals(""))
+                continue;
+
+            timeoutString = extension.getAttribute("timeout");
+            if (timeoutString == null || timeoutString.equals(""))
+                timeoutString = "" + TIMEOUT_DEFAULT;
+
+            TYPE_PARAMS_MAP.put(contentType, new String[] { command, timeoutString });
+        }
+    }
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
+
+
 }
Index: src/plugin/ontology/src/test/org/apache/nutch/ontology/TestOntology.java
===================================================================
--- src/plugin/ontology/src/test/org/apache/nutch/ontology/TestOntology.java	(revision 359225)
+++ src/plugin/ontology/src/test/org/apache/nutch/ontology/TestOntology.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.nutch.parse.Parser;
 import org.apache.nutch.parse.Parse;
 import org.apache.nutch.parse.ParseException;
+import org.apache.nutch.util.NutchConf;
 
 import junit.framework.TestCase;
 
@@ -66,7 +67,7 @@
 
     if (ontology==null) {
       try {
-        ontology = OntologyFactory.getOntology();
+        ontology = new OntologyFactory().getOntology(new NutchConf());
       } catch (Exception e) {
         throw new Exception("Failed to instantiate ontology");
       }
Index: src/plugin/ontology/src/java/org/apache/nutch/ontology/OntologyImpl.java
===================================================================
--- src/plugin/ontology/src/java/org/apache/nutch/ontology/OntologyImpl.java	(revision 359225)
+++ src/plugin/ontology/src/java/org/apache/nutch/ontology/OntologyImpl.java	(working copy)
@@ -325,9 +325,10 @@
 
   public static void main( String[] args ) throws Exception {
 
-    Ontology ontology = OntologyFactory.getOntology();
+    NutchConf nutchConf = new NutchConf(); 
+    Ontology ontology = new OntologyFactory().getOntology(nutchConf);
 
-    String urls = NutchConf.get().get("extension.ontology.urls");
+    String urls = nutchConf.get("extension.ontology.urls");
     if (urls==null || urls.trim().equals("")) {
       LOG.severe("No ontology url found.");
       return;
Index: src/plugin/parse-html/src/test/org/apache/nutch/parse/html/TestDOMContentUtils.java
===================================================================
--- src/plugin/parse-html/src/test/org/apache/nutch/parse/html/TestDOMContentUtils.java	(revision 359225)
+++ src/plugin/parse-html/src/test/org/apache/nutch/parse/html/TestDOMContentUtils.java	(working copy)
@@ -19,6 +19,7 @@
 import junit.framework.TestCase;
 
 import org.apache.nutch.parse.Outlink;
+import org.apache.nutch.util.NutchConf;
 
 import java.io.ByteArrayInputStream;
 import java.net.MalformedURLException;
@@ -174,6 +175,7 @@
   }
 
   private static void setup() {
+    NutchConf nutchConf = new NutchConf();
     DOMFragmentParser parser= new DOMFragmentParser();
     for (int i= 0; i < testPages.length; i++) {
         DocumentFragment node= 
@@ -192,36 +194,36 @@
     try {
      answerOutlinks = new Outlink[][]{ 
          {
-           new Outlink("http://www.nutch.org", "anchor"),
+           new Outlink("http://www.nutch.org", "anchor", nutchConf),
          },
          {
-           new Outlink("http://www.nutch.org/", "home"),
-           new Outlink("http://www.nutch.org/docs/bot.html", "bots"),
+           new Outlink("http://www.nutch.org/", "home", nutchConf),
+           new Outlink("http://www.nutch.org/docs/bot.html", "bots", nutchConf),
          },
          {
-           new Outlink("http://www.nutch.org/", "separate this"),
-           new Outlink("http://www.nutch.org/docs/ok", "from this"),
+           new Outlink("http://www.nutch.org/", "separate this", nutchConf),
+           new Outlink("http://www.nutch.org/docs/ok", "from this", nutchConf),
          },
          {
-           new Outlink("http://www.nutch.org/", "home"),
-           new Outlink("http://www.nutch.org/docs/1", "1"),
-           new Outlink("http://www.nutch.org/docs/2", "2"),
+           new Outlink("http://www.nutch.org/", "home", nutchConf),
+           new Outlink("http://www.nutch.org/docs/1", "1", nutchConf),
+           new Outlink("http://www.nutch.org/docs/2", "2", nutchConf),
          },
          {
-           new Outlink("http://www.nutch.org/frames/top.html", ""),
-           new Outlink("http://www.nutch.org/frames/left.html", ""),
-           new Outlink("http://www.nutch.org/frames/invalid.html", ""),
-           new Outlink("http://www.nutch.org/frames/right.html", ""),
+           new Outlink("http://www.nutch.org/frames/top.html", "", nutchConf),
+           new Outlink("http://www.nutch.org/frames/left.html", "", nutchConf),
+           new Outlink("http://www.nutch.org/frames/invalid.html", "", nutchConf),
+           new Outlink("http://www.nutch.org/frames/right.html", "", nutchConf),
          },
          {
-           new Outlink("http://www.nutch.org/maps/logo.gif", ""),
-           new Outlink("http://www.nutch.org/index.html", ""),
-           new Outlink("http://www.nutch.org/maps/#bottom", ""),
-           new Outlink("http://www.nutch.org/bot.html", ""),
-           new Outlink("http://www.nutch.org/docs/index.html", ""),
+           new Outlink("http://www.nutch.org/maps/logo.gif", "", nutchConf),
+           new Outlink("http://www.nutch.org/index.html", "", nutchConf),
+           new Outlink("http://www.nutch.org/maps/#bottom", "", nutchConf),
+           new Outlink("http://www.nutch.org/bot.html", "", nutchConf),
+           new Outlink("http://www.nutch.org/docs/index.html", "", nutchConf),
          },
          {
-             new Outlink("http://www.nutch.org/index.html", "whitespace test"),
+             new Outlink("http://www.nutch.org/index.html", "whitespace test", nutchConf),
          },
          {
          }
@@ -282,7 +284,7 @@
       setup();
     for (int i= 0; i < testPages.length; i++) {
       ArrayList outlinks= new ArrayList();
-      DOMContentUtils.getOutlinks(testBaseHrefURLs[i], outlinks, testDOMs[i]);
+      DOMContentUtils.getOutlinks(testBaseHrefURLs[i], outlinks, testDOMs[i], new NutchConf());
       Outlink[] outlinkArr= new Outlink[outlinks.size()];
       outlinkArr= (Outlink[]) outlinks.toArray(outlinkArr);
       compareOutlinks(answerOutlinks[i], outlinkArr);
Index: src/plugin/parse-html/src/java/org/apache/nutch/parse/html/HtmlParser.java
===================================================================
--- src/plugin/parse-html/src/java/org/apache/nutch/parse/html/HtmlParser.java	(revision 359225)
+++ src/plugin/parse-html/src/java/org/apache/nutch/parse/html/HtmlParser.java	(working copy)
@@ -51,7 +51,7 @@
     Pattern.compile("charset=\\s*([a-z][_\\-0-9a-z]*)",
                     Pattern.CASE_INSENSITIVE);
   
-  private static String parserImpl = NutchConf.get().get("parser.html.impl", "neko");
+  private String parserImpl;
 
   /**
    * Given a <code>byte[]</code> representing an html file of an 
@@ -91,9 +91,12 @@
   }
 
 
-  private static String defaultCharEncoding =
-    NutchConf.get().get("parser.character.encoding.default", "windows-1252");
+  private String defaultCharEncoding;
 
+  private NutchConf nutchConf;
+
+  private HtmlParseFilters htmlParseFilters;
+
   public Parse getParse(Content content) {
     HTMLMetaTags metaTags = new HTMLMetaTags();
 
@@ -101,7 +104,7 @@
     try {
       base = new URL(content.getBaseUrl());
     } catch (MalformedURLException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     }
 
     String text = "";
@@ -151,14 +154,14 @@
       LOG.fine("Parsing...");
       root = parse(input);
     } catch (IOException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     } catch (DOMException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     } catch (SAXException e) {
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     } catch (Exception e) {
       e.printStackTrace();
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     }
       
     // get meta directives
@@ -180,7 +183,7 @@
       ArrayList l = new ArrayList();              // extract outlinks
       URL baseTag = DOMContentUtils.getBase(root);
       LOG.fine("Getting links...");
-      DOMContentUtils.getOutlinks(baseTag!=null?baseTag:base, l, root);
+      DOMContentUtils.getOutlinks(baseTag!=null?baseTag:base, l, root, getConf());
       outlinks = (Outlink[])l.toArray(new Outlink[l.size()]);
       LOG.fine("found "+outlinks.length+" outlinks in "+content.getUrl());
     }
@@ -196,14 +199,14 @@
       status.setMinorCode(ParseStatus.SUCCESS_REDIRECT);
       status.setMessage(metaTags.getRefreshHref().toString());
     }
-    ParseData parseData = new ParseData(status, title, outlinks, metadata);
+    ParseData parseData = new ParseData(status, title, outlinks, metadata, getConf());
     Parse parse = new ParseImpl(text, parseData);
 
     // run filters on parse
-    return HtmlParseFilters.filter(content, parse, metaTags, root);
+    return this.htmlParseFilters.filter(content, parse, metaTags, root);
   }
 
-  private DocumentFragment parse(InputSource input) throws Exception {
+private DocumentFragment parse(InputSource input) throws Exception {
     if (parserImpl.equalsIgnoreCase("tagsoup"))
       return parseTagSoup(input);
     else return parseNeko(input);
@@ -267,10 +270,31 @@
     in.readFully(bytes);
     Parse parse = new HtmlParser().getParse(new Content(url,url,
                                                         bytes,"text/html",
-                                                        new ContentProperties()));
+                                                        new ContentProperties(), new NutchConf()));
     System.out.println("data: "+parse.getData());
 
     System.out.println("text: "+parse.getText());
     
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+        this.htmlParseFilters = new HtmlParseFilters(getConf());
+        this.parserImpl = getConf().get("parser.html.impl", "neko");
+        this.defaultCharEncoding = getConf().get("parser.character.encoding.default", "windows-1252");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
Index: src/plugin/parse-html/src/java/org/apache/nutch/parse/html/DOMContentUtils.java
===================================================================
--- src/plugin/parse-html/src/java/org/apache/nutch/parse/html/DOMContentUtils.java	(revision 359225)
+++ src/plugin/parse-html/src/java/org/apache/nutch/parse/html/DOMContentUtils.java	(working copy)
@@ -22,6 +22,7 @@
 import java.util.HashMap;
 
 import org.apache.nutch.parse.Outlink;
+import org.apache.nutch.util.NutchConf;
 
 import org.w3c.dom.*;
 
@@ -286,7 +287,7 @@
    * nekohtml).
    */
   public static final void getOutlinks(URL base, ArrayList outlinks, 
-                                       Node node) {
+                                       Node node, NutchConf nutchConf) {
 
     NodeList children = node.getChildNodes();
     int childLen= 0;
@@ -322,7 +323,7 @@
             try {
               URL url = new URL(base, target);
               outlinks.add(new Outlink(url.toString(),
-                                       linkText.toString().trim()));
+                                       linkText.toString().trim(), nutchConf));
             } catch (MalformedURLException e) {
               // don't care
             }
@@ -332,7 +333,7 @@
       }
     }
     for ( int i = 0; i < childLen; i++ ) {
-      getOutlinks(base, outlinks, children.item(i));
+      getOutlinks(base, outlinks, children.item(i), nutchConf);
     }
   }
 
Index: src/plugin/parse-mspowerpoint/src/test/org/apache/nutch/parse/mspowerpoint/TestMSPowerPointParser.java
===================================================================
--- src/plugin/parse-mspowerpoint/src/test/org/apache/nutch/parse/mspowerpoint/TestMSPowerPointParser.java	(revision 367309)
+++ src/plugin/parse-mspowerpoint/src/test/org/apache/nutch/parse/mspowerpoint/TestMSPowerPointParser.java	(working copy)
@@ -34,6 +34,7 @@
 import org.apache.nutch.protocol.Protocol;
 import org.apache.nutch.protocol.ProtocolFactory;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 import org.apache.nutch.io.UTF8;
 import org.apache.nutch.crawl.CrawlDatum;
@@ -105,7 +106,7 @@
     this.urlString = createUrl(this.testFile.getName());
 
     System.out.println("Testing file: " + this.urlString + "...");
-    this.protocol = ProtocolFactory.getProtocol(this.urlString);
+    this.protocol =new  ProtocolFactory(new NutchConf()).getProtocol(this.urlString);
     this.content = this.protocol.getProtocolOutput(new UTF8(this.urlString), new CrawlDatum()).getContent();
   }
 
@@ -125,7 +126,7 @@
    */
   public void testContent() throws Exception {
 
-    Parse parse = ParseUtil.parseByParserId("parse-mspowerpoint",this.content);
+    Parse parse = new ParseUtil(new NutchConf()).parseByParserId("parse-mspowerpoint",this.content);
 
     ParseData data = parse.getData();
     String text = parse.getText();
@@ -162,7 +163,7 @@
    */
   public void testMeta() throws Exception {
 
-    Parse parse = ParseUtil.parseByParserId("parse-mspowerpoint",content);
+    Parse parse = new ParseUtil(new NutchConf()).parseByParserId("parse-mspowerpoint",content);
     
     ParseData data = parse.getData();
 
Index: src/plugin/parse-mspowerpoint/src/java/org/apache/nutch/parse/mspowerpoint/MSPowerPointParser.java
===================================================================
--- src/plugin/parse-mspowerpoint/src/java/org/apache/nutch/parse/mspowerpoint/MSPowerPointParser.java	(revision 359225)
+++ src/plugin/parse-mspowerpoint/src/java/org/apache/nutch/parse/mspowerpoint/MSPowerPointParser.java	(working copy)
@@ -32,6 +32,7 @@
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.protocol.ContentProperties;
 import org.apache.nutch.util.LogFormatter;
+import org.apache.nutch.util.NutchConf;
 
 /**
  * Nutch-Parser for parsing MS PowerPoint slides ( mime type:
@@ -51,6 +52,8 @@
   private static final Logger LOG = LogFormatter
       .getLogger(MSPowerPointParser.class.getName());
 
+private NutchConf nutchConf;
+
   /**
    * 
    */
@@ -77,7 +80,7 @@
     ContentProperties prop = new ContentProperties();
     prop.setProperty("Content-Length", "" + raw.length);
 
-    Content content = new Content(file, file, raw, MIME_TYPE, prop);
+    Content content = new Content(file, file, raw, MIME_TYPE, prop, new NutchConf());
 
     System.out.println(ppe.getParse(content).getText());
   }
@@ -106,7 +109,7 @@
                 + raw.length
                 + " bytes. Please increase <protocol>.content.limit at nutch-default.xml. "
                 + "Parser can't handle incomplete PowerPoint files.")
-            .getEmptyParse();
+            .getEmptyParse(getConf());
       }
 
       final PPTExtractor extractor = new PPTExtractor(new ByteArrayInputStream(
@@ -114,11 +117,11 @@
 
       plainText = extractor.getText();
       properties = extractor.getProperties();
-      outlinks = OutlinkExtractor.getOutlinks(plainText, content.getUrl());
+      outlinks = OutlinkExtractor.getOutlinks(plainText, content.getUrl(), getConf());
 
     } catch (Exception e) {
       LOG.throwing(this.getClass().getName(), "getParse", e);
-      return new ParseStatus(e).getEmptyParse();
+      return new ParseStatus(e).getEmptyParse(getConf());
     }
 
     // collect meta data
@@ -140,7 +143,7 @@
     }
 
     final ParseStatus status = new ParseStatus(ParseStatus.SUCCESS);
-    final ParseData parseData = new ParseData(status, title, outlinks, metadata);
+    final ParseData parseData = new ParseData(status, title, outlinks, metadata, getConf());
 
     LOG.finest("PowerPoint file parsed sucessful.");
     return new ParseImpl(plainText, parseData);
@@ -161,4 +164,22 @@
     }
 
   }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#setConf(org.apache.nutch.util.NutchConf)
+     */
+    public void setConf(NutchConf conf) {
+        this.nutchConf = conf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.nutch.util.NutchConfigurable#getConf()
+     */
+    public NutchConf getConf() {
+        return this.nutchConf;
+    }
 }
