diff --git a/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java b/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java new file mode 100644 index 00000000000..688d692193a --- /dev/null +++ b/src/test/org/apache/solr/servlet/DirectSolrConnectionTest.java @@ -0,0 +1,83 @@ +/** + * 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 org.apache.solr.request.SolrParams; +import org.apache.solr.util.AbstractSolrTestCase; + + + +public class DirectSolrConnectionTest extends AbstractSolrTestCase +{ + public String getSchemaFile() { return "solr/crazy-path-to-schema.xml"; } + public String getSolrConfigFile() { return "solr/crazy-path-to-config.xml"; } + + DirectSolrConnection direct; + + @Override + public void setUp() throws Exception + { + super.setUp(); + direct = new DirectSolrConnection(); + } + + // Check that a request gets back the echoParams call + public void testSimpleRequest() throws Exception + { + String pathAndParams = "/select?wt=xml&version=2.2&echoParams=explicit&q=*:*"; + + String got = direct.request( pathAndParams, null ); + + assertTrue( got.indexOf( "explicit" ) > 5 ); + + + // It should throw an exception for unknown handler + try { + direct.request( "/path to nonexistang thingy!!", null ); + fail( "should throw an exception" ); + } + catch( Exception ex ){} + } + + + // Check that a request gets back the echoParams call + public void testInsertThenSelect() throws Exception + { + String value = "Kittens!!! \u20AC"; + String[] cmds = new String[] { + "42", + "42"+value+"", + "" + }; + String getIt = "/select?wt=xml&q=id:42"; + + // Test using the Stream body parameter + for( String cmd : cmds ) { + direct.request( "/update?"+SolrParams.STREAM_BODY+"="+cmd, null ); + } + String got = direct.request( getIt, null ); + assertTrue( got.indexOf( value ) > 0 ); + + // Same thing using the posted body + for( String cmd : cmds ) { + direct.request( "/update", cmd ); + } + got = direct.request( getIt, null ); + assertTrue( got.indexOf( value ) > 0 ); + } +} diff --git a/src/test/test-files/solr/crazy-path-to-config.xml b/src/test/test-files/solr/crazy-path-to-config.xml index 6c8a655c2c3..03a07739e07 100644 --- a/src/test/test-files/solr/crazy-path-to-config.xml +++ b/src/test/test-files/solr/crazy-path-to-config.xml @@ -62,6 +62,8 @@ implicit + + diff --git a/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java b/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java new file mode 100644 index 00000000000..dd554f30842 --- /dev/null +++ b/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java @@ -0,0 +1,180 @@ +/** + * 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.File; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +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.MapSolrParams; +import org.apache.solr.request.QueryResponseWriter; +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.schema.IndexSchema; +import org.apache.solr.util.ContentStream; +import org.apache.solr.util.ContentStreamBase; + +/** + * DirectSolrConnection provides an interface to solr that is similar to + * the the HTTP interface, but does not require an HTTP connection. + * + * This class is designed to be as simple as possible and alow for more flexibility + * in how you interface to solr. + * + * @author ryan + * @version $Id$ + * @since solr 1.2 + */ +public class DirectSolrConnection +{ + final SolrCore core; + final SolrRequestParsers parser; + + /** + * Initialize using the static singleton SolrCore.getSolrCore(). + */ + public DirectSolrConnection() + { + core = SolrCore.getSolrCore(); + parser = new SolrRequestParsers( core, SolrConfig.config ); + } + + /** + * Initialize using an explicit SolrCore + */ + public DirectSolrConnection( SolrCore c ) + { + core = c; + parser = new SolrRequestParsers( core, SolrConfig.config ); + } + + /** + * This constructor is designed to make it easy for JNI embedded applications + * to setup the entire solr environment with a simple interface. It takes three parameters: + * + * instanceDir: The solr instance directory. If null, it will check the standard + * places first (JNDI,properties,"solr" directory) + * + * dataDir: where the index is stored. + * + * loggingPath: Path to a java.util.logging.config.file. If the path represents + * an absolute path or is relative to the CWD, it will use that. Next it will try a path + * relative to the instanceDir. If none of these files exist, it will error. + */ + public DirectSolrConnection( String instanceDir, String dataDir, String loggingPath ) + { + // Set the instance directory + if( instanceDir != null ) { + if( Config.isInstanceDirInitialized() ) { + String dir = Config.getInstanceDir(); + if( !dir.equals( instanceDir ) ) { + throw new SolrException( 500, "already initalized: "+dir ); + } + } + Config.setInstanceDir( instanceDir ); + } + + // If a loggingPath is specified, try using that + if( loggingPath != null ) { + File loggingConfig = new File( loggingPath ); + if( !loggingConfig.exists() ) { + loggingConfig = new File( new File(Config.getInstanceDir()), loggingPath ); + } + if( loggingConfig.exists() ) { + System.setProperty("java.util.logging.config.file", loggingConfig.getAbsolutePath() ); + } + else { + throw new SolrException( 500, "can not find logging file: "+loggingConfig ); + } + } + + // If the Data directory is specified, initalize SolrCore directly + if( dataDir != null ) { + core = new SolrCore( dataDir, new IndexSchema(instanceDir+"/conf/schema.xml")); + } + else { + core = SolrCore.getSolrCore(); + } + parser = new SolrRequestParsers( core, SolrConfig.config ); + } + + + /** + * For example: + * + * String json = solr.request( "/select?qt=dismax&wt=json&q=...", null ); + * String xml = solr.request( "/update", " 0 ) { + path = pathAndParams.substring( 0, idx ); + params = SolrRequestParsers.parseQueryString( pathAndParams.substring(idx+1) ); + } + else { + path= pathAndParams; + params = new MapSolrParams( new HashMap() ); + } + + // Extract the handler from the path or params + SolrRequestHandler handler = core.getRequestHandler( path ); + if( handler == null ) { + if( "/select".equals( path ) || "/select/".equalsIgnoreCase( path) ) { + String qt = params.get( SolrParams.QT ); + handler = core.getRequestHandler( qt ); + if( handler == null ) { + throw new SolrException( 400, "unknown handler: "+qt); + } + } + } + if( handler == null ) { + throw new SolrException( 400, "unknown handler: "+path ); + } + + // Make a stream for the 'body' content + List streams = new ArrayList( 1 ); + if( body != null && body.length() > 0 ) { + streams.add( new ContentStreamBase.StringStream( body ) ); + } + + SolrQueryRequest req = parser.buildRequestFrom( params, streams ); + SolrQueryResponse rsp = new SolrQueryResponse(); + core.execute( handler, req, rsp ); + if( rsp.getException() != null ) { + throw rsp.getException(); + } + + // Now write it out + QueryResponseWriter responseWriter = core.getQueryResponseWriter(req); + StringWriter out = new StringWriter(); + responseWriter.write(out, req, rsp); + return out.toString(); + } +}