You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2014/03/16 19:11:10 UTC

svn commit: r1578133 [7/11] - in /lucene/dev/branches/lucene5376_2/lucene: ./ analysis/common/src/java/org/apache/lucene/analysis/charfilter/ analysis/common/src/java/org/apache/lucene/analysis/pattern/ analysis/common/src/java/org/apache/lucene/analys...

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SetCommitUserDataHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SetCommitUserDataHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SetCommitUserDataHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SetCommitUserDataHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,72 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.*;
+import net.minidev.json.JSONObject;
+
+/** Handles {@code setCommitUserData}. */
+public class SetCommitUserDataHandler extends Handler {
+
+  private static StructType TYPE = new StructType(
+                                                  new Param("indexName", "Index name", new StringType()),
+                                                  new Param("userData", "Custom Map<String,String>", new AnyType()));
+
+  /** Sole constructor. */
+  public SetCommitUserDataHandler(GlobalState state) {
+    super(state);
+  }
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Sets custom user data in the index, later retrieved with getCommitUserData.";
+  }
+  
+  @Override
+  public FinishRequest handle(final IndexState state, Request r, Map<String,List<String>> params) throws Exception {
+
+    final Map<String,String> userData = new HashMap<String,String>();
+    for(Map.Entry<String,Object> ent : ((JSONObject) r.getAndRemoveRaw("userData")).entrySet()) {
+      if (ent.getValue() instanceof String == false) {
+        r.failWrongClass("userData", "all values must be String ", ent.getValue());
+      }
+      userData.put(ent.getKey(), (String) ent.getValue());
+    }
+
+    return new FinishRequest() {
+      @Override
+      public String finish() throws IOException {
+        state.writer.getIndexWriter().setCommitData(userData);
+        return "{}";
+      }
+    };
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SettingsHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SettingsHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SettingsHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SettingsHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,131 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.codecs.NormsFormat;
+import org.apache.lucene.server.DirectoryFactory;
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.*;
+import org.apache.lucene.server.params.PolyType.PolyEntry;
+import org.apache.lucene.server.params.Request.PolyResult;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.packed.PackedInts;
+import net.minidev.json.JSONValue;
+
+/** For changing index settings that cannot be changed while
+ *  the index is running. */
+public class SettingsHandler extends Handler {
+
+  // TODO: merge scheduler, CMS max threads, etc.
+
+  // TODO: add "includeDefaults" bool ... if true then we
+  // return ALL settings (incl default ones)
+
+  /** Parameters accepted by this handler. */
+  public static final StructType TYPE =
+    new StructType(
+        new Param("indexName", "Index name", new StringType()),
+        RegisterFieldHandler.MATCH_VERSION_PARAM,
+        new Param("mergeMaxMBPerSec", "Rate limit merges to at most this many MB/sec", new FloatType()),
+        new Param("nrtCachingDirectory.maxMergeSizeMB", "Largest merged segment size to cache in RAMDirectory", new FloatType(), 5.0),
+        new Param("nrtCachingDirectory.maxSizeMB", "Largest overall size for all files cached in NRTCachingDirectory; set to 0 to disable NRTCachingDirectory", new FloatType(), 60.0),
+        new Param("concurrentMergeScheduler.maxThreadCount", "How many merge threads to allow at once", new IntType(), 1),
+        new Param("concurrentMergeScheduler.maxMergeCount", "Maximum backlog of pending merges before indexing threads are stalled", new IntType(), 2),
+
+        new Param("index.verbose", "Turn on IndexWriter's infoStream (to stdout)", new BooleanType(), false),
+        // nocommit how to accept any class on the CP that
+        // implements NormsFormat and has default ctor ...?
+        new Param("normsFormat", "Which NormsFormat should be used for all indexed fields.",
+                  new StructType(
+                      new Param("class", "Which NormsFormat implementation to use",
+                          new PolyType(NormsFormat.class, "Lucene42",
+                              new PolyEntry("Lucene42", "Lucene42NormsFormat",
+                                  new Param("acceptableOverheadRatio", "How much, if any, compression should be used; pass 7.0 or higher for no compression, and 0.0 for maximum compression.", new FloatType(), PackedInts.FASTEST)),
+                              new PolyEntry("Lucene40", "Lucene40NormsFormat"))))),
+        new Param("directory", "Base Directory implementation to use (NRTCachingDirectory will wrap this); either one of the core implementations (FSDirectory, MMapDirectory, NIOFSDirectory, SimpleFSDirectory, RAMDirectory (for temporary indices!) or a fully qualified path to a Directory implementation that has a public constructor taking a single File argument",
+            new StringType(), "FSDirectory"));
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Change global offline settings for this index.  This returns the currently set settings; pass no settings changes to retrieve current settings.";
+  }
+
+  /** Sole constructor. */
+  public SettingsHandler(GlobalState state) {
+    super(state);
+  }
+
+  @Override
+  public FinishRequest handle(final IndexState state, Request r, Map<String,List<String>> params) throws Exception {
+    // nocommit how to / should we make this truly thread
+    // safe?
+    final DirectoryFactory df;
+    final String directoryJSON;
+    if (r.hasParam("directory")) {
+      directoryJSON = r.getRaw("directory").toString();
+      df = DirectoryFactory.get(r.getString("directory"));
+    } else {
+      df = null;
+      directoryJSON = null;
+    }
+
+    if (r.hasParam("normsFormat")) {
+      Request r2 = r.getStruct("normsFormat");
+      Request.PolyResult npr = r2.getPoly("class");
+      float acceptableOverheadRatio;
+      if (npr.name.equals("Lucene42") && npr.r.hasParam("acceptableOverheadRatio")) {
+        acceptableOverheadRatio = npr.r.getFloat("acceptableOverheadRatio");
+      } else {
+        acceptableOverheadRatio = PackedInts.FASTEST;
+      }
+
+      state.setNormsFormat(npr.name, acceptableOverheadRatio);
+      
+      // Sneaky: if we don't do this, and if the PolyResult
+      // was a struct, then state.mergeSimpleSettings below
+      // gets angry because it doesn't know what to do w/
+      // this parameter:
+      r.clearParam("normsFormat");
+    }
+
+    // nocommit these settings take effect even if there is
+    // an error?
+    state.mergeSimpleSettings(r);
+
+    return new FinishRequest() {
+      @Override
+      public String finish() {
+        if (df != null) {
+          state.setDirectoryFactory(df, JSONValue.parse(directoryJSON));
+        }
+        return state.getSettingsJSON();
+      }
+    };
+  }
+}
+

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/ShutdownHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/ShutdownHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/ShutdownHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/ShutdownHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,61 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.*;
+
+/** Handles {@code shutdown}. */
+public class ShutdownHandler extends Handler {
+
+  /** Sole constructor. */
+  public ShutdownHandler(GlobalState globalState) {
+    super(globalState);
+    requiresIndexName = false;
+  }
+
+  private static StructType TYPE = new StructType();
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Shut down the server.";
+  }
+
+  @Override
+  public FinishRequest handle(final IndexState state, Request r, Map<String,List<String>> params) throws Exception {
+    return new FinishRequest() {
+      @Override
+      public String finish() throws IOException {
+        globalState.shutdownNow.countDown();
+        return "{}";
+      }
+    };
+  }
+}
+

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StartIndexHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StartIndexHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StartIndexHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StartIndexHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,79 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.facet.taxonomy.SearcherTaxonomyManager.SearcherAndTaxonomy;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.Param;
+import org.apache.lucene.server.params.Request;
+import org.apache.lucene.server.params.StringType;
+import org.apache.lucene.server.params.StructType;
+import net.minidev.json.JSONObject;
+
+/** Handles {@code startIndex}. */
+public class StartIndexHandler extends Handler {
+  private static StructType TYPE = new StructType(
+                                       new Param("indexName", "Index name", new StringType()));
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Starts an index";
+  }
+
+  /** Sole constructor. */
+  public StartIndexHandler(GlobalState state) {
+    super(state);
+  }
+
+  @Override
+  public FinishRequest handle(final IndexState state, final Request r, Map<String,List<String>> params) throws Exception {
+    return new FinishRequest() {
+      @Override
+      public String finish() throws Exception {
+        long t0 = System.nanoTime();
+        state.start();
+        JSONObject result = new JSONObject();
+        SearcherAndTaxonomy s = state.manager.acquire();
+        try {
+          IndexReader r = s.searcher.getIndexReader();
+          result.put("maxDoc", r.maxDoc());
+          result.put("numDocs", r.numDocs());
+          result.put("segments", r.toString());
+        } finally {
+          state.manager.release(s);
+        }
+        long t1 = System.nanoTime();
+        result.put("startTimeMS", ((t1-t0)/1000000.0));
+
+        return result.toString();
+      }
+    };
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StatsHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StatsHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StatsHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StatsHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,112 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.facet.taxonomy.SearcherTaxonomyManager.SearcherAndTaxonomy;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.search.CachingWrapperFilter;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.SearcherLifetimeManager;
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.MyIndexSearcher;
+import org.apache.lucene.server.params.Param;
+import org.apache.lucene.server.params.Request;
+import org.apache.lucene.server.params.StringType;
+import org.apache.lucene.server.params.StructType;
+import org.apache.lucene.util.RamUsageEstimator;
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+
+/** Handles {@code stats}. */
+public class StatsHandler extends Handler {
+
+  StructType TYPE = new StructType(new Param("indexName", "Index name", new StringType()));
+
+  @Override
+  public String getTopDoc() {
+    return "Retrieve index statistics.";
+  }
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  /** Sole constructor. */
+  public StatsHandler(GlobalState state) {
+    super(state);
+  }
+
+  @Override
+  public FinishRequest handle(final IndexState state, final Request r, Map<String,List<String>> params) throws Exception {
+    return new FinishRequest() {
+      @Override
+      public String finish() throws IOException {
+        JSONObject result = new JSONObject();
+        final JSONObject searchers = new JSONObject();
+        result.put("searchers", searchers);
+
+        // TODO: snapshots
+
+        // TODO: go per segment and print more details, and
+        // only print segment for a given searcher if it's
+        // "new"
+
+        // Doesn't actually prune; just gathers stats
+        state.slm.prune(new SearcherLifetimeManager.Pruner() {
+            @Override
+            public boolean doPrune(double ageSec, IndexSearcher searcher) {
+              JSONObject s = new JSONObject();
+              searchers.put(Long.toString(((DirectoryReader) searcher.getIndexReader()).getVersion()), s);
+              s.put("staleAgeSeconds", ageSec);
+              s.put("segments", searcher.getIndexReader().toString());
+              return false;
+            }
+          });
+
+        JSONObject taxo = new JSONObject();
+        result.put("taxonomy", taxo);
+        
+        SearcherAndTaxonomy s = state.manager.acquire();
+        try {
+          taxo.put("segments", s.taxonomyReader.toString());
+          taxo.put("numOrds", s.taxonomyReader.getSize());
+        } finally {
+          state.manager.release(s);
+        }
+
+        JSONArray cachedFilters = new JSONArray();
+        result.put("cachedFilters", cachedFilters);
+        for(Map.Entry<String,CachingWrapperFilter> ent : state.cachedFilters.entrySet()) {
+          JSONObject c = new JSONObject();
+          cachedFilters.add(c);
+          c.put("id", ent.getKey());
+          c.put("bytes", ent.getValue().sizeInBytes());
+        }
+
+        return result.toString();
+      }
+    };
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StopIndexHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StopIndexHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StopIndexHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/StopIndexHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,62 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.Param;
+import org.apache.lucene.server.params.Request;
+import org.apache.lucene.server.params.StringType;
+import org.apache.lucene.server.params.StructType;
+
+/** Handles {@code stopIndex}. */
+public class StopIndexHandler extends Handler {
+  private static StructType TYPE = new StructType(
+                                       new Param("indexName", "Index name", new StringType()));
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Stops an index";
+  }
+
+  /** Sole constructor. */
+  public StopIndexHandler(GlobalState state) {
+    super(state);
+  }
+
+  @Override
+  public FinishRequest handle(final IndexState state, final Request r, Map<String,List<String>> params) throws Exception {
+    return new FinishRequest() {
+      @Override
+      public String finish() throws IOException {
+        state.close();
+        return "{}";
+      }
+    };
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SuggestLookupHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SuggestLookupHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SuggestLookupHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/SuggestLookupHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,107 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.search.suggest.Lookup.LookupResult;
+import org.apache.lucene.search.suggest.Lookup;
+import org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester;
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.handlers.BuildSuggestHandler.LookupHighlightFragment;
+import org.apache.lucene.server.params.*;
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+
+/** Handles {@code suggestLookup}. */
+public class SuggestLookupHandler extends Handler {
+
+  private final static StructType TYPE =
+    new StructType(
+        new Param("indexName", "Index name", new StringType()),
+        new Param("suggestName", "Which suggester to use.", new StringType()),
+        new Param("text", "Text to suggest from.", new StringType()),
+        new Param("highlight", "True if the suggestions should be highlighted (currently only works with AnalyzingInfixSuggester).", new BooleanType(), true),
+        new Param("allTermsRequired", "If true then all terms must be found (this only applies to InfixSuggester currently).",
+                  new BooleanType(), false),
+        new Param("count", "How many suggestions to return.", new IntType(), 5));
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Perform an auto-suggest lookup.";
+  }
+
+  /** Sole constructor. */
+  public SuggestLookupHandler(GlobalState state) {
+    super(state);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public FinishRequest handle(final IndexState state, final Request r, Map<String,List<String>> params) throws Exception {
+    String suggestName = r.getString("suggestName");
+    final Lookup lookup = state.suggesters.get(suggestName);
+    if (lookup == null) {
+      r.fail("suggestName", "this suggester (\"" + suggestName + "\") was not yet built; valid suggestNames: " + state.suggesters.keySet());
+    }
+    final String text = r.getString("text");
+    final int count = r.getInt("count");
+    final boolean allTermsRequired = r.getBoolean("allTermsRequired");
+    final boolean highlight = r.getBoolean("highlight");
+
+    return new FinishRequest() {
+      @Override
+      public String finish() throws IOException {
+        List<LookupResult> results;
+        if (lookup instanceof AnalyzingInfixSuggester) {
+          results = ((AnalyzingInfixSuggester) lookup).lookup(text, count, allTermsRequired, highlight);
+        } else {
+          results = lookup.lookup(text, false, count);
+        }
+        JSONObject ret = new JSONObject();
+        JSONArray retArray = new JSONArray();
+        ret.put("results", retArray);
+        for(LookupResult result : results) {
+          JSONObject o = new JSONObject();
+          retArray.add(o);
+          if (result.highlightKey != null) {
+            // Currently only AnalyzingInfixSuggester does highlighting:
+            o.put("key", result.highlightKey);
+          } else {
+            o.put("key", result.key);
+          }
+          o.put("weight", result.value);
+          if (result.payload != null) {
+            o.put("payload", result.payload.utf8ToString());
+          }
+        }
+    
+        return ret.toString();
+      }
+    };
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateDocumentHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateDocumentHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateDocumentHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateDocumentHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,98 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.StringReader;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.Param;
+import org.apache.lucene.server.params.Request;
+import org.apache.lucene.server.params.StringType;
+import org.apache.lucene.server.params.StructType;
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+import net.minidev.json.JSONValue;
+
+/** Handles {@code updateDocument}, by delegating the single
+ *  document to {@link BulkUpdateDocumentHandler}. */
+public class UpdateDocumentHandler extends Handler {
+  final StructType TYPE = new StructType(
+                               new Param("indexName", "Index Name", new StringType()),
+                               new Param("term", "Identifies which document to replace", 
+                                         new StructType(
+                                             new Param("field", "Field", new StringType()),
+                                             new Param("term", "Text", new StringType()))));
+
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Replaces one document in the index.  Returns the index generation (indexGen) that contains this added document.";
+  }
+
+  /** Sole constructor. */
+  public UpdateDocumentHandler(GlobalState state) {
+    super(state);
+    TYPE.params.putAll(AddDocumentHandler.DOCUMENT_TYPE.params);
+  }
+
+  @Override
+  public FinishRequest handle(final IndexState state, final Request r, Map<String,List<String>> params) throws Exception {
+
+    state.verifyStarted(r);
+
+    // NOTE: somewhat wasteful since we re-serialize to
+    // string only to re-parse the JSON, but this allows
+    // single-source (bulk) for parsing, and apps that care
+    // about performance will use bulk APIs:
+
+    JSONObject raw = r.getRawParams();
+    StringBuilder sb = new StringBuilder();
+    sb.append("{\"indexName\": \"");
+    sb.append(state.name);
+    sb.append("\", \"documents\": [");
+    sb.append(raw.toString());
+    sb.append("]}");
+    raw.clear();
+
+    final String bulkRequestString = sb.toString();
+
+    return new FinishRequest() {
+
+      @Override
+      public String finish() throws Exception {
+        String result = globalState.getHandler("bulkUpdateDocument").handleStreamed(new StringReader(bulkRequestString), null);
+        if (result.indexOf("errors") != -1) {
+          JSONObject o = (JSONObject) JSONValue.parseStrict(result);
+          if (o.containsKey("errors")) {
+            JSONObject err = (JSONObject) ((JSONArray) o.get("errors")).get(0);
+            throw new IllegalArgumentException((String) err.get("exception"));
+          }
+        }
+        return result;
+      }
+    };
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateSuggestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateSuggestHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateSuggestHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/UpdateSuggestHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,111 @@
+package org.apache.lucene.server.handlers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.search.suggest.InputIterator;
+import org.apache.lucene.search.suggest.Lookup;
+import org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester;
+import org.apache.lucene.server.FinishRequest;
+import org.apache.lucene.server.FromFileTermFreqIterator;
+import org.apache.lucene.server.GlobalState;
+import org.apache.lucene.server.IndexState;
+import org.apache.lucene.server.params.Param;
+import org.apache.lucene.server.params.Request;
+import org.apache.lucene.server.params.StringType;
+import org.apache.lucene.server.params.StructType;
+import org.apache.lucene.util.BytesRef;
+import net.minidev.json.JSONObject;
+
+/** Handles {@code updateSuggest}. */
+
+public class UpdateSuggestHandler extends Handler {
+  private final static StructType TYPE =
+    new StructType(
+        new Param("indexName", "Index Name", new StringType()),
+        new Param("suggestName", "Which suggester to update.", new StringType()),
+        // nocommit option to stream suggestions in over the wire too
+        // nocommit also allow pulling from index/expressions, like BuildSuggest:
+        new Param("source", "Where to get suggestions from",
+            new StructType(
+                new Param("localFile", "Local file (to the server) to read suggestions + weights from; format is weight U+001F suggestion U+001F payload, one per line, with suggestion UTF-8 encoded.  If this option is used then searcher, suggestField, weightField/Expression, payloadField should not be specified.", new StringType()))));
+
+  /** Sole constructor. */
+  public UpdateSuggestHandler(GlobalState state) {
+    super(state);
+  }
+  
+  @Override
+  public StructType getType() {
+    return TYPE;
+  }
+
+  @Override
+  public String getTopDoc() {
+    return "Updates existing suggestions, if the suggester supports near-real-time changes.";
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public FinishRequest handle(final IndexState state, final Request r, Map<String,List<String>> params) throws Exception {
+    final String suggestName = r.getString("suggestName");
+    Lookup lookup = state.suggesters.get(suggestName);
+    if (lookup == null) {
+      r.fail("suggestName", "this suggester (\"" + suggestName + "\") was not yet built; valid suggestNames: " + state.suggesters.keySet());
+    }
+    if ((lookup instanceof AnalyzingInfixSuggester) == false) {
+      r.fail("suggestName", "can only update AnalyzingInfixSuggester; got " + lookup);
+    }
+
+    final AnalyzingInfixSuggester lookup2 = (AnalyzingInfixSuggester) lookup;
+
+    Request r2 = r.getStruct("source");
+    final File localFile = new File(r2.getString("localFile"));
+
+    return new FinishRequest() {
+
+      @Override
+      public String finish() throws IOException {
+
+        InputIterator iterator = new FromFileTermFreqIterator(localFile);
+        boolean hasPayloads = iterator.hasPayloads();
+        int count = 0;
+        while (true) {
+          BytesRef term = iterator.next();
+          if (term == null) {
+            break;
+          }
+
+          lookup2.update(term, iterator.weight(), hasPayloads ? iterator.payload() : null);
+          count++;
+        }
+
+        lookup2.refresh();
+
+        JSONObject ret = new JSONObject();
+        ret.put("count", count);
+        return ret.toString();
+      }
+    };
+  }
+}
+

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/package.html?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/package.html (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/handlers/package.html Sun Mar 16 18:11:07 2014
@@ -0,0 +1,25 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+  <head>
+    <title>Lucene Server: handlers</title>
+  </head>
+  <body>
+    <h1>Lucene Server: handlers</h1>
+    Classes that handle each request method (search, addDocument, etc.).
+  </body>
+</html>

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/HttpStaticFileServerHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/HttpStaticFileServerHandler.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/HttpStaticFileServerHandler.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/HttpStaticFileServerHandler.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,333 @@
+package org.apache.lucene.server.http;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This file adapted from the netty example (under apache 2.0 license):
+// https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+import javax.activation.MimetypesFileTypeMap;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelFutureListener;
+import org.jboss.netty.channel.ChannelFutureProgressListener;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.DefaultFileRegion;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.FileRegion;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import org.jboss.netty.handler.codec.frame.TooLongFrameException;
+import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
+import org.jboss.netty.handler.codec.http.HttpRequest;
+import org.jboss.netty.handler.codec.http.HttpResponse;
+import org.jboss.netty.handler.codec.http.HttpResponseStatus;
+import org.jboss.netty.handler.ssl.SslHandler;
+import org.jboss.netty.handler.stream.ChunkedFile;
+import org.jboss.netty.util.CharsetUtil;
+
+import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
+import static org.jboss.netty.handler.codec.http.HttpMethod.*;
+import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
+import static org.jboss.netty.handler.codec.http.HttpVersion.*;
+
+/**
+ * A simple handler that serves incoming HTTP requests to send their respective
+ * HTTP responses.  It also implements {@code 'If-Modified-Since'} header to
+ * take advantage of browser cache, as described in
+ * <a href="http://tools.ietf.org/html/rfc2616#section-14.25">RFC 2616</a>.
+ *
+ * <h3>How Browser Caching Works</h3>
+ *
+ * Web browser caching works with HTTP headers as illustrated by the following
+ * sample:
+ * <ol>
+ * <li>Request #1 returns the content of {@code /file1.txt}.</li>
+ * <li>Contents of {@code /file1.txt} is cached by the browser.</li>
+ * <li>Request #2 for {@code /file1.txt} does return the contents of the
+ *     file again. Rather, a 304 Not Modified is returned. This tells the
+ *     browser to use the contents stored in its cache.</li>
+ * <li>The server knows the file has not been modified because the
+ *     {@code If-Modified-Since} date is the same as the file's last
+ *     modified date.</li>
+ * </ol>
+ *
+ * <pre>
+ * Request #1 Headers
+ * ===================
+ * GET /file1.txt HTTP/1.1
+ *
+ * Response #1 Headers
+ * ===================
+ * HTTP/1.1 200 OK
+ * Date:               Tue, 01 Mar 2011 22:44:26 GMT
+ * Last-Modified:      Wed, 30 Jun 2010 21:36:48 GMT
+ * Expires:            Tue, 01 Mar 2012 22:44:26 GMT
+ * Cache-Control:      private, max-age=31536000
+ *
+ * Request #2 Headers
+ * ===================
+ * GET /file1.txt HTTP/1.1
+ * If-Modified-Since:  Wed, 30 Jun 2010 21:36:48 GMT
+ *
+ * Response #2 Headers
+ * ===================
+ * HTTP/1.1 304 Not Modified
+ * Date:               Tue, 01 Mar 2011 22:44:28 GMT
+ *
+ * </pre>
+ */
+public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
+
+  /** HTTP header format. */
+  public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
+
+  /** HTTP header timezone. */
+  public static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
+
+  /** How long the client should cache a static file. */
+  public static final int HTTP_CACHE_SECONDS = 60;
+
+  private final File rootDir;
+
+  /** Sole constructor. */
+  public HttpStaticFileServerHandler(File rootDir) throws IOException {
+    this.rootDir = rootDir.getCanonicalFile();
+  }
+
+  @Override
+  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+    HttpRequest request = (HttpRequest) e.getMessage();
+    if (request.getMethod() != GET) {
+      sendError(ctx, METHOD_NOT_ALLOWED);
+      return;
+    }
+
+    final File file = sanitizeUri(request.getUri());
+    if (file == null) {
+      sendError(ctx, FORBIDDEN);
+      return;
+    }
+
+    if (file.isHidden() || !file.exists()) {
+      sendError(ctx, NOT_FOUND);
+      return;
+    }
+    if (!file.isFile()) {
+      sendError(ctx, FORBIDDEN);
+      return;
+    }
+
+    // Cache Validation
+    String ifModifiedSince = request.getHeader(IF_MODIFIED_SINCE);
+    if (ifModifiedSince != null && ifModifiedSince.length() != 0) {
+      SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
+      Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
+
+      // Only compare up to the second because the datetime format we send to the client does
+      // not have milliseconds
+      long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
+      long fileLastModifiedSeconds = file.lastModified() / 1000;
+      if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
+        sendNotModified(ctx);
+        return;
+      }
+    }
+
+    RandomAccessFile raf;
+    try {
+      raf = new RandomAccessFile(file, "r");
+    } catch (FileNotFoundException fnfe) {
+      sendError(ctx, NOT_FOUND);
+      return;
+    }
+    long fileLength = raf.length();
+
+    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
+    setContentLength(response, fileLength);
+    setContentTypeHeader(response, file);
+    setDateAndCacheHeaders(response, file);
+
+    Channel ch = e.getChannel();
+
+    // Write the initial line and the header.
+    ch.write(response);
+
+    // Write the content.
+    ChannelFuture writeFuture;
+    if (ch.getPipeline().get(SslHandler.class) != null) {
+      // Cannot use zero-copy with HTTPS.
+      writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192));
+    } else {
+      // No encryption - use zero-copy.
+      final FileRegion region =
+        new DefaultFileRegion(raf.getChannel(), 0, fileLength);
+      writeFuture = ch.write(region);
+      writeFuture.addListener(new ChannelFutureProgressListener() {
+          public void operationComplete(ChannelFuture future) {
+            region.releaseExternalResources();
+          }
+
+          public void operationProgressed(
+                                          ChannelFuture future, long amount, long current, long total) {
+            System.out.printf("%s: %d / %d (+%d)%n", file.toString(), current, total, amount);
+          }
+        });
+    }
+
+    // Decide whether to close the connection or not.
+    if (!isKeepAlive(request)) {
+      // Close the connection when the whole content is written out.
+      writeFuture.addListener(ChannelFutureListener.CLOSE);
+    }
+  }
+
+  @Override
+  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+    throws Exception {
+    Channel ch = e.getChannel();
+    Throwable cause = e.getCause();
+    if (cause instanceof TooLongFrameException) {
+      sendError(ctx, BAD_REQUEST);
+      return;
+    }
+
+    cause.printStackTrace();
+    if (ch.isConnected()) {
+      sendError(ctx, INTERNAL_SERVER_ERROR);
+    }
+  }
+
+  private File sanitizeUri(String uri) throws IOException {
+    // Decode the path.
+    try {
+      uri = URLDecoder.decode(uri, "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      try {
+        uri = URLDecoder.decode(uri, "ISO-8859-1");
+      } catch (UnsupportedEncodingException e1) {
+        throw new Error();
+      }
+    }
+
+    // Convert file separators.
+    uri = uri.replace('/', File.separatorChar);
+
+    // Convert to absolute path.
+    File fullPath = new File(rootDir + File.separator + uri);
+    // Don't allow ../ to escape the root dir:
+    if (!fullPath.getCanonicalFile().toString().startsWith(rootDir.toString())) {
+      return null;
+    }
+
+    return fullPath;
+  }
+
+  private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
+    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
+    response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
+    response.setContent(ChannelBuffers.copiedBuffer(
+                                                    "Failure: " + status.toString() + "\r\n",
+                                                    CharsetUtil.UTF_8));
+
+    // Close the connection as soon as the error message is sent.
+    ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
+  }
+
+  /**
+   * When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
+   *
+   * @param ctx
+   *            Context
+   */
+  private static void sendNotModified(ChannelHandlerContext ctx) {
+    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NOT_MODIFIED);
+    setDateHeader(response);
+
+    // Close the connection as soon as the error message is sent.
+    ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
+  }
+
+  /**
+   * Sets the Date header for the HTTP response
+   *
+   * @param response
+   *            HTTP response
+   */
+  private static void setDateHeader(HttpResponse response) {
+    SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
+    TimeZone tz = TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE);
+    dateFormatter.setTimeZone(tz);
+
+    Calendar time = new GregorianCalendar(tz, Locale.US);
+    response.setHeader(DATE, dateFormatter.format(time.getTime()));
+  }
+
+  /**
+   * Sets the Date and Cache headers for the HTTP Response
+   *
+   * @param response
+   *            HTTP response
+   * @param fileToCache
+   *            file to extract content type
+   */
+  private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
+    SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
+    TimeZone tz = TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE);
+    dateFormatter.setTimeZone(tz);
+
+    // Date header
+    Calendar time = new GregorianCalendar(tz, Locale.US);
+    response.setHeader(DATE, dateFormatter.format(time.getTime()));
+
+    // Add cache headers
+    time.add(Calendar.SECOND, HTTP_CACHE_SECONDS);
+    response.setHeader(EXPIRES, dateFormatter.format(time.getTime()));
+    response.setHeader(CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);
+    response.setHeader(
+                       LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
+  }
+
+  /**
+   * Sets the content type header for the HTTP Response
+   *
+   * @param response
+   *            HTTP response
+   * @param file
+   *            file to extract content type
+   */
+  private static void setContentTypeHeader(HttpResponse response, File file) {
+    MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
+    response.setHeader(CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
+  }
+
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/package.html?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/package.html (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/http/package.html Sun Mar 16 18:11:07 2014
@@ -0,0 +1,25 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+  <head>
+    <title>Lucene Server: http</title>
+  </head>
+  <body>
+    <h1>Lucene Server: http</h1>
+    Classes to handle HTTP server communication.
+  </body>
+</html>

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/package.html?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/package.html (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/package.html Sun Mar 16 18:11:07 2014
@@ -0,0 +1,78 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+  <head>
+    <title>Lucene Server</title>
+  </head>
+  <body>
+    <h1>Lucene Server</h1>
+    A basic example JSON/HTTP server showing how to use Lucene's APIs in a server context.
+    <p>
+      Features/design:
+      <ul>
+	<li> A number of Lucene's capabilities have been exposed:
+	  indexing documents, bulk indexing (streaming JSON), block
+	  joins, grouping, highlighting, suggest, live-values,
+	  snapshots, etc.
+
+	<li> Lucene's legacy FieldCache is never used; only the
+	  faster, more RAM efficient doc values are used when you
+	  sort, group, facet on a field.
+
+	<li> All searching is based on near-real-time IndexReader; you
+	  configure the minimum and maximum refresh times.
+
+	<li> There is no required ID field; instead, a document is
+	  identified by the pair of the searcher version and Lucene's
+	  docID.
+
+	<li> The server APIs are self documenting; point your browser
+	  at http://localhost:4000/doc to browse the available methods
+	  and parameters.
+
+	<li> Error checking is strict but each error message should
+	  be easy to understand, pointing to the exact path/parameter
+	  that was problematic.  It's an error if a
+	  request has unexpected parameters.
+
+	<li> Write-once schema: fields must be registered up front,
+	  once, before any document is indexed with them; once a field
+	  is registered, it cannot be changed (write-once).
+    
+	<li> All changes (creating and configuring indices, indexing
+	  documents, etc.) are done through JSON APIs; there are no
+	  human-edited configuration files (though the server does
+	  store its index metadata in on-disk JSON files).
+
+	<li> A snapshot records all configuration (registered fields,
+	  settings, etc.) in addition to the point-in-time view of the
+	  index; future searches can then reference that snapshot for
+	  searching.
+
+	<li> A server thread pool handles all concurrency during
+	  indexing, so a single client thread using the bulk
+	  indexing API will take advantage of the server computer's
+	  concurrent hardware.
+
+	<li> Settings are divided into <em>live</em> settings, which
+	  can be changed after the index is started, and ordinary
+	  settings, which cannot.
+
+	<li> Limited infrastructure for plugins.
+      </ul>
+  </body>
+</html>

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/AnyType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/AnyType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/AnyType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/AnyType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,31 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Accepts any object. */
+public class AnyType extends Type {
+
+  /** Sole constructor. */
+  public AnyType() {
+  }
+
+  @Override
+  public void validate(Object o) {
+  }
+}
+

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/BooleanType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/BooleanType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/BooleanType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/BooleanType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,33 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Type for booleans. */
+public class BooleanType extends Type {
+
+  /** Sole constructor. */
+  public BooleanType() {
+  }
+
+  @Override
+  public void validate(Object o) {
+    if (!(o instanceof Boolean)) {
+      throw new IllegalArgumentException("expected Boolean but got " + o.getClass());
+    }
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/EnumType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/EnumType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/EnumType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/EnumType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,53 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Type for an enumeration. */
+public class EnumType extends Type {
+
+  /** Maps label to description. */
+  final Map<String,String> values;
+
+  /** Sole constructor, values is alternating label1,
+   *  desc1, label2, desc2, ... */
+  public EnumType(String ... values) {
+    if ((values.length & 1) != 0) {
+      throw new IllegalArgumentException("input must be value/desc pairs");
+    }
+    this.values = new HashMap<String,String>();
+    for(int i=0;i<values.length;i+=2) {
+      this.values.put(values[i], values[i+1]);
+    }
+  }
+
+  @Override
+  public void validate(Object o) {
+    if (!(o instanceof String)) {
+      throw new IllegalArgumentException("expected String but got " + o.getClass());
+    }
+    if (values.containsKey(o) == false) {
+      String[] keys = new ArrayList<String>(values.keySet()).toArray(new String[values.size()]);
+      throw new IllegalArgumentException("expected one of " + Arrays.toString(keys) + " but got \"" + o + "\"");
+    }
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/FloatType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/FloatType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/FloatType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/FloatType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,36 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.math.BigDecimal;
+
+/** Type for any number that could be a double. */
+public class FloatType extends Type {
+
+  /** Sole constructor. */
+  public FloatType() {
+  }
+
+  @Override
+  public void validate(Object o) {
+    // nocommit messy:
+    if (!(o instanceof Float) && !(o instanceof Double) && !(o instanceof BigDecimal)) {
+      throw new IllegalArgumentException("expected Float or Double but got " + o.getClass());
+    }
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/IntType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/IntType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/IntType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/IntType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,33 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Type for an integer. */
+public class IntType extends Type {
+
+  /** Sole constructor. */
+  public IntType() {
+  }
+
+  @Override
+  public void validate(Object o) {
+    if (!(o instanceof Integer)) {
+      throw new IllegalArgumentException("expected Integer but got " + o.getClass());
+    }
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/ListType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/ListType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/ListType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/ListType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,47 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+/** Type for a list of items of fixed subType. */
+public class ListType extends Type {
+
+  /** Type of our elements. */
+  public final Type subType;
+
+  /** Sole constructor. */
+  public ListType(Type subType) {
+    this.subType = subType;
+  }
+
+  @Override
+  public void validate(Object _o) {
+    if (!(_o instanceof List)) {
+      throw new IllegalArgumentException("expected List but got " + _o.getClass());
+    }
+    for(Object o2 : (List) _o) {
+      subType.validate(o2);
+    }
+  }
+
+  /** Returns item subType. */
+  public Type getSubType() {
+    return subType;
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/LongType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/LongType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/LongType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/LongType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,33 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Type for a long. */
+public class LongType extends Type {
+
+  /** Sole constructor. */
+  public LongType() {
+  }
+
+  @Override
+  public void validate(Object o) {
+    if (!(o instanceof Long) && !(o instanceof Integer)) {
+      throw new IllegalArgumentException("expected Long or Integer but got " + o.getClass());
+    }
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/OrType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/OrType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/OrType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/OrType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,52 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Type that accepts any of the provided list of types. */
+public class OrType extends Type {
+
+  /** Allowed sub-types. */
+  public final Type[] types;
+
+  /** Sole constructor. */
+  public OrType(Type... types) {
+    this.types = types;
+  }
+
+  @Override
+  public void validate(Object o) {
+    for(Type t : types) {
+      try {
+        t.validate(o);
+        return;
+      } catch (IllegalArgumentException iae) {
+      }
+    }
+    StringBuilder sb = new StringBuilder();
+    sb.append("expected one of ");
+    for(int i=0;i<types.length;i++) {
+      if (i != 0) {
+        sb.append(", ");
+      }
+      sb.append(types[i].getClass().getSimpleName());
+    }
+    sb.append(", but got " + o.getClass().getSimpleName());
+
+    throw new IllegalArgumentException(sb.toString());
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/Param.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/Param.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/Param.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/Param.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,50 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Represents one paramater to a method. */
+public class Param {
+
+  /** Name. */
+  public final String name;
+
+  /** Description (English). */
+  public final String desc;
+
+  /** Type description. */
+  public final Type type;
+
+  /** Default value; if null the parameter is required. */
+  public final Object defaultValue;
+
+  /** Creates this, with a default value. */
+  public Param(String name, String desc, Type type, Object defaultValue) {
+    this.name = name;
+    this.desc = desc;
+    this.type = type;
+    this.defaultValue = defaultValue;
+    if (defaultValue != null) {
+      type.validate(defaultValue);
+    }
+  }
+
+  /** Creates this, with no default value. */
+  public Param(String name, String desc, Type type) {
+    this(name, desc, type, null);
+  }
+}

Added: lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/PolyType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/PolyType.java?rev=1578133&view=auto
==============================================================================
--- lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/PolyType.java (added)
+++ lucene/dev/branches/lucene5376_2/lucene/server/src/java/org/apache/lucene/server/params/PolyType.java Sun Mar 16 18:11:07 2014
@@ -0,0 +1,91 @@
+package org.apache.lucene.server.params;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Allows one parameter in a struct (usually named class)
+ *  to define/refine the type of the struct.  For example,
+ *  this is used for a generic "similarity": the "class"
+ *  param will specify a concrete class (DefaultSim,
+ *  BM25Sim, etc.), and switch the struct to other types
+ *  (because each sim impl takes different params) based on
+ *  that. */
+
+@SuppressWarnings("rawtypes")
+public class PolyType extends Type {
+
+  /** Maps parameter name to the {@link PolyEntry}
+   *  describing the sub type. */
+  public final Map<String,PolyEntry> types = new HashMap<String,PolyEntry>();
+
+  /** Not yet used but ... could be used in the future
+   *  to allow custom (plugin) classes to be accepted. */
+  public final Class baseClass;
+
+  /** Default value, or null. */
+  public final String defaultClassName;
+
+  /** Describes one sub type. */
+  public static class PolyEntry {
+
+    /** Name of the sub-type, e.g. BM25Similarity. */
+    public final String name;
+
+    /** Defines the sub type. */
+    public final StructType type;
+
+    /** Description of this entry (English). */
+    public final String desc;
+
+    /** Creates this, folding the provided params into a
+     *  new {@link StructType}. */
+    public PolyEntry(String name, String desc, Param... params) {
+      this(name, desc, new StructType(params));
+    }
+
+    /** Creates this. */
+    public PolyEntry(String name, String desc, StructType type) {
+      this.name = name;
+      this.desc = desc;
+      this.type = type;
+    }
+  }
+
+  @Override
+  public void validate(Object o) {
+  }
+
+  /** No default value. */
+  public PolyType(Class baseClass, PolyEntry... entries) {
+    this(baseClass, null, entries);
+  }
+
+  /** With default value. */
+  public PolyType(Class baseClass, String defaultClassName, PolyEntry... entries) {
+    this.baseClass = baseClass;
+    this.defaultClassName = defaultClassName;
+    for(PolyEntry e : entries) {
+      if (types.containsKey(e.name)) {
+        throw new IllegalArgumentException("name \"" + e.name + "\" appears more than once");
+      }
+      types.put(e.name, e);
+    }
+  }
+}