Index: src/java/org/apache/nutch/scoring/ScoringFilters.java
===================================================================
--- src/java/org/apache/nutch/scoring/ScoringFilters.java	(revision 1518249)
+++ src/java/org/apache/nutch/scoring/ScoringFilters.java	(working copy)
@@ -17,11 +17,16 @@
 
 package org.apache.nutch.scoring;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map.Entry;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.io.Text;
 import org.apache.nutch.crawl.CrawlDatum;
 import org.apache.nutch.crawl.Inlinks;
 import org.apache.nutch.indexer.NutchDocument;
@@ -29,15 +34,13 @@
 import org.apache.nutch.parse.ParseData;
 import org.apache.nutch.plugin.Extension;
 import org.apache.nutch.plugin.ExtensionPoint;
+import org.apache.nutch.plugin.PluginRepository;
 import org.apache.nutch.plugin.PluginRuntimeException;
-import org.apache.nutch.plugin.PluginRepository;
 import org.apache.nutch.protocol.Content;
 import org.apache.nutch.util.ObjectCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.conf.Configured;
-import org.apache.hadoop.io.Text;
-
 /**
  * Creates and caches {@link ScoringFilter} implementing plugins.
  * 
@@ -45,102 +48,131 @@
  */
 public class ScoringFilters extends Configured implements ScoringFilter {
 
-  private ScoringFilter[] filters;
+    private static final Logger LOG = LoggerFactory
+            .getLogger(ScoringFilters.class);
 
-  public ScoringFilters(Configuration conf) {
-    super(conf);
-    ObjectCache objectCache = ObjectCache.get(conf);
-    String order = conf.get("scoring.filter.order");
-    this.filters = (ScoringFilter[]) objectCache.getObject(ScoringFilter.class.getName());
+    private ScoringFilter[] filters;
 
-    if (this.filters == null) {
-      String[] orderedFilters = null;
-      if (order != null && !order.trim().equals("")) {
-        orderedFilters = order.trim().split("\\s+");
-      }
+    public ScoringFilters(Configuration conf) {
+        super(conf);
+        ObjectCache objectCache = ObjectCache.get(conf);
+        String order = conf.get("scoring.filter.order");
+        this.filters = (ScoringFilter[]) objectCache
+                .getObject(ScoringFilter.class.getName());
 
-      try {
-        ExtensionPoint point = PluginRepository.get(conf).getExtensionPoint(ScoringFilter.X_POINT_ID);
-        if (point == null) throw new RuntimeException(ScoringFilter.X_POINT_ID + " not found.");
-        Extension[] extensions = point.getExtensions();
-        HashMap<String, ScoringFilter> filterMap =
-          new HashMap<String, ScoringFilter>();
-        for (int i = 0; i < extensions.length; i++) {
-          Extension extension = extensions[i];
-          ScoringFilter filter = (ScoringFilter) extension.getExtensionInstance();
-          if (!filterMap.containsKey(filter.getClass().getName())) {
-            filterMap.put(filter.getClass().getName(), filter);
-          }
+        if (this.filters == null) {
+            List<String> orderOfFilters = new ArrayList<String>();
+            boolean userDefinedOrder = false;
+            if (order != null && !order.trim().equals("")) {
+                orderOfFilters = Arrays.asList(order.trim().split("\\s+"));
+                userDefinedOrder = true;
+            }
+
+            try {
+                ExtensionPoint point = PluginRepository.get(conf)
+                        .getExtensionPoint(ScoringFilter.X_POINT_ID);
+                if (point == null)
+                    throw new RuntimeException(ScoringFilter.X_POINT_ID
+                            + " not found.");
+                Extension[] extensions = point.getExtensions();
+                HashMap<String, ScoringFilter> filterMap = new HashMap<String, ScoringFilter>();
+                for (int i = 0; i < extensions.length; i++) {
+                    Extension extension = extensions[i];
+                    ScoringFilter filter = (ScoringFilter) extension
+                            .getExtensionInstance();
+                    if (!filterMap.containsKey(filter.getClass().getName())) {
+                        filterMap.put(filter.getClass().getName(), filter);
+                        if (!userDefinedOrder)
+                            orderOfFilters.add(filter.getClass().getName());
+                    }
+                }
+                List <ScoringFilter> sorted = new ArrayList <ScoringFilter>();
+                for (String orderedFilter : orderOfFilters) {
+                    ScoringFilter f = filterMap.get(orderedFilter);
+                    if (f == null) {
+                        LOG.error("ScoringFilter : "
+                                + orderedFilter
+                                + " declared in conf but not found in an active plugin - ignoring.");
+                        continue;
+                    }
+                    sorted.add(f);
+                }
+                ScoringFilter[] filter = sorted.toArray(new ScoringFilter[sorted.size()]);
+                objectCache.setObject(ScoringFilter.class.getName(), filter);
+            } catch (PluginRuntimeException e) {
+                throw new RuntimeException(e);
+            }
+
+            this.filters = (ScoringFilter[]) objectCache
+                    .getObject(ScoringFilter.class.getName());
         }
-        if (orderedFilters == null) {
-          objectCache.setObject(ScoringFilter.class.getName(), filterMap.values().toArray(new ScoringFilter[0]));
-        } else {
-          ScoringFilter[] filter = new ScoringFilter[orderedFilters.length];
-          for (int i = 0; i < orderedFilters.length; i++) {
-            filter[i] = filterMap.get(orderedFilters[i]);
-          }
-          objectCache.setObject(ScoringFilter.class.getName(), filter);
+    }
+
+    /** Calculate a sort value for Generate. */
+    public float generatorSortValue(Text url, CrawlDatum datum, float initSort)
+            throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            initSort = this.filters[i].generatorSortValue(url, datum, initSort);
         }
-      } catch (PluginRuntimeException e) {
-        throw new RuntimeException(e);
-      }
-      this.filters = (ScoringFilter[]) objectCache.getObject(ScoringFilter.class.getName());
+        return initSort;
     }
-  }
 
-  /** Calculate a sort value for Generate. */
-  public float generatorSortValue(Text url, CrawlDatum datum, float initSort) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      initSort = this.filters[i].generatorSortValue(url, datum, initSort);
+    /** Calculate a new initial score, used when adding newly discovered pages. */
+    public void initialScore(Text url, CrawlDatum datum)
+            throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            this.filters[i].initialScore(url, datum);
+        }
     }
-    return initSort;
-  }
 
-  /** Calculate a new initial score, used when adding newly discovered pages. */
-  public void initialScore(Text url, CrawlDatum datum) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      this.filters[i].initialScore(url, datum);
+    /** Calculate a new initial score, used when injecting new pages. */
+    public void injectedScore(Text url, CrawlDatum datum)
+            throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            this.filters[i].injectedScore(url, datum);
+        }
     }
-  }
 
-  /** Calculate a new initial score, used when injecting new pages. */
-  public void injectedScore(Text url, CrawlDatum datum) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      this.filters[i].injectedScore(url, datum);
+    /** Calculate updated page score during CrawlDb.update(). */
+    public void updateDbScore(Text url, CrawlDatum old, CrawlDatum datum,
+            List<CrawlDatum> inlinked) throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            this.filters[i].updateDbScore(url, old, datum, inlinked);
+        }
     }
-  }
 
-  /** Calculate updated page score during CrawlDb.update(). */
-  public void updateDbScore(Text url, CrawlDatum old, CrawlDatum datum, List<CrawlDatum> inlinked) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      this.filters[i].updateDbScore(url, old, datum, inlinked);
+    public void passScoreBeforeParsing(Text url, CrawlDatum datum,
+            Content content) throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            this.filters[i].passScoreBeforeParsing(url, datum, content);
+        }
     }
-  }
 
-  public void passScoreBeforeParsing(Text url, CrawlDatum datum, Content content) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      this.filters[i].passScoreBeforeParsing(url, datum, content);
+    public void passScoreAfterParsing(Text url, Content content, Parse parse)
+            throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            this.filters[i].passScoreAfterParsing(url, content, parse);
+        }
     }
-  }
-  
-  public void passScoreAfterParsing(Text url, Content content, Parse parse) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      this.filters[i].passScoreAfterParsing(url, content, parse);
+
+    public CrawlDatum distributeScoreToOutlinks(Text fromUrl,
+            ParseData parseData, Collection<Entry<Text, CrawlDatum>> targets,
+            CrawlDatum adjust, int allCount) throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            adjust = this.filters[i].distributeScoreToOutlinks(fromUrl,
+                    parseData, targets, adjust, allCount);
+        }
+        return adjust;
     }
-  }
-  
-  public CrawlDatum distributeScoreToOutlinks(Text fromUrl, ParseData parseData, Collection<Entry<Text, CrawlDatum>> targets, CrawlDatum adjust, int allCount) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      adjust = this.filters[i].distributeScoreToOutlinks(fromUrl, parseData, targets, adjust, allCount);
-    }
-    return adjust;
-  }
 
-  public float indexerScore(Text url, NutchDocument doc, CrawlDatum dbDatum, CrawlDatum fetchDatum, Parse parse, Inlinks inlinks, float initScore) throws ScoringFilterException {
-    for (int i = 0; i < this.filters.length; i++) {
-      initScore = this.filters[i].indexerScore(url, doc, dbDatum, fetchDatum, parse, inlinks, initScore);
+    public float indexerScore(Text url, NutchDocument doc, CrawlDatum dbDatum,
+            CrawlDatum fetchDatum, Parse parse, Inlinks inlinks, float initScore)
+            throws ScoringFilterException {
+        for (int i = 0; i < this.filters.length; i++) {
+            initScore = this.filters[i].indexerScore(url, doc, dbDatum,
+                    fetchDatum, parse, inlinks, initScore);
+        }
+        return initScore;
     }
-    return initScore;
-  }
 
 }
