Skip to content
This repository has been archived by the owner on May 4, 2023. It is now read-only.

Commit

Permalink
Added no-argument constructor to LuceneServlet, handy for web.xml set…
Browse files Browse the repository at this point in the history
…ting when running via Tomcat. Extracted configuration handling to Config class, used by Main and LuceneServlet's no-arg constructor.
  • Loading branch information
cliffano committed May 19, 2011
1 parent 9d3402a commit 2977df2
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 166 deletions.
278 changes: 143 additions & 135 deletions src/main/java/com/github/rnewson/couchdb/lucene/LuceneServlet.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;


import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalINIConfiguration; import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
Expand All @@ -47,47 +48,54 @@


public final class LuceneServlet extends HttpServlet { public final class LuceneServlet extends HttpServlet {


private static final Logger LOG = Logger.getLogger(LuceneServlet.class); private static final Logger LOG = Logger.getLogger(LuceneServlet.class);


private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;


private final HttpClient client; private final HttpClient client;


private final Map<Database, DatabaseIndexer> indexers = new HashMap<Database, DatabaseIndexer>(); private final Map<Database, DatabaseIndexer> indexers = new HashMap<Database, DatabaseIndexer>();


private final HierarchicalINIConfiguration ini; private final HierarchicalINIConfiguration ini;


private final File root; private final File root;


private final Map<Database, Thread> threads = new HashMap<Database, Thread>(); private final Map<Database, Thread> threads = new HashMap<Database, Thread>();


public LuceneServlet(final HttpClient client, final File root, public LuceneServlet() throws ConfigurationException, IOException {
final HierarchicalINIConfiguration ini) { final Config config = new Config();
this.client = client; this.client = config.getClient();
this.root = root; this.root = config.getDir();
this.ini = ini; this.ini = config.getConfiguration();
} }

public LuceneServlet(final HttpClient client, final File root,
final HierarchicalINIConfiguration ini) {
this.client = client;
this.root = root;
this.ini = ini;
}


private void cleanup(final HttpServletRequest req, private void cleanup(final HttpServletRequest req,
final HttpServletResponse resp) throws IOException, JSONException { final HttpServletResponse resp) throws IOException, JSONException {
final Couch couch = getCouch(req); final Couch couch = getCouch(req);
final Set<String> dbKeep = new HashSet<String>(); final Set<String> dbKeep = new HashSet<String>();
final JSONArray databases = couch.getAllDatabases(); final JSONArray databases = couch.getAllDatabases();
for (int i=0; i< databases.length(); i++) { for (int i=0; i< databases.length(); i++) {
final Database db = couch.getDatabase(databases.getString(i)); final Database db = couch.getDatabase(databases.getString(i));
final UUID uuid = db.getUuid(); final UUID uuid = db.getUuid();
if (uuid == null) { if (uuid == null) {
continue; continue;
} }
dbKeep.add(uuid.toString()); dbKeep.add(uuid.toString());


final Set<String> viewKeep = new HashSet<String>(); final Set<String> viewKeep = new HashSet<String>();


for (final DesignDocument ddoc : db.getAllDesignDocuments()) { for (final DesignDocument ddoc : db.getAllDesignDocuments()) {
for (final View view : ddoc.getAllViews().values()) { for (final View view : ddoc.getAllViews().values()) {
viewKeep.add(view.getDigest()); viewKeep.add(view.getDigest());
} }
} }


// Delete all indexes except the keepers. // Delete all indexes except the keepers.
final File[] dirs = DatabaseIndexer.uuidDir(root, db.getUuid()).listFiles(); final File[] dirs = DatabaseIndexer.uuidDir(root, db.getUuid()).listFiles();
Expand All @@ -104,127 +112,127 @@ private void cleanup(final HttpServletRequest req,
} }
} }
} }
} }


// Delete all directories except the keepers. // Delete all directories except the keepers.
for (final File dir : root.listFiles()) { for (final File dir : root.listFiles()) {
if (!dbKeep.contains(dir.getName())) { if (!dbKeep.contains(dir.getName())) {
LOG.info("Cleaning old index at " + dir); LOG.info("Cleaning old index at " + dir);
FileUtils.deleteDirectory(dir); FileUtils.deleteDirectory(dir);
} }
} }


resp.setStatus(202); resp.setStatus(202);
ServletUtils.sendJsonSuccess(req, resp); ServletUtils.sendJsonSuccess(req, resp);
} }


private Couch getCouch(final HttpServletRequest req) throws IOException { private Couch getCouch(final HttpServletRequest req) throws IOException {
final Configuration section = ini.getSection(new PathParts(req) final Configuration section = ini.getSection(new PathParts(req)
.getKey()); .getKey());
final String url = section.containsKey("url") ? section final String url = section.containsKey("url") ? section
.getString("url") : null; .getString("url") : null;
return new Couch(client, url); return new Couch(client, url);
} }


private synchronized DatabaseIndexer getIndexer(final Database database) private synchronized DatabaseIndexer getIndexer(final Database database)
throws IOException, JSONException { throws IOException, JSONException {
DatabaseIndexer result = indexers.get(database); DatabaseIndexer result = indexers.get(database);
Thread thread = threads.get(database); Thread thread = threads.get(database);
if (result == null || thread == null || !thread.isAlive()) { if (result == null || thread == null || !thread.isAlive()) {
result = new DatabaseIndexer(client, root, database, ini); result = new DatabaseIndexer(client, root, database, ini);
thread = new Thread(result); thread = new Thread(result);
thread.start(); thread.start();
result.awaitInitialization(); result.awaitInitialization();
if (result.isClosed()) { if (result.isClosed()) {
return null; return null;
} else { } else {
indexers.put(database, result); indexers.put(database, result);
threads.put(database, thread); threads.put(database, thread);
} }
} }


return result; return result;
} }


private DatabaseIndexer getIndexer(final HttpServletRequest req) private DatabaseIndexer getIndexer(final HttpServletRequest req)
throws IOException, JSONException { throws IOException, JSONException {
final Couch couch = getCouch(req); final Couch couch = getCouch(req);
final Database database = couch.getDatabase(new PathParts(req) final Database database = couch.getDatabase(new PathParts(req)
.getDatabaseName()); .getDatabaseName());
return getIndexer(database); return getIndexer(database);
} }


private void handleWelcomeReq(final HttpServletRequest req, private void handleWelcomeReq(final HttpServletRequest req,
final HttpServletResponse resp) throws ServletException, final HttpServletResponse resp) throws ServletException,
IOException, JSONException { IOException, JSONException {
final Package p = this.getClass().getPackage(); final Package p = this.getClass().getPackage();
final JSONObject welcome = new JSONObject(); final JSONObject welcome = new JSONObject();
welcome.put("couchdb-lucene", "Welcome"); welcome.put("couchdb-lucene", "Welcome");
welcome.put("version", p.getImplementationVersion()); welcome.put("version", p.getImplementationVersion());
ServletUtils.sendJson(req, resp, welcome); ServletUtils.sendJson(req, resp, welcome);
} }


@Override @Override
protected void doGet(final HttpServletRequest req, protected void doGet(final HttpServletRequest req,
final HttpServletResponse resp) throws ServletException, final HttpServletResponse resp) throws ServletException,
IOException { IOException {
try { try {
doGetInternal(req, resp); doGetInternal(req, resp);
} catch (final JSONException e) { } catch (final JSONException e) {
resp.sendError(500); resp.sendError(500);
} }
} }


private void doGetInternal(final HttpServletRequest req, final HttpServletResponse resp) private void doGetInternal(final HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException, JSONException { throws ServletException, IOException, JSONException {
switch (StringUtils.countMatches(req.getRequestURI(), "/")) { switch (StringUtils.countMatches(req.getRequestURI(), "/")) {
case 1: case 1:
handleWelcomeReq(req, resp); handleWelcomeReq(req, resp);
return; return;
case 5: case 5:
final DatabaseIndexer indexer = getIndexer(req); final DatabaseIndexer indexer = getIndexer(req);
if (indexer == null) { if (indexer == null) {
ServletUtils.sendJsonError(req, resp, 500, "error_creating_index"); ServletUtils.sendJsonError(req, resp, 500, "error_creating_index");
return; return;
} }
if (req.getParameter("q") == null) { if (req.getParameter("q") == null) {
indexer.info(req, resp); indexer.info(req, resp);
} else { } else {
indexer.search(req, resp); indexer.search(req, resp);
} }
return; return;
} }


ServletUtils.sendJsonError(req, resp, 400, "bad_request"); ServletUtils.sendJsonError(req, resp, 400, "bad_request");
} }


@Override @Override
protected void doPost(final HttpServletRequest req, protected void doPost(final HttpServletRequest req,
final HttpServletResponse resp) throws ServletException, final HttpServletResponse resp) throws ServletException,
IOException { IOException {
try { try {
doPostInternal(req, resp); doPostInternal(req, resp);
} catch (final JSONException e) { } catch (final JSONException e) {
resp.sendError(500); resp.sendError(500);
} }
} }


private void doPostInternal(final HttpServletRequest req, final HttpServletResponse resp) private void doPostInternal(final HttpServletRequest req, final HttpServletResponse resp)
throws IOException, JSONException { throws IOException, JSONException {
switch (StringUtils.countMatches(req.getRequestURI(), "/")) { switch (StringUtils.countMatches(req.getRequestURI(), "/")) {
case 3: case 3:
if (req.getPathInfo().endsWith("/_cleanup")) { if (req.getPathInfo().endsWith("/_cleanup")) {
cleanup(req, resp); cleanup(req, resp);
return; return;
} }
break; break;
case 6: case 6:
final DatabaseIndexer indexer = getIndexer(req); final DatabaseIndexer indexer = getIndexer(req);
indexer.admin(req, resp); indexer.admin(req, resp);
return; return;
} }
ServletUtils.sendJsonError(req, resp, 400, "bad_request"); ServletUtils.sendJsonError(req, resp, 400, "bad_request");
} }


} }
36 changes: 5 additions & 31 deletions src/main/java/com/github/rnewson/couchdb/lucene/Main.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@
*/ */


import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.Iterator;


import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.io.FileUtils;
import org.apache.http.client.HttpClient;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mortbay.jetty.Connector; import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler; import org.mortbay.jetty.Handler;
Expand All @@ -42,41 +36,21 @@ public class Main {
* Run couchdb-lucene. * Run couchdb-lucene.
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
final HierarchicalINIConfiguration configuration = new HierarchicalINIConfiguration( final Config config = new Config();
Main.class.getClassLoader().getResource("couchdb-lucene.ini")); final File dir = config.getDir();
configuration.setReloadingStrategy(new FileChangedReloadingStrategy());

final File dir = new File(configuration.getString("lucene.dir", "indexes"));

if (!dir.exists() && !dir.mkdir()) {
LOG.error("Could not create " + dir.getCanonicalPath());
System.exit(1);
}
if (!dir.canRead()) {
LOG.error(dir + " is not readable.");
System.exit(1);
}
if (!dir.canWrite()) {
LOG.error(dir + " is not writable.");
System.exit(1);
}
LOG.info("Index output goes to: " + dir.getCanonicalPath());


final Server server = new Server(); final Server server = new Server();
final SelectChannelConnector connector = new SelectChannelConnector(); final SelectChannelConnector connector = new SelectChannelConnector();
connector.setHost(configuration.getString("lucene.host", "localhost")); connector.setHost(config.getConfiguration().getString("lucene.host", "localhost"));
connector.setPort(configuration.getInt("lucene.port", 5985)); connector.setPort(config.getConfiguration().getInt("lucene.port", 5985));


LOG.info("Accepting connections with " + connector); LOG.info("Accepting connections with " + connector);


server.setConnectors(new Connector[]{connector}); server.setConnectors(new Connector[]{connector});
server.setStopAtShutdown(true); server.setStopAtShutdown(true);
server.setSendServerVersion(false); server.setSendServerVersion(false);


HttpClientFactory.setIni(configuration); final LuceneServlet servlet = new LuceneServlet(config.getClient(), dir, config.getConfiguration());
final HttpClient httpClient = HttpClientFactory.getInstance();

final LuceneServlet servlet = new LuceneServlet(httpClient, dir, configuration);


final Context context = new Context(server, "/", Context.NO_SESSIONS | Context.NO_SECURITY); final Context context = new Context(server, "/", Context.NO_SESSIONS | Context.NO_SECURITY);
context.addServlet(new ServletHolder(servlet), "/*"); context.addServlet(new ServletHolder(servlet), "/*");
Expand Down

0 comments on commit 2977df2

Please sign in to comment.