mirror of https://github.com/apache/lucene.git
SOLR-104 - Support for Update Plugins: giving RequestHandlers access to ContentStreams, new URL structure allowing for more RESTful URLs, common baseclass for RequestHandlers, refactoring existing XML based updates into a RequestHandler
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@501174 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7e877bc49f
commit
3c603b2aea
|
@ -60,6 +60,14 @@ New Features
|
|||
7. SOLR-107: JAVA API: Change NamedList to use Java5 generics
|
||||
and implement Iterable<Map.Entry> (Ryan McKinley via yonik)
|
||||
|
||||
8. SOLR-104: Support for "Update Plugins" -- RequestHandlers that want
|
||||
access to streams of data for doing updates. ContentStreams can come
|
||||
from the raw POST body, multi-part form data, or remote URLs.
|
||||
Included in this change is a new SlrDispatchFilter that allows
|
||||
RequestHandlers registered with names that begin with a "/" to be
|
||||
accessed using a URL structure based on that name.
|
||||
(Ryan McKinley via hossman)
|
||||
|
||||
Changes in runtime behavior
|
||||
1. Highlighting using DisMax will only pick up terms from the main
|
||||
user query, not boost or filter queries (klaas).
|
||||
|
|
|
@ -222,6 +222,8 @@
|
|||
|
||||
</query>
|
||||
|
||||
<!--Make sure your system has some authentication before enabling remote streaming! -->
|
||||
<requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048" />
|
||||
|
||||
<!-- requestHandler plugins... incoming queries will be dispatched to the
|
||||
correct handler based on the qt (query type) param matching the
|
||||
|
@ -338,6 +340,22 @@
|
|||
</str>
|
||||
</requestHandler>
|
||||
|
||||
|
||||
<!-- Standard update plugin. If we put this on /update, it will get all the new goodness -->
|
||||
<requestHandler name="/update/xml" class="solr.XmlUpdateRequestHandler" >
|
||||
<!--
|
||||
<lst name="defaults">
|
||||
<str name="name">value</str>
|
||||
</lst>
|
||||
-->
|
||||
</requestHandler>
|
||||
|
||||
<requestHandler name="/debug/dump" class="solr.DumpRequestHandler" />
|
||||
|
||||
<!-- NOTE, /update is mapped to a servlet, we can have the filter handle requests off that! -->
|
||||
<requestHandler name="/update/commit" class="solr.CommitRequestHandler" />
|
||||
|
||||
|
||||
<!-- queryResponseWriter plugins... query responses will be written using the
|
||||
writer specified by the 'wt' request parameter matching the name of a registered
|
||||
writer.
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
AnyObjectId[5058ac0a3df716610375d6401c835aea9c35540f] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -0,0 +1,2 @@
|
|||
AnyObjectId[b2867cdde4284228f2adc51e8a0358972bccaaf1] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -181,7 +181,7 @@ public class Config {
|
|||
|
||||
private static final String project = "solr";
|
||||
private static final String base = "org.apache" + "." + project;
|
||||
private static final String[] packages = {"","analysis.","schema.","search.","update.","core.","request.","util."};
|
||||
private static final String[] packages = {"","analysis.","schema.","search.","update.","core.","request.","handler.","util."};
|
||||
|
||||
public static Class findClass(String cname, String... subpackages) {
|
||||
ClassLoader loader = getClassLoader();
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.lucene.index.IndexReader;
|
|||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.solr.handler.XmlUpdateRequestHandler;
|
||||
import org.apache.solr.request.*;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
|
@ -41,7 +42,10 @@ import org.xmlpull.v1.XmlPullParserFactory;
|
|||
import javax.xml.xpath.XPathConstants;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
@ -241,6 +245,18 @@ public final class SolrCore {
|
|||
|
||||
void finalizer() { close(); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Update Handler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* RequestHandlers need access to the updateHandler so they can all talk to the
|
||||
* same RAM indexer.
|
||||
*/
|
||||
public UpdateHandler getUpdateHandler()
|
||||
{
|
||||
return updateHandler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Searcher Control
|
||||
|
@ -589,14 +605,7 @@ public final class SolrCore {
|
|||
}
|
||||
|
||||
|
||||
|
||||
public void execute(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
SolrRequestHandler handler = getRequestHandler(req.getQueryType());
|
||||
if (handler==null) {
|
||||
log.warning("Unknown Request Handler '" + req.getQueryType() +"' :" + req);
|
||||
throw new SolrException(400,"Unknown Request Handler '" + req.getQueryType() + "'", true);
|
||||
}
|
||||
|
||||
public void execute(SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
// setup response header and handle request
|
||||
final NamedList responseHeader = new NamedList();
|
||||
rsp.add("responseHeader", responseHeader);
|
||||
|
@ -607,6 +616,16 @@ public final class SolrCore {
|
|||
(int)(rsp.getEndTime() - req.getStartTime()));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void execute(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
SolrRequestHandler handler = getRequestHandler(req.getQueryType());
|
||||
if (handler==null) {
|
||||
log.warning("Unknown Request Handler '" + req.getQueryType() +"' :" + req);
|
||||
throw new SolrException(400,"Unknown Request Handler '" + req.getQueryType() + "'", true);
|
||||
}
|
||||
execute(handler, req, rsp);
|
||||
}
|
||||
|
||||
protected void setResponseHeaderValues(NamedList responseHeader,SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
// TODO should check that responseHeader has not been replaced by handler
|
||||
|
||||
|
@ -625,321 +644,6 @@ public final class SolrCore {
|
|||
}
|
||||
}
|
||||
|
||||
XmlPullParserFactory factory;
|
||||
{
|
||||
try {
|
||||
factory = XmlPullParserFactory.newInstance();
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
factory.setNamespaceAware(false);
|
||||
}
|
||||
|
||||
|
||||
private int findNextTag(XmlPullParser xpp, String tag) throws XmlPullParserException, IOException {
|
||||
int eventType;
|
||||
while((eventType=xpp.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
if(eventType == XmlPullParser.START_TAG) {
|
||||
if (tag.equals(xpp.getName())) break;
|
||||
}
|
||||
}
|
||||
return eventType;
|
||||
}
|
||||
|
||||
|
||||
public void update(Reader reader, Writer writer) {
|
||||
|
||||
// TODO: add param to specify maximum time to commit?
|
||||
|
||||
// todo - might be nice to separate command parsing w/ a factory
|
||||
// then new commands could be added w/o risk to old ones
|
||||
|
||||
|
||||
XmlPullParser xpp = null;
|
||||
try {
|
||||
xpp = factory.newPullParser();
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
long startTime=System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
xpp.setInput(reader);
|
||||
xpp.nextTag();
|
||||
|
||||
String currTag = xpp.getName();
|
||||
if ("add".equals(currTag)) {
|
||||
log.finest("SolrCore.update(add)");
|
||||
AddUpdateCommand cmd = new AddUpdateCommand();
|
||||
cmd.allowDups=false; // the default
|
||||
|
||||
int status=0;
|
||||
boolean pendingAttr=false, committedAttr=false;
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("allowDups".equals(attrName)) {
|
||||
cmd.allowDups = StrUtils.parseBoolean(attrVal);
|
||||
} else if ("overwritePending".equals(attrName)) {
|
||||
cmd.overwritePending = StrUtils.parseBoolean(attrVal);
|
||||
pendingAttr=true;
|
||||
} else if ("overwriteCommitted".equals(attrName)) {
|
||||
cmd.overwriteCommitted = StrUtils.parseBoolean(attrVal);
|
||||
committedAttr=true;
|
||||
} else {
|
||||
log.warning("Unknown attribute id in add:" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
//set defaults for committed and pending based on allowDups value
|
||||
if (!pendingAttr) cmd.overwritePending=!cmd.allowDups;
|
||||
if (!committedAttr) cmd.overwriteCommitted=!cmd.allowDups;
|
||||
|
||||
DocumentBuilder builder = new DocumentBuilder(schema);
|
||||
SchemaField uniqueKeyField = schema.getUniqueKeyField();
|
||||
int eventType=0;
|
||||
// accumulate responses
|
||||
List<String> added = new ArrayList<String>(10);
|
||||
while(true) {
|
||||
// this may be our second time through the loop in the case
|
||||
// that there are multiple docs in the add... so make sure that
|
||||
// objects can handle that.
|
||||
|
||||
cmd.indexedId = null; // reset the id for this add
|
||||
|
||||
if (eventType !=0) {
|
||||
eventType=xpp.getEventType();
|
||||
if (eventType==XmlPullParser.END_DOCUMENT) break;
|
||||
}
|
||||
// eventType = xpp.next();
|
||||
eventType = xpp.nextTag();
|
||||
if (eventType == XmlPullParser.END_TAG || eventType == XmlPullParser.END_DOCUMENT) break; // should match </add>
|
||||
|
||||
readDoc(builder,xpp);
|
||||
builder.endDoc();
|
||||
cmd.doc = builder.getDoc();
|
||||
log.finest("adding doc...");
|
||||
updateHandler.addDoc(cmd);
|
||||
String docId = null;
|
||||
if (uniqueKeyField!=null)
|
||||
docId = schema.printableUniqueKey(cmd.doc);
|
||||
added.add(docId);
|
||||
|
||||
} // end while
|
||||
// write log and result
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (String docId: added)
|
||||
if(docId != null)
|
||||
out.append(docId + ",");
|
||||
String outMsg = out.toString();
|
||||
if(outMsg.length() > 0)
|
||||
outMsg = outMsg.substring(0, outMsg.length() - 1);
|
||||
log.info("added id={" + outMsg + "} in " + (System.currentTimeMillis()-startTime) + "ms");
|
||||
writer.write("<result status=\"0\"></result>");
|
||||
|
||||
} // end add
|
||||
|
||||
else if ("commit".equals(currTag) || "optimize".equals(currTag)) {
|
||||
log.finest("parsing "+currTag);
|
||||
try {
|
||||
CommitUpdateCommand cmd = new CommitUpdateCommand("optimize".equals(currTag));
|
||||
|
||||
boolean sawWaitSearcher=false, sawWaitFlush=false;
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("waitFlush".equals(attrName)) {
|
||||
cmd.waitFlush = StrUtils.parseBoolean(attrVal);
|
||||
sawWaitFlush=true;
|
||||
} else if ("waitSearcher".equals(attrName)) {
|
||||
cmd.waitSearcher = StrUtils.parseBoolean(attrVal);
|
||||
sawWaitSearcher=true;
|
||||
} else {
|
||||
log.warning("unexpected attribute commit/@" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
// If waitFlush is specified and waitSearcher wasn't, then
|
||||
// clear waitSearcher.
|
||||
if (sawWaitFlush && !sawWaitSearcher) {
|
||||
cmd.waitSearcher=false;
|
||||
}
|
||||
|
||||
updateHandler.commit(cmd);
|
||||
if ("optimize".equals(currTag)) {
|
||||
log.info("optimize 0 "+(System.currentTimeMillis()-startTime));
|
||||
}
|
||||
else {
|
||||
log.info("commit 0 "+(System.currentTimeMillis()-startTime));
|
||||
}
|
||||
while (true) {
|
||||
int eventType = xpp.nextTag();
|
||||
if (eventType == XmlPullParser.END_TAG) break; // match </commit>
|
||||
}
|
||||
writer.write("<result status=\"0\"></result>");
|
||||
} catch (SolrException e) {
|
||||
log(e);
|
||||
if ("optimize".equals(currTag)) {
|
||||
log.info("optimize "+e.code+" "+
|
||||
(System.currentTimeMillis()-startTime));
|
||||
}
|
||||
else {
|
||||
log.info("commit "+e.code+" "+
|
||||
(System.currentTimeMillis()-startTime));
|
||||
}
|
||||
writeResult(writer,e);
|
||||
} catch (Exception e) {
|
||||
SolrException.log(log, "Exception during commit/optimize",e);
|
||||
writeResult(writer,e);
|
||||
}
|
||||
} // end commit
|
||||
|
||||
else if ("delete".equals(currTag)) {
|
||||
log.finest("parsing delete");
|
||||
try {
|
||||
DeleteUpdateCommand cmd = new DeleteUpdateCommand();
|
||||
cmd.fromPending=true;
|
||||
cmd.fromCommitted=true;
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("fromPending".equals(attrName)) {
|
||||
cmd.fromPending = StrUtils.parseBoolean(attrVal);
|
||||
} else if ("fromCommitted".equals(attrName)) {
|
||||
cmd.fromCommitted = StrUtils.parseBoolean(attrVal);
|
||||
} else {
|
||||
log.warning("unexpected attribute delete/@" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
int eventType = xpp.nextTag();
|
||||
currTag = xpp.getName();
|
||||
String val = xpp.nextText();
|
||||
|
||||
if ("id".equals(currTag)) {
|
||||
cmd.id = val;
|
||||
updateHandler.delete(cmd);
|
||||
log.info("delete(id " + val + ") 0 " +
|
||||
(System.currentTimeMillis()-startTime));
|
||||
} else if ("query".equals(currTag)) {
|
||||
cmd.query = val;
|
||||
updateHandler.deleteByQuery(cmd);
|
||||
log.info("deleteByQuery(query " + val + ") 0 " +
|
||||
(System.currentTimeMillis()-startTime));
|
||||
} else {
|
||||
log.warning("unexpected XML tag /delete/"+currTag);
|
||||
throw new SolrException(400,"unexpected XML tag /delete/"+currTag);
|
||||
}
|
||||
|
||||
writer.write("<result status=\"0\"></result>");
|
||||
|
||||
while (xpp.nextTag() != XmlPullParser.END_TAG);
|
||||
|
||||
} catch (SolrException e) {
|
||||
log(e);
|
||||
log.info("delete "+e.code+" "+(System.currentTimeMillis()-startTime));
|
||||
writeResult(writer,e);
|
||||
} catch (Exception e) {
|
||||
log(e);
|
||||
writeResult(writer,e);
|
||||
}
|
||||
} // end delete
|
||||
|
||||
|
||||
} catch (XmlPullParserException e) {
|
||||
log(e);
|
||||
writeResult(writer,e);
|
||||
} catch (IOException e) {
|
||||
log(e);
|
||||
writeResult(writer,e);
|
||||
} catch (SolrException e) {
|
||||
log(e);
|
||||
log.info("update "+e.code+" "+(System.currentTimeMillis()-startTime));
|
||||
writeResult(writer,e);
|
||||
} catch (Throwable e) {
|
||||
log(e);
|
||||
writeResult(writer,e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void readDoc(DocumentBuilder builder, XmlPullParser xpp) throws IOException, XmlPullParserException {
|
||||
// xpp should be at <doc> at this point
|
||||
|
||||
builder.startDoc();
|
||||
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
float docBoost = 1.0f;
|
||||
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("boost".equals(attrName)) {
|
||||
docBoost = Float.parseFloat(attrVal);
|
||||
builder.setBoost(docBoost);
|
||||
} else {
|
||||
log.warning("Unknown attribute doc/@" + attrName);
|
||||
}
|
||||
}
|
||||
if (docBoost != 1.0f) builder.setBoost(docBoost);
|
||||
|
||||
// while (findNextTag(xpp,"field") != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
while(true) {
|
||||
int eventType = xpp.nextTag();
|
||||
if (eventType == XmlPullParser.END_TAG) break; // </doc>
|
||||
|
||||
String tname=xpp.getName();
|
||||
// System.out.println("FIELD READER AT TAG " + tname);
|
||||
|
||||
if (!"field".equals(tname)) {
|
||||
log.warning("unexpected XML tag doc/"+tname);
|
||||
throw new SolrException(400,"unexpected XML tag doc/"+tname);
|
||||
}
|
||||
|
||||
//
|
||||
// get field name and parse field attributes
|
||||
//
|
||||
attrcount = xpp.getAttributeCount();
|
||||
String name=null;
|
||||
float boost=1.0f;
|
||||
boolean isNull=false;
|
||||
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("name".equals(attrName)) {
|
||||
name=attrVal;
|
||||
} else if ("boost".equals(attrName)) {
|
||||
boost=Float.parseFloat(attrVal);
|
||||
} else if ("null".equals(attrName)) {
|
||||
isNull=StrUtils.parseBoolean(attrVal);
|
||||
} else {
|
||||
log.warning("Unknown attribute doc/field/@" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
// now get the field value
|
||||
String val = xpp.nextText(); // todo... text event for <field></field>???
|
||||
// need this line for isNull???
|
||||
// Don't add fields marked as null (for now at least)
|
||||
if (!isNull) {
|
||||
if (boost != 1.0f) {
|
||||
builder.addField(name,val,boost);
|
||||
} else {
|
||||
builder.addField(name,val);
|
||||
}
|
||||
}
|
||||
|
||||
// do I have to do a nextTag here to read the end_tag?
|
||||
|
||||
} // end field loop
|
||||
|
||||
}
|
||||
|
||||
|
||||
final public static void log(Throwable e) {
|
||||
|
@ -947,23 +651,6 @@ public final class SolrCore {
|
|||
}
|
||||
|
||||
|
||||
final static void writeResult(Writer out, SolrException e) {
|
||||
try {
|
||||
XML.writeXML(out,"result",e.getMessage(),"status",e.code());
|
||||
} catch (Exception ee) {
|
||||
log.severe("Error writing to putput stream: "+ee);
|
||||
}
|
||||
}
|
||||
|
||||
final static void writeResult(Writer out, Throwable e) {
|
||||
try {
|
||||
XML.writeXML(out,"result",SolrException.toStr(e),"status","1");
|
||||
} catch (Exception ee) {
|
||||
log.severe("Error writing to putput stream: "+ee);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private QueryResponseWriter defaultResponseWriter;
|
||||
private final Map<String, QueryResponseWriter> responseWriters = new HashMap<String, QueryResponseWriter>();
|
||||
|
@ -1034,3 +721,4 @@ public final class SolrCore {
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.update.CommitUpdateCommand;
|
||||
|
||||
public class CommitRequestHandler extends RequestHandlerBase
|
||||
{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException
|
||||
{
|
||||
SolrParams params = req.getParams();
|
||||
|
||||
boolean optimize = params.getBool( UpdateParams.OPTIMIZE, false );
|
||||
CommitUpdateCommand cmd = new CommitUpdateCommand( optimize );
|
||||
cmd.waitFlush = params.getBool( UpdateParams.WAIT_FLUSH, cmd.waitFlush );
|
||||
cmd.waitSearcher = params.getBool( UpdateParams.WAIT_SEARCHER, cmd.waitSearcher );
|
||||
|
||||
SolrCore.getSolrCore().getUpdateHandler().commit( cmd );
|
||||
|
||||
if( optimize ) {
|
||||
rsp.add( "optimize", "true" );
|
||||
}
|
||||
else {
|
||||
rsp.add( "commit", "true" );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Commit all pending documents";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL:$";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.solr.request.ContentStream;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.util.NamedList;
|
||||
|
||||
public class DumpRequestHandler extends RequestHandlerBase
|
||||
{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException
|
||||
{
|
||||
// Show params
|
||||
rsp.add( "params", req.getParams().toNamedList() );
|
||||
|
||||
// Write the streams...
|
||||
if( req.getContentStreams() != null ) {
|
||||
NamedList<Object> streams = new NamedList<Object>();
|
||||
// Cycle through each stream
|
||||
for( ContentStream content : req.getContentStreams() ) {
|
||||
NamedList<Object> stream = new NamedList<Object>();
|
||||
stream.add( "name", content.getName() );
|
||||
stream.add( "fieldName", content.getSourceInfo() );
|
||||
stream.add( "size", content.getSize() );
|
||||
stream.add( "contentType", content.getContentType() );
|
||||
stream.add( "stream", IOUtils.toString( content.getStream() ) );
|
||||
streams.add( "stream", stream );
|
||||
}
|
||||
rsp.add( "streams", streams );
|
||||
}
|
||||
|
||||
// Show the context
|
||||
Map<Object,Object> context = req.getContext();
|
||||
if( context != null ) {
|
||||
NamedList ctx = new NamedList();
|
||||
for( Map.Entry<Object,Object> entry : context.entrySet() ) {
|
||||
ctx.add( entry.getKey().toString(), entry.getValue() );
|
||||
}
|
||||
rsp.add( "context", ctx );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Dump handler (debug)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL:$";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.handler;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.core.SolrInfoMBean;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.SolrPluginUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfoMBean {
|
||||
|
||||
// statistics
|
||||
// TODO: should we bother synchronizing these, or is an off-by-one error
|
||||
// acceptable every million requests or so?
|
||||
long numRequests;
|
||||
long numErrors;
|
||||
protected SolrParams defaults;
|
||||
protected SolrParams appends;
|
||||
protected SolrParams invariants;
|
||||
|
||||
/** shorten the class references for utilities */
|
||||
private static class U extends SolrPluginUtils {
|
||||
/* :NOOP */
|
||||
}
|
||||
|
||||
public void init(NamedList args) {
|
||||
// Copied from StandardRequestHandler
|
||||
if( args != null ) {
|
||||
Object o = args.get("defaults");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
defaults = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
o = args.get("appends");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
appends = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
o = args.get("invariants");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
invariants = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void handleRequestBody( SolrQueryRequest req, SolrQueryResponse rsp ) throws Exception;
|
||||
|
||||
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
numRequests++;
|
||||
|
||||
try {
|
||||
U.setDefaults(req,defaults,appends,invariants);
|
||||
handleRequestBody( req, rsp );
|
||||
}
|
||||
catch( SolrException se ) {
|
||||
numErrors++;
|
||||
throw se;
|
||||
}
|
||||
catch( Exception e) {
|
||||
numErrors++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
public String getName() {
|
||||
return this.getClass().getName();
|
||||
}
|
||||
|
||||
public abstract String getDescription();
|
||||
public abstract String getSourceId();
|
||||
public abstract String getSource();
|
||||
public abstract String getVersion();
|
||||
|
||||
public Category getCategory() {
|
||||
return Category.QUERYHANDLER;
|
||||
}
|
||||
|
||||
public URL[] getDocs() {
|
||||
return null; // this can be overridden, but not required
|
||||
}
|
||||
|
||||
public NamedList getStatistics() {
|
||||
NamedList lst = new NamedList();
|
||||
lst.add("requests", numRequests);
|
||||
lst.add("errors", numErrors);
|
||||
return lst;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.handler;
|
||||
|
||||
/**
|
||||
* A collection of params used by Update handlers
|
||||
*/
|
||||
public interface UpdateParams
|
||||
{
|
||||
/** wait till the command has flushed */
|
||||
public static String WAIT_FLUSH = "waitFlush";
|
||||
|
||||
/** wait for the search to warm up */
|
||||
public static String WAIT_SEARCHER = "waitSearcher";
|
||||
|
||||
/** overwrite indexing fields */
|
||||
public static String OVERWRITE = "overwrite";
|
||||
|
||||
/** Commit everything after the command completes */
|
||||
public static String COMMIT = "commit";
|
||||
|
||||
/** Commit everything after the command completes */
|
||||
public static String OPTIMIZE = "optimize";
|
||||
}
|
|
@ -0,0 +1,399 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.request.ContentStream;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.servlet.SolrServlet;
|
||||
import org.apache.solr.update.AddUpdateCommand;
|
||||
import org.apache.solr.update.CommitUpdateCommand;
|
||||
import org.apache.solr.update.DeleteUpdateCommand;
|
||||
import org.apache.solr.update.DocumentBuilder;
|
||||
import org.apache.solr.update.UpdateHandler;
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.StrUtils;
|
||||
import org.apache.solr.util.XML;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
public class XmlUpdateRequestHandler extends RequestHandlerBase
|
||||
{
|
||||
public static Logger log = Logger.getLogger(XmlUpdateRequestHandler.class.getName());
|
||||
|
||||
private XmlPullParserFactory factory;
|
||||
|
||||
// This must be called AFTER solrCore has initalized!
|
||||
// otherwise you get a big bad error loop
|
||||
public void init(NamedList args)
|
||||
{
|
||||
super.init( args );
|
||||
|
||||
try {
|
||||
factory = XmlPullParserFactory.newInstance();
|
||||
factory.setNamespaceAware(false);
|
||||
}
|
||||
catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - this should be a general utility in another class
|
||||
public static String getCharsetFromContentType( String contentType )
|
||||
{
|
||||
if( contentType != null ) {
|
||||
int idx = contentType.toLowerCase().indexOf( "charset=" );
|
||||
if( idx > 0 ) {
|
||||
return contentType.substring( idx + "charset=".length() ).trim();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
|
||||
{
|
||||
Iterable<ContentStream> streams = req.getContentStreams();
|
||||
if( streams == null ) {
|
||||
throw new SolrException( 400, "missing content stream" );
|
||||
}
|
||||
|
||||
|
||||
// Cycle through each stream
|
||||
for( ContentStream stream : req.getContentStreams() ) {
|
||||
String charset = getCharsetFromContentType( stream.getContentType() );
|
||||
Reader reader = null;
|
||||
if( charset == null ) {
|
||||
reader = new InputStreamReader( stream.getStream() );
|
||||
}
|
||||
else {
|
||||
reader = new InputStreamReader( stream.getStream(), charset );
|
||||
}
|
||||
rsp.add( "update", this.update( reader ) );
|
||||
|
||||
// Make sure its closed
|
||||
try { reader.close(); } catch( Exception ex ){}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public NamedList update( Reader reader ) throws Exception
|
||||
{
|
||||
SolrCore core = SolrCore.getSolrCore();
|
||||
IndexSchema schema = core.getSchema();
|
||||
UpdateHandler updateHandler = core.getUpdateHandler();
|
||||
|
||||
// TODO: What results should be returned?
|
||||
NamedList res = new NamedList();
|
||||
|
||||
XmlPullParser xpp = factory.newPullParser();
|
||||
long startTime=System.currentTimeMillis();
|
||||
|
||||
xpp.setInput(reader);
|
||||
xpp.nextTag();
|
||||
|
||||
String currTag = xpp.getName();
|
||||
if ("add".equals(currTag)) {
|
||||
log.finest("SolrCore.update(add)");
|
||||
AddUpdateCommand cmd = new AddUpdateCommand();
|
||||
cmd.allowDups=false; // the default
|
||||
|
||||
int status=0;
|
||||
boolean pendingAttr=false, committedAttr=false;
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("allowDups".equals(attrName)) {
|
||||
cmd.allowDups = StrUtils.parseBoolean(attrVal);
|
||||
} else if ("overwritePending".equals(attrName)) {
|
||||
cmd.overwritePending = StrUtils.parseBoolean(attrVal);
|
||||
pendingAttr=true;
|
||||
} else if ("overwriteCommitted".equals(attrName)) {
|
||||
cmd.overwriteCommitted = StrUtils.parseBoolean(attrVal);
|
||||
committedAttr=true;
|
||||
} else {
|
||||
log.warning("Unknown attribute id in add:" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
//set defaults for committed and pending based on allowDups value
|
||||
if (!pendingAttr) cmd.overwritePending=!cmd.allowDups;
|
||||
if (!committedAttr) cmd.overwriteCommitted=!cmd.allowDups;
|
||||
|
||||
DocumentBuilder builder = new DocumentBuilder(schema);
|
||||
SchemaField uniqueKeyField = schema.getUniqueKeyField();
|
||||
int eventType=0;
|
||||
// accumulate responses
|
||||
List<String> added = new ArrayList<String>(10);
|
||||
while(true) {
|
||||
// this may be our second time through the loop in the case
|
||||
// that there are multiple docs in the add... so make sure that
|
||||
// objects can handle that.
|
||||
|
||||
cmd.indexedId = null; // reset the id for this add
|
||||
|
||||
if (eventType !=0) {
|
||||
eventType=xpp.getEventType();
|
||||
if (eventType==XmlPullParser.END_DOCUMENT) break;
|
||||
}
|
||||
// eventType = xpp.next();
|
||||
eventType = xpp.nextTag();
|
||||
if (eventType == XmlPullParser.END_TAG || eventType == XmlPullParser.END_DOCUMENT) break; // should match </add>
|
||||
|
||||
readDoc(builder,xpp);
|
||||
builder.endDoc();
|
||||
cmd.doc = builder.getDoc();
|
||||
log.finest("adding doc...");
|
||||
updateHandler.addDoc(cmd);
|
||||
String docId = null;
|
||||
if (uniqueKeyField!=null)
|
||||
docId = schema.printableUniqueKey(cmd.doc);
|
||||
added.add(docId);
|
||||
|
||||
} // end while
|
||||
// write log and result
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (String docId: added)
|
||||
if(docId != null)
|
||||
out.append(docId + ",");
|
||||
String outMsg = out.toString();
|
||||
if(outMsg.length() > 0)
|
||||
outMsg = outMsg.substring(0, outMsg.length() - 1);
|
||||
log.info("added id={" + outMsg + "} in " + (System.currentTimeMillis()-startTime) + "ms");
|
||||
|
||||
// Add output
|
||||
res.add( "added", outMsg );
|
||||
} // end add
|
||||
|
||||
else if ("commit".equals(currTag) || "optimize".equals(currTag)) {
|
||||
log.finest("parsing "+currTag);
|
||||
|
||||
CommitUpdateCommand cmd = new CommitUpdateCommand("optimize".equals(currTag));
|
||||
|
||||
boolean sawWaitSearcher=false, sawWaitFlush=false;
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("waitFlush".equals(attrName)) {
|
||||
cmd.waitFlush = StrUtils.parseBoolean(attrVal);
|
||||
sawWaitFlush=true;
|
||||
} else if ("waitSearcher".equals(attrName)) {
|
||||
cmd.waitSearcher = StrUtils.parseBoolean(attrVal);
|
||||
sawWaitSearcher=true;
|
||||
} else {
|
||||
log.warning("unexpected attribute commit/@" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
// If waitFlush is specified and waitSearcher wasn't, then
|
||||
// clear waitSearcher.
|
||||
if (sawWaitFlush && !sawWaitSearcher) {
|
||||
cmd.waitSearcher=false;
|
||||
}
|
||||
|
||||
updateHandler.commit(cmd);
|
||||
if ("optimize".equals(currTag)) {
|
||||
log.info("optimize 0 "+(System.currentTimeMillis()-startTime));
|
||||
}
|
||||
else {
|
||||
log.info("commit 0 "+(System.currentTimeMillis()-startTime));
|
||||
}
|
||||
while (true) {
|
||||
int eventType = xpp.nextTag();
|
||||
if (eventType == XmlPullParser.END_TAG) break; // match </commit>
|
||||
}
|
||||
|
||||
// add debug output
|
||||
res.add( cmd.optimize?"optimize":"commit", "" );
|
||||
} // end commit
|
||||
|
||||
else if ("delete".equals(currTag)) {
|
||||
log.finest("parsing delete");
|
||||
|
||||
DeleteUpdateCommand cmd = new DeleteUpdateCommand();
|
||||
cmd.fromPending=true;
|
||||
cmd.fromCommitted=true;
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("fromPending".equals(attrName)) {
|
||||
cmd.fromPending = StrUtils.parseBoolean(attrVal);
|
||||
} else if ("fromCommitted".equals(attrName)) {
|
||||
cmd.fromCommitted = StrUtils.parseBoolean(attrVal);
|
||||
} else {
|
||||
log.warning("unexpected attribute delete/@" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
int eventType = xpp.nextTag();
|
||||
currTag = xpp.getName();
|
||||
String val = xpp.nextText();
|
||||
|
||||
if ("id".equals(currTag)) {
|
||||
cmd.id = val;
|
||||
updateHandler.delete(cmd);
|
||||
log.info("delete(id " + val + ") 0 " +
|
||||
(System.currentTimeMillis()-startTime));
|
||||
} else if ("query".equals(currTag)) {
|
||||
cmd.query = val;
|
||||
updateHandler.deleteByQuery(cmd);
|
||||
log.info("deleteByQuery(query " + val + ") 0 " +
|
||||
(System.currentTimeMillis()-startTime));
|
||||
} else {
|
||||
log.warning("unexpected XML tag /delete/"+currTag);
|
||||
throw new SolrException(400,"unexpected XML tag /delete/"+currTag);
|
||||
}
|
||||
|
||||
res.add( "delete", "" );
|
||||
|
||||
while (xpp.nextTag() != XmlPullParser.END_TAG);
|
||||
} // end delete
|
||||
return res;
|
||||
}
|
||||
|
||||
private void readDoc(DocumentBuilder builder, XmlPullParser xpp) throws IOException, XmlPullParserException {
|
||||
// xpp should be at <doc> at this point
|
||||
|
||||
builder.startDoc();
|
||||
|
||||
int attrcount = xpp.getAttributeCount();
|
||||
float docBoost = 1.0f;
|
||||
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("boost".equals(attrName)) {
|
||||
docBoost = Float.parseFloat(attrVal);
|
||||
builder.setBoost(docBoost);
|
||||
} else {
|
||||
log.warning("Unknown attribute doc/@" + attrName);
|
||||
}
|
||||
}
|
||||
if (docBoost != 1.0f) builder.setBoost(docBoost);
|
||||
|
||||
// while (findNextTag(xpp,"field") != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
while(true) {
|
||||
int eventType = xpp.nextTag();
|
||||
if (eventType == XmlPullParser.END_TAG) break; // </doc>
|
||||
|
||||
String tname=xpp.getName();
|
||||
// System.out.println("FIELD READER AT TAG " + tname);
|
||||
|
||||
if (!"field".equals(tname)) {
|
||||
log.warning("unexpected XML tag doc/"+tname);
|
||||
throw new SolrException(400,"unexpected XML tag doc/"+tname);
|
||||
}
|
||||
|
||||
//
|
||||
// get field name and parse field attributes
|
||||
//
|
||||
attrcount = xpp.getAttributeCount();
|
||||
String name=null;
|
||||
float boost=1.0f;
|
||||
boolean isNull=false;
|
||||
|
||||
for (int i=0; i<attrcount; i++) {
|
||||
String attrName = xpp.getAttributeName(i);
|
||||
String attrVal = xpp.getAttributeValue(i);
|
||||
if ("name".equals(attrName)) {
|
||||
name=attrVal;
|
||||
} else if ("boost".equals(attrName)) {
|
||||
boost=Float.parseFloat(attrVal);
|
||||
} else if ("null".equals(attrName)) {
|
||||
isNull=StrUtils.parseBoolean(attrVal);
|
||||
} else {
|
||||
log.warning("Unknown attribute doc/field/@" + attrName);
|
||||
}
|
||||
}
|
||||
|
||||
// now get the field value
|
||||
String val = xpp.nextText(); // todo... text event for <field></field>???
|
||||
// need this line for isNull???
|
||||
// Don't add fields marked as null (for now at least)
|
||||
if (!isNull) {
|
||||
if (boost != 1.0f) {
|
||||
builder.addField(name,val,boost);
|
||||
} else {
|
||||
builder.addField(name,val);
|
||||
}
|
||||
}
|
||||
|
||||
// do I have to do a nextTag here to read the end_tag?
|
||||
|
||||
} // end field loop
|
||||
}
|
||||
|
||||
/**
|
||||
* A Convinince method for getting back a simple XML string indicating
|
||||
* successs of failure from an XML formated Update (from the Reader)
|
||||
*/
|
||||
public void doLegacyUpdate(Reader input, Writer output) {
|
||||
|
||||
try {
|
||||
NamedList ignored = this.update( input );
|
||||
output.write("<result status=\"0\"></result>");
|
||||
}
|
||||
catch( Exception ex ) {
|
||||
try {
|
||||
XML.writeXML(output,"result",SolrException.toStr(ex),"status","1");
|
||||
} catch (Exception ee) {
|
||||
log.severe("Error writing to output stream: "+ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Add documents with XML";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL:$";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface ContentStream {
|
||||
String getName();
|
||||
String getSourceInfo();
|
||||
String getContentType();
|
||||
Long getSize(); // size if we know it, otherwise null
|
||||
InputStream getStream() throws IOException;
|
||||
}
|
|
@ -17,41 +17,34 @@
|
|||
|
||||
package org.apache.solr.request;
|
||||
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrInfoMBean;
|
||||
import org.apache.solr.core.SolrException;
|
||||
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.search.DocList;
|
||||
import org.apache.solr.search.DocSet;
|
||||
import org.apache.solr.search.DocListAndSet;
|
||||
import org.apache.solr.search.SolrQueryParser;
|
||||
import org.apache.solr.search.QueryParsing;
|
||||
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.HighlightingUtils;
|
||||
import org.apache.solr.util.SolrPluginUtils;
|
||||
import org.apache.solr.util.DisMaxParams;
|
||||
import static org.apache.solr.request.SolrParams.*;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
|
||||
/* this is the standard logging framework for Solr */
|
||||
import static org.apache.solr.request.SolrParams.FACET;
|
||||
import static org.apache.solr.request.SolrParams.FQ;
|
||||
import static org.apache.solr.request.SolrParams.Q;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.search.DocListAndSet;
|
||||
import org.apache.solr.search.DocSet;
|
||||
import org.apache.solr.search.QueryParsing;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.search.SolrQueryParser;
|
||||
import org.apache.solr.util.DisMaxParams;
|
||||
import org.apache.solr.util.HighlightingUtils;
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.SolrPluginUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -122,9 +115,7 @@ import java.net.URL;
|
|||
* :TODO: make bf,pf,qf multival params now that SolrParams supports them
|
||||
* </pre>
|
||||
*/
|
||||
public class DisMaxRequestHandler
|
||||
implements SolrRequestHandler, SolrInfoMBean {
|
||||
|
||||
public class DisMaxRequestHandler extends RequestHandlerBase {
|
||||
|
||||
/**
|
||||
* A field we can't ever find in any schema, so we can safely tell
|
||||
|
@ -133,15 +124,6 @@ public class DisMaxRequestHandler
|
|||
*/
|
||||
private static String IMPOSSIBLE_FIELD_NAME = "\uFFFC\uFFFC\uFFFC";
|
||||
|
||||
// statistics
|
||||
// TODO: should we bother synchronizing these, or is an off-by-one error
|
||||
// acceptable every million requests or so?
|
||||
long numRequests;
|
||||
long numErrors;
|
||||
|
||||
SolrParams defaults;
|
||||
SolrParams appends;
|
||||
SolrParams invariants;
|
||||
|
||||
/** shorten the class references for utilities */
|
||||
private static class U extends SolrPluginUtils {
|
||||
|
@ -156,74 +138,24 @@ public class DisMaxRequestHandler
|
|||
super();
|
||||
}
|
||||
|
||||
/* returns URLs to the Wiki pages */
|
||||
public URL[] getDocs() {
|
||||
/* :TODO: need docs */
|
||||
return new URL[0];
|
||||
}
|
||||
public String getName() {
|
||||
return this.getClass().getName();
|
||||
}
|
||||
|
||||
public NamedList getStatistics() {
|
||||
NamedList lst = new NamedList();
|
||||
lst.add("requests", numRequests);
|
||||
lst.add("errors", numErrors);
|
||||
return lst;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return "$Revision:$";
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "DisjunctionMax Request Handler: Does relevancy based queries "
|
||||
+ "accross a variety of fields using configured boosts";
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return Category.QUERYHANDLER;
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return "$Id:$";
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return "$URL:$";
|
||||
}
|
||||
|
||||
/** sets the default variables for any usefull info it finds in the config
|
||||
* if a config option is not inthe format expected, logs an warning
|
||||
* and ignores it..
|
||||
*/
|
||||
public void init(NamedList args) {
|
||||
|
||||
// Handle an old format
|
||||
if (-1 == args.indexOf("defaults",0)) {
|
||||
// no explict defaults list, use all args implicitly
|
||||
// indexOf so "<null name="defaults"/> is valid indicator of no defaults
|
||||
defaults = SolrParams.toSolrParams(args);
|
||||
} else {
|
||||
Object o = args.get("defaults");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
defaults = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
o = args.get("appends");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
appends = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
o = args.get("invariants");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
invariants = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
// otherwise use the new one.
|
||||
super.init( args );
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
numRequests++;
|
||||
|
||||
try {
|
||||
U.setDefaults(req,defaults,appends,invariants);
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
|
||||
{
|
||||
SolrParams params = req.getParams();
|
||||
|
||||
int flags = 0;
|
||||
|
@ -385,12 +317,6 @@ public class DisMaxRequestHandler
|
|||
if(sumData != null)
|
||||
rsp.add("highlighting", sumData);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
SolrException.log(SolrCore.log,e);
|
||||
rsp.setException(e);
|
||||
numErrors++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,4 +337,34 @@ public class DisMaxRequestHandler
|
|||
}
|
||||
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "DisjunctionMax Request Handler: Does relevancy based queries "
|
||||
+ "accross a variety of fields using configured boosts";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL:$";
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL[] getDocs() {
|
||||
try {
|
||||
return new URL[] { new URL("http://wiki.apache.org/solr/DisMaxRequestHandler") };
|
||||
}
|
||||
catch( MalformedURLException ex ) { return null; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,13 @@ public abstract class SolrParams {
|
|||
*/
|
||||
public static final String FACET_PREFIX = "facet.prefix";
|
||||
|
||||
/** If the content stream should come from a URL */
|
||||
public static final String STREAM_URL = "stream.url";
|
||||
|
||||
/** If the content stream should come directly from a field */
|
||||
public static final String STREAM_BODY = "stream.body";
|
||||
|
||||
|
||||
/** returns the String value of a param, or null if not set */
|
||||
public abstract String get(String param);
|
||||
|
||||
|
|
|
@ -40,6 +40,10 @@ public interface SolrQueryRequest {
|
|||
*/
|
||||
public void setParams(SolrParams params);
|
||||
|
||||
/** A Collection of ContentStreams passed to the request
|
||||
*/
|
||||
public Iterable<ContentStream> getContentStreams();
|
||||
|
||||
/** Returns the original request parameters. As this
|
||||
* does not normally include configured defaults
|
||||
* it's more suitable for logging.
|
||||
|
@ -117,3 +121,5 @@ public interface SolrQueryRequest {
|
|||
******/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.solr.schema.IndexSchema;
|
|||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
@ -56,6 +57,7 @@ public abstract class SolrQueryRequestBase implements SolrQueryRequest {
|
|||
protected final SolrParams origParams;
|
||||
protected SolrParams params;
|
||||
protected Map<Object,Object> context;
|
||||
protected Iterable<ContentStream> streams;
|
||||
|
||||
public SolrQueryRequestBase(SolrCore core, SolrParams params) {
|
||||
this.core = core;
|
||||
|
@ -115,15 +117,18 @@ public abstract class SolrQueryRequestBase implements SolrQueryRequest {
|
|||
return s==null ? defval : s;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getQueryString() {
|
||||
return params.get(SolrParams.Q);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getQueryType() {
|
||||
return params.get(SolrParams.QT);
|
||||
}
|
||||
|
||||
// starting position in matches to return to client
|
||||
@Deprecated
|
||||
public int getStart() {
|
||||
return params.getInt(SolrParams.START, 0);
|
||||
}
|
||||
|
@ -175,6 +180,15 @@ public abstract class SolrQueryRequestBase implements SolrQueryRequest {
|
|||
}
|
||||
}
|
||||
|
||||
/** A Collection of ContentStreams passed to the request
|
||||
*/
|
||||
public Iterable<ContentStream> getContentStreams() {
|
||||
return streams;
|
||||
}
|
||||
|
||||
public void setContentStreams( Iterable<ContentStream> s ) {
|
||||
streams = s;
|
||||
}
|
||||
|
||||
public String getParamString() {
|
||||
return origParams.toString();
|
||||
|
|
|
@ -19,9 +19,10 @@ package org.apache.solr.request;
|
|||
|
||||
import org.apache.lucene.search.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.solr.util.StrUtils;
|
||||
import org.apache.solr.util.NamedList;
|
||||
|
@ -29,8 +30,11 @@ import org.apache.solr.util.HighlightingUtils;
|
|||
import org.apache.solr.util.SolrPluginUtils;
|
||||
import org.apache.solr.search.*;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrInfoMBean;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
|
||||
import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException;
|
||||
|
||||
import static org.apache.solr.request.SolrParams.*;
|
||||
|
||||
/**
|
||||
|
@ -53,43 +57,17 @@ import static org.apache.solr.request.SolrParams.*;
|
|||
* </ul>
|
||||
*
|
||||
*/
|
||||
public class StandardRequestHandler implements SolrRequestHandler, SolrInfoMBean {
|
||||
|
||||
// statistics
|
||||
// TODO: should we bother synchronizing these, or is an off-by-one error
|
||||
// acceptable every million requests or so?
|
||||
long numRequests;
|
||||
long numErrors;
|
||||
SolrParams defaults;
|
||||
SolrParams appends;
|
||||
SolrParams invariants;
|
||||
public class StandardRequestHandler extends RequestHandlerBase {
|
||||
|
||||
/** shorten the class references for utilities */
|
||||
private static class U extends SolrPluginUtils {
|
||||
/* :NOOP */
|
||||
}
|
||||
|
||||
public void init(NamedList args) {
|
||||
Object o = args.get("defaults");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
defaults = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
o = args.get("appends");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
appends = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
o = args.get("invariants");
|
||||
if (o != null && o instanceof NamedList) {
|
||||
invariants = SolrParams.toSolrParams((NamedList)o);
|
||||
}
|
||||
|
||||
}
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
|
||||
{
|
||||
|
||||
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
numRequests++;
|
||||
|
||||
try {
|
||||
U.setDefaults(req,defaults,appends,invariants);
|
||||
SolrParams p = req.getParams();
|
||||
String sreq = p.get(Q);
|
||||
|
||||
|
@ -165,17 +143,6 @@ public class StandardRequestHandler implements SolrRequestHandler, SolrInfoMBean
|
|||
results.docList, query, req, new String[]{defaultField});
|
||||
if(sumData != null)
|
||||
rsp.add("highlighting", sumData);
|
||||
|
||||
} catch (SolrException e) {
|
||||
rsp.setException(e);
|
||||
numErrors++;
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
SolrException.log(SolrCore.log,e);
|
||||
rsp.setException(e);
|
||||
numErrors++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,23 +166,14 @@ public class StandardRequestHandler implements SolrRequestHandler, SolrInfoMBean
|
|||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
|
||||
public String getName() {
|
||||
return StandardRequestHandler.class.getName();
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return SolrCore.version;
|
||||
return "$Revision$";
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "The standard Solr request handler";
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return Category.QUERYHANDLER;
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return "$Id$";
|
||||
}
|
||||
|
@ -225,14 +183,10 @@ public class StandardRequestHandler implements SolrRequestHandler, SolrInfoMBean
|
|||
}
|
||||
|
||||
public URL[] getDocs() {
|
||||
return null;
|
||||
try {
|
||||
return new URL[] { new URL("http://wiki.apache.org/solr/StandardRequestHandler") };
|
||||
}
|
||||
|
||||
public NamedList getStatistics() {
|
||||
NamedList lst = new NamedList();
|
||||
lst.add("requests", numRequests);
|
||||
lst.add("errors", numErrors);
|
||||
return lst;
|
||||
catch( MalformedURLException ex ) { return null; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.solr.util;
|
|||
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.handler.XmlUpdateRequestHandler;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
import org.apache.solr.request.QueryResponseWriter;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
|
@ -36,9 +37,12 @@ import javax.xml.xpath.XPathFactory;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -62,6 +66,7 @@ public class TestHarness {
|
|||
private SolrCore core;
|
||||
private XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
private DocumentBuilder builder;
|
||||
XmlUpdateRequestHandler updater;
|
||||
|
||||
/**
|
||||
* Assumes "solrconfig.xml" is the config file to use, and
|
||||
|
@ -93,26 +98,34 @@ public class TestHarness {
|
|||
SolrConfig.initConfig(confFile);
|
||||
core = new SolrCore(dataDirectory, new IndexSchema(schemaFile));
|
||||
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
|
||||
updater = new XmlUpdateRequestHandler();
|
||||
updater.init( null );
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Processes an "update" (add, commit or optimize) and
|
||||
* returns the response as a String.
|
||||
*
|
||||
* The better approach is to instanciate a Updatehandler directly
|
||||
*
|
||||
* @param xml The XML of the update
|
||||
* @return The XML response to the update
|
||||
*/
|
||||
@Deprecated
|
||||
public String update(String xml) {
|
||||
|
||||
StringReader req = new StringReader(xml);
|
||||
StringWriter writer = new StringWriter(32000);
|
||||
core.update(req, writer);
|
||||
return writer.toString();
|
||||
|
||||
updater.doLegacyUpdate(req, writer);
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.solr.core.Config;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.request.ContentStream;
|
||||
import org.apache.solr.request.MapSolrParams;
|
||||
import org.apache.solr.request.MultiMapSolrParams;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.util.AbstractSolrTestCase;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SolrRequestParserTest extends AbstractSolrTestCase {
|
||||
|
||||
public String getSchemaFile() { return "schema.xml"; }
|
||||
public String getSolrConfigFile() { return "solrconfig.xml"; }
|
||||
|
||||
SolrRequestParsers parser;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
parser = new SolrRequestParsers( SolrCore.getSolrCore(), SolrConfig.config );
|
||||
}
|
||||
|
||||
public void testStreamBody() throws Exception
|
||||
{
|
||||
String body1 = "AMANAPLANPANAMA";
|
||||
String body2 = "qwertasdfgzxcvb";
|
||||
String body3 = "1234567890";
|
||||
|
||||
Map<String,String[]> args = new HashMap<String, String[]>();
|
||||
args.put( SolrParams.STREAM_BODY, new String[] {body1} );
|
||||
|
||||
// Make sure it got a single stream in and out ok
|
||||
List<ContentStream> streams = new ArrayList<ContentStream>();
|
||||
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
|
||||
assertEquals( 1, streams.size() );
|
||||
assertEquals( body1, IOUtils.toString( streams.get(0).getStream() ) );
|
||||
|
||||
// Now add three and make sure they come out ok
|
||||
streams = new ArrayList<ContentStream>();
|
||||
args.put( SolrParams.STREAM_BODY, new String[] {body1,body2,body3} );
|
||||
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
|
||||
assertEquals( 3, streams.size() );
|
||||
ArrayList<String> input = new ArrayList<String>();
|
||||
ArrayList<String> output = new ArrayList<String>();
|
||||
input.add( body1 );
|
||||
input.add( body2 );
|
||||
input.add( body3 );
|
||||
output.add( IOUtils.toString( streams.get(0).getStream() ) );
|
||||
output.add( IOUtils.toString( streams.get(1).getStream() ) );
|
||||
output.add( IOUtils.toString( streams.get(2).getStream() ) );
|
||||
// sort them so the output is consistent
|
||||
Collections.sort( input );
|
||||
Collections.sort( output );
|
||||
assertEquals( input.toString(), output.toString() );
|
||||
}
|
||||
|
||||
|
||||
public void testStreamURL() throws Exception
|
||||
{
|
||||
boolean ok = false;
|
||||
String url = "http://svn.apache.org/repos/asf/lucene/solr/trunk/";
|
||||
String txt = null;
|
||||
try {
|
||||
txt = IOUtils.toString( new URL(url).openStream() );
|
||||
}
|
||||
catch( Exception ex ) {
|
||||
// TODO - should it fail/skip?
|
||||
fail( "this test only works if you have a network connection." );
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String,String[]> args = new HashMap<String, String[]>();
|
||||
args.put( SolrParams.STREAM_URL, new String[] {url} );
|
||||
|
||||
// Make sure it got a single stream in and out ok
|
||||
List<ContentStream> streams = new ArrayList<ContentStream>();
|
||||
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
|
||||
assertEquals( 1, streams.size() );
|
||||
assertEquals( txt, IOUtils.toString( streams.get(0).getStream() ) );
|
||||
}
|
||||
}
|
|
@ -255,6 +255,8 @@
|
|||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<!-- enable streaming for testing... -->
|
||||
<requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048" />
|
||||
|
||||
<admin>
|
||||
<defaultQuery>solr</defaultQuery>
|
||||
|
|
|
@ -30,6 +30,17 @@
|
|||
"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"/>
|
||||
-->
|
||||
|
||||
<!-- Any path (name) registered in solrconfig.xml will be sent to that filter -->
|
||||
<filter>
|
||||
<filter-name>SolrRequestFilter</filter-name>
|
||||
<filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>SolrRequestFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- Otherwise it will continue to the old servlets -->
|
||||
|
||||
<servlet>
|
||||
<servlet-name>SolrServer</servlet-name>
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.NoInitialContextException;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.solr.core.Config;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.request.QueryResponseWriter;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
|
||||
/**
|
||||
* This filter looks at the incoming URL maps them to handlers defined in solrconfig.xml
|
||||
*/
|
||||
public class SolrDispatchFilter implements Filter
|
||||
{
|
||||
final Logger log = Logger.getLogger(SolrDispatchFilter.class.getName());
|
||||
|
||||
protected SolrCore core;
|
||||
protected SolrRequestParsers parsers;
|
||||
|
||||
public void init(FilterConfig config) throws ServletException
|
||||
{
|
||||
log.info("SolrDispatchFilter.init()");
|
||||
try {
|
||||
Context c = new InitialContext();
|
||||
|
||||
/***
|
||||
System.out.println("Enumerating JNDI Context=" + c);
|
||||
NamingEnumeration<NameClassPair> en = c.list("java:comp/env");
|
||||
while (en.hasMore()) {
|
||||
NameClassPair ncp = en.next();
|
||||
System.out.println(" ENTRY:" + ncp);
|
||||
}
|
||||
System.out.println("JNDI lookup=" + c.lookup("java:comp/env/solr/home"));
|
||||
***/
|
||||
|
||||
String home = (String)c.lookup("java:comp/env/solr/home");
|
||||
if (home!=null) Config.setInstanceDir(home);
|
||||
} catch (NoInitialContextException e) {
|
||||
log.info("JNDI not configured for Solr (NoInitialContextEx)");
|
||||
} catch (NamingException e) {
|
||||
log.info("No /solr/home in JNDI");
|
||||
}
|
||||
|
||||
log.info("user.dir=" + System.getProperty("user.dir"));
|
||||
core = SolrCore.getSolrCore();
|
||||
parsers = new SolrRequestParsers( core, SolrConfig.config );
|
||||
|
||||
log.info("SolrDispatchFilter.init() done");
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
core.close();
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||
{
|
||||
if( request instanceof HttpServletRequest) {
|
||||
HttpServletRequest req = (HttpServletRequest)request;
|
||||
try {
|
||||
String path = req.getServletPath();
|
||||
if( req.getPathInfo() != null ) {
|
||||
// this lets you handle /update/commit when /update is a servlet
|
||||
path += req.getPathInfo();
|
||||
}
|
||||
int idx = path.indexOf( ':' );
|
||||
if( idx > 0 ) {
|
||||
// save the portion after the ':' for a 'handler' path parameter
|
||||
path = path.substring( 0, idx );
|
||||
}
|
||||
|
||||
SolrRequestHandler handler = core.getRequestHandler( path );
|
||||
if( handler != null ) {
|
||||
SolrQueryRequest solrReq = parsers.parse( path, req );
|
||||
SolrQueryResponse solrRsp = new SolrQueryResponse();
|
||||
core.execute( handler, solrReq, solrRsp );
|
||||
if( solrRsp.getException() != null ) {
|
||||
sendError( (HttpServletResponse)response, solrRsp.getException() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Now write it out
|
||||
QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
|
||||
response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
|
||||
PrintWriter out = response.getWriter();
|
||||
responseWriter.write(out, solrReq, solrRsp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch( Throwable ex ) {
|
||||
sendError( (HttpServletResponse)response, ex );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise let the webapp handle the request
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
protected void sendError(HttpServletResponse res, Throwable ex) throws IOException
|
||||
{
|
||||
int code=500;
|
||||
String trace = "";
|
||||
if( ex instanceof SolrException ) {
|
||||
code = ((SolrException)ex).code();
|
||||
}
|
||||
|
||||
// For any regular code, don't include the stack trace
|
||||
if( code == 500 || code < 100 ) {
|
||||
StringWriter sw = new StringWriter();
|
||||
ex.printStackTrace(new PrintWriter(sw));
|
||||
trace = "\n\n"+sw.toString();
|
||||
|
||||
SolrException.logOnce(log,null,ex );
|
||||
|
||||
// non standard codes have undefined results with various servers
|
||||
if( code < 100 ) {
|
||||
log.warning( "invalid return code: "+code );
|
||||
code = 500;
|
||||
}
|
||||
}
|
||||
res.sendError( code, ex.getMessage() + trace );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,383 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.servlet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.solr.core.Config;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.request.ContentStream;
|
||||
import org.apache.solr.request.MultiMapSolrParams;
|
||||
import org.apache.solr.request.ServletSolrParams;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryRequestBase;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
|
||||
public class SolrRequestParsers
|
||||
{
|
||||
final Logger log = Logger.getLogger(SolrRequestParsers.class.getName());
|
||||
|
||||
// Should these constants be in a more public place?
|
||||
public static final String MULTIPART = "multipart";
|
||||
public static final String RAW = "raw";
|
||||
public static final String SIMPLE = "simple";
|
||||
public static final String STANDARD = "standard";
|
||||
|
||||
private HashMap<String, SolrRequestParser> parsers;
|
||||
private SolrCore core;
|
||||
private boolean enableRemoteStreams = false;
|
||||
private StandardRequestParser standard;
|
||||
|
||||
public SolrRequestParsers( SolrCore core, Config config )
|
||||
{
|
||||
this.core = core;
|
||||
|
||||
long uploadLimitKB = 2000; // 2MB default
|
||||
NodeList nodes = (NodeList)config.evaluate("requestParsers", XPathConstants.NODESET);
|
||||
if( nodes!=null && nodes.getLength()>0 ) {
|
||||
// only look at the first node.
|
||||
NamedNodeMap attrs = nodes.item(0).getAttributes();
|
||||
Node node = attrs.getNamedItem( "enableRemoteStreaming" );
|
||||
if( node != null ) {
|
||||
enableRemoteStreams = Boolean.parseBoolean( node.getTextContent() );
|
||||
}
|
||||
node = attrs.getNamedItem( "multipartUploadLimitInKB" );
|
||||
if( node != null ) {
|
||||
uploadLimitKB = Long.parseLong( node.getTextContent() );
|
||||
}
|
||||
}
|
||||
|
||||
MultipartRequestParser multi = new MultipartRequestParser( uploadLimitKB );
|
||||
RawRequestParser raw = new RawRequestParser();
|
||||
standard = new StandardRequestParser( multi, raw );
|
||||
|
||||
// I don't see a need to have this publically configured just yet
|
||||
// adding it is trivial
|
||||
parsers = new HashMap<String, SolrRequestParser>();
|
||||
parsers.put( MULTIPART, multi );
|
||||
parsers.put( RAW, raw );
|
||||
parsers.put( SIMPLE, new SimpleRequestParser() );
|
||||
parsers.put( STANDARD, standard );
|
||||
parsers.put( "", standard );
|
||||
}
|
||||
|
||||
public SolrQueryRequest parse( String path, HttpServletRequest req ) throws Exception
|
||||
{
|
||||
SolrRequestParser parser = standard;
|
||||
|
||||
// TODO -- in the future, we could pick a different parser based on the request
|
||||
|
||||
// Pick the parer from the request...
|
||||
ArrayList<ContentStream> streams = new ArrayList<ContentStream>(1);
|
||||
SolrParams params = parser.parseParamsAndFillStreams( req, streams );
|
||||
SolrQueryRequest sreq = buildRequestFrom( params, streams );
|
||||
|
||||
// If there is some path left over, add it to the context
|
||||
int idx = req.getServletPath().indexOf( ':' );
|
||||
if( idx > 0 ) {
|
||||
sreq.getContext().put( "path", req.getServletPath().substring( idx+1 ) );
|
||||
}
|
||||
return sreq;
|
||||
}
|
||||
|
||||
SolrQueryRequest buildRequestFrom( SolrParams params, List<ContentStream> streams ) throws Exception
|
||||
{
|
||||
// Handle anything with a remoteURL
|
||||
String[] strs = params.getParams( SolrParams.STREAM_URL );
|
||||
if( strs != null ) {
|
||||
if( !enableRemoteStreams ) {
|
||||
throw new SolrException( 400, "Remote Streaming is disabled." );
|
||||
}
|
||||
for( final String url : strs ) {
|
||||
final URLConnection conn = new URL(url).openConnection();
|
||||
streams.add( new ContentStream() {
|
||||
public String getContentType() { return conn.getContentType(); }
|
||||
public String getName() { return url; }
|
||||
public Long getSize() { return new Long( conn.getContentLength() ); }
|
||||
public String getSourceInfo() {
|
||||
return SolrParams.STREAM_URL;
|
||||
}
|
||||
public InputStream getStream() throws IOException {
|
||||
return conn.getInputStream();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check for streams in the request parameters
|
||||
strs = params.getParams( SolrParams.STREAM_BODY );
|
||||
if( strs != null ) {
|
||||
for( final String body : strs ) {
|
||||
streams.add( new ContentStream() {
|
||||
public String getContentType() { return null; } // Is there anything meaningful?
|
||||
public String getName() { return null; }
|
||||
public Long getSize() { return null; }
|
||||
public String getSourceInfo() {
|
||||
return SolrParams.STREAM_BODY;
|
||||
}
|
||||
public InputStream getStream() throws IOException {
|
||||
return new ByteArrayInputStream( body.getBytes() );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SolrQueryRequestBase q = new SolrQueryRequestBase( core, params ) { };
|
||||
if( streams != null && streams.size() > 0 ) {
|
||||
q.setContentStreams( streams );
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a standard query string map it into solr params
|
||||
*/
|
||||
public static MultiMapSolrParams parseQueryString(String queryString)
|
||||
{
|
||||
Map<String,String[]> map = new HashMap<String, String[]>();
|
||||
if( queryString != null && queryString.length() > 0 ) {
|
||||
for( String kv : queryString.split( "&" ) ) {
|
||||
int idx = kv.indexOf( '=' );
|
||||
if( idx > 0 ) {
|
||||
String name = URLDecoder.decode( kv.substring( 0, idx ));
|
||||
String value = URLDecoder.decode( kv.substring( idx+1 ));
|
||||
MultiMapSolrParams.addParam( name, value, map );
|
||||
}
|
||||
else {
|
||||
String name = URLDecoder.decode( kv );
|
||||
MultiMapSolrParams.addParam( name, "", map );
|
||||
}
|
||||
}
|
||||
}
|
||||
return new MultiMapSolrParams( map );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
// I guess we don't really even need the interface, but i'll keep it here just for kicks
|
||||
interface SolrRequestParser
|
||||
{
|
||||
public SolrParams parseParamsAndFillStreams(
|
||||
final HttpServletRequest req, ArrayList<ContentStream> streams ) throws Exception;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The simple parser just uses the params directly
|
||||
*/
|
||||
class SimpleRequestParser implements SolrRequestParser
|
||||
{
|
||||
public SolrParams parseParamsAndFillStreams(
|
||||
final HttpServletRequest req, ArrayList<ContentStream> streams ) throws Exception
|
||||
{
|
||||
return new ServletSolrParams(req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The simple parser just uses the params directly
|
||||
*/
|
||||
class RawRequestParser implements SolrRequestParser
|
||||
{
|
||||
public SolrParams parseParamsAndFillStreams(
|
||||
final HttpServletRequest req, ArrayList<ContentStream> streams ) throws Exception
|
||||
{
|
||||
streams.add( new ContentStream() {
|
||||
public String getContentType() {
|
||||
return req.getContentType();
|
||||
}
|
||||
public String getName() {
|
||||
return null; // Is there any meaningfull name?
|
||||
}
|
||||
public String getSourceInfo() {
|
||||
return null; // Is there any meaningfull name?
|
||||
}
|
||||
public Long getSize() {
|
||||
String v = req.getHeader( "Content-Length" );
|
||||
if( v != null ) {
|
||||
return Long.valueOf( v );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public InputStream getStream() throws IOException {
|
||||
return req.getInputStream();
|
||||
}
|
||||
});
|
||||
return SolrRequestParsers.parseQueryString( req.getQueryString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Extract Multipart streams
|
||||
*/
|
||||
class MultipartRequestParser implements SolrRequestParser
|
||||
{
|
||||
private long uploadLimitKB;
|
||||
|
||||
public MultipartRequestParser( long limit )
|
||||
{
|
||||
uploadLimitKB = limit;
|
||||
}
|
||||
|
||||
public SolrParams parseParamsAndFillStreams(
|
||||
final HttpServletRequest req, ArrayList<ContentStream> streams ) throws Exception
|
||||
{
|
||||
if( !ServletFileUpload.isMultipartContent(req) ) {
|
||||
throw new SolrException( 400, "Not multipart content! "+req.getContentType() );
|
||||
}
|
||||
|
||||
MultiMapSolrParams params = SolrRequestParsers.parseQueryString( req.getQueryString() );
|
||||
|
||||
// Create a factory for disk-based file items
|
||||
DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||
|
||||
// Set factory constraints
|
||||
// TODO - configure factory.setSizeThreshold(yourMaxMemorySize);
|
||||
// TODO - configure factory.setRepository(yourTempDirectory);
|
||||
|
||||
// Create a new file upload handler
|
||||
ServletFileUpload upload = new ServletFileUpload(factory);
|
||||
upload.setSizeMax( uploadLimitKB*1024 );
|
||||
|
||||
// Parse the request
|
||||
List items = upload.parseRequest(req);
|
||||
Iterator iter = items.iterator();
|
||||
while (iter.hasNext()) {
|
||||
FileItem item = (FileItem) iter.next();
|
||||
|
||||
// If its a form field, put it in our parameter map
|
||||
if (item.isFormField()) {
|
||||
MultiMapSolrParams.addParam(
|
||||
item.getFieldName(),
|
||||
item.getString(), params.getMap() );
|
||||
}
|
||||
// Only add it if it actually has something...
|
||||
else if( item.getSize() > 0 ) {
|
||||
streams.add( new FileItemContentStream( item ) );
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a FileItem as a ContentStream
|
||||
*/
|
||||
private static class FileItemContentStream implements ContentStream
|
||||
{
|
||||
FileItem item;
|
||||
|
||||
public FileItemContentStream( FileItem f )
|
||||
{
|
||||
item = f;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return item.getContentType();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return item.getName();
|
||||
}
|
||||
|
||||
public InputStream getStream() throws IOException {
|
||||
return item.getInputStream();
|
||||
}
|
||||
|
||||
public String getSourceInfo() {
|
||||
return item.getFieldName();
|
||||
}
|
||||
|
||||
public Long getSize()
|
||||
{
|
||||
return item.getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The default Logic
|
||||
*/
|
||||
class StandardRequestParser implements SolrRequestParser
|
||||
{
|
||||
MultipartRequestParser multipart;
|
||||
RawRequestParser raw;
|
||||
|
||||
StandardRequestParser( MultipartRequestParser multi, RawRequestParser raw )
|
||||
{
|
||||
this.multipart = multi;
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
public SolrParams parseParamsAndFillStreams(
|
||||
final HttpServletRequest req, ArrayList<ContentStream> streams ) throws Exception
|
||||
{
|
||||
String method = req.getMethod().toUpperCase();
|
||||
if( "GET".equals( method ) ) {
|
||||
return new ServletSolrParams(req);
|
||||
}
|
||||
if( "POST".equals( method ) ) {
|
||||
String contentType = req.getContentType();
|
||||
if( contentType != null ) {
|
||||
if( "application/x-www-form-urlencoded".equals( contentType.toLowerCase() ) ) {
|
||||
return new ServletSolrParams(req); // just get the params from parameterMap
|
||||
}
|
||||
if( ServletFileUpload.isMultipartContent(req) ) {
|
||||
return multipart.parseParamsAndFillStreams(req, streams);
|
||||
}
|
||||
}
|
||||
return raw.parseParamsAndFillStreams(req, streams);
|
||||
}
|
||||
throw new SolrException( 400, "Unsuported method: "+method );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -17,29 +17,27 @@
|
|||
|
||||
package org.apache.solr.servlet;
|
||||
|
||||
import org.apache.solr.core.Config;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.QueryResponseWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.NoInitialContextException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.request.QueryResponseWriter;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
|
||||
/**
|
||||
* @author yonik
|
||||
* @author <a href='mailto:mbaranczak@epublishing.com'> Mike Baranczak </a>
|
||||
*/
|
||||
|
||||
@Deprecated
|
||||
public class SolrServlet extends HttpServlet {
|
||||
|
||||
final Logger log = Logger.getLogger(SolrServlet.class.getName());
|
||||
|
@ -47,38 +45,10 @@ public class SolrServlet extends HttpServlet {
|
|||
|
||||
public void init() throws ServletException {
|
||||
log.info("SolrServlet.init()");
|
||||
try {
|
||||
Context c = new InitialContext();
|
||||
|
||||
/***
|
||||
System.out.println("Enumerating JNDI Context=" + c);
|
||||
NamingEnumeration<NameClassPair> en = c.list("java:comp/env");
|
||||
while (en.hasMore()) {
|
||||
NameClassPair ncp = en.next();
|
||||
System.out.println(" ENTRY:" + ncp);
|
||||
}
|
||||
System.out.println("JNDI lookup=" + c.lookup("java:comp/env/solr/home"));
|
||||
***/
|
||||
|
||||
String home = (String)c.lookup("java:comp/env/solr/home");
|
||||
if (home!=null) Config.setInstanceDir(home);
|
||||
} catch (NoInitialContextException e) {
|
||||
log.info("JNDI not configured for Solr (NoInitialContextEx)");
|
||||
} catch (NamingException e) {
|
||||
log.info("No /solr/home in JNDI");
|
||||
}
|
||||
|
||||
log.info("user.dir=" + System.getProperty("user.dir"));
|
||||
core = SolrCore.getSolrCore();
|
||||
|
||||
log.info("SolrServlet.init() done");
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
core.close();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
doGet(request,response);
|
||||
}
|
||||
|
@ -87,7 +57,13 @@ public class SolrServlet extends HttpServlet {
|
|||
SolrServletRequest solrReq = new SolrServletRequest(core, request);;
|
||||
SolrQueryResponse solrRsp = new SolrQueryResponse();
|
||||
try {
|
||||
core.execute(solrReq, solrRsp);
|
||||
|
||||
SolrRequestHandler handler = core.getRequestHandler(solrReq.getQueryType());
|
||||
if (handler==null) {
|
||||
log.warning("Unknown Request Handler '" + solrReq.getQueryType() +"' :" + solrReq);
|
||||
throw new SolrException(400,"Unknown Request Handler '" + solrReq.getQueryType() + "'", true);
|
||||
}
|
||||
core.execute(handler, solrReq, solrRsp );
|
||||
if (solrRsp.getException() == null) {
|
||||
QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
|
||||
response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
|
||||
|
@ -127,14 +103,4 @@ public class SolrServlet extends HttpServlet {
|
|||
SolrException.log(log,e);
|
||||
}
|
||||
}
|
||||
|
||||
final int getParam(HttpServletRequest request, String param, int defval) {
|
||||
final String pval = request.getParameter(param);
|
||||
return (pval==null) ? defval : Integer.parseInt(pval);
|
||||
}
|
||||
|
||||
final boolean paramExists(HttpServletRequest request, String param) {
|
||||
return request.getParameter(param)!=null ? true : false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,41 +15,46 @@ package org.apache.solr.servlet;/**
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.request.XMLResponseWriter;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.QueryResponseWriter;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.ServletException;
|
||||
import java.util.logging.Logger;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.handler.XmlUpdateRequestHandler;
|
||||
import org.apache.solr.request.QueryResponseWriter;
|
||||
import org.apache.solr.request.XMLResponseWriter;
|
||||
import org.apache.solr.util.XML;
|
||||
|
||||
/**
|
||||
* @author yonik
|
||||
* @version $Id$
|
||||
*/
|
||||
@Deprecated
|
||||
public class SolrUpdateServlet extends HttpServlet {
|
||||
final Logger log = Logger.getLogger(SolrUpdateServlet.class.getName());
|
||||
private SolrCore core;
|
||||
|
||||
XmlUpdateRequestHandler legacyUpdateHandler;
|
||||
XMLResponseWriter xmlResponseWriter;
|
||||
|
||||
public void init() throws ServletException
|
||||
{
|
||||
core = SolrCore.getSolrCore();
|
||||
legacyUpdateHandler = new XmlUpdateRequestHandler();
|
||||
legacyUpdateHandler.init( null );
|
||||
|
||||
log.info("SolrUpdateServlet.init() done");
|
||||
}
|
||||
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
BufferedReader requestReader = request.getReader();
|
||||
response.setContentType(QueryResponseWriter.CONTENT_TYPE_XML_UTF8);
|
||||
PrintWriter responseWriter = response.getWriter();
|
||||
core.update(requestReader, responseWriter);
|
||||
|
||||
PrintWriter writer = response.getWriter();
|
||||
legacyUpdateHandler.doLegacyUpdate(requestReader, writer);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue