Author: ryan
Date: Wed Jan 2 09:15:30 2008
New Revision: 608150
URL: http://svn.apache.org/viewvc?rev=608150&view=rev
Log:
SOLR-142: Added RawResponseWriter and ShowFileRequestHandler. This returns
config files directly. If the AdminHandlers is configured, this will be added
automatically.
Added:
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
(with props)
lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java
(with props)
Modified:
lucene/solr/trunk/CHANGES.txt
lucene/solr/trunk/example/solr/conf/solrconfig.xml
lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/AdminHandlers.java
lucene/solr/trunk/src/webapp/resources/admin/get-file.jsp
lucene/solr/trunk/src/webapp/resources/admin/index.jsp
Modified: lucene/solr/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/CHANGES.txt?rev=608150&r1=608149&r2=608150&view=diff
==============================================================================
--- lucene/solr/trunk/CHANGES.txt (original)
+++ lucene/solr/trunk/CHANGES.txt Wed Jan 2 09:15:30 2008
@@ -175,6 +175,10 @@
<requestHandler name="/admin/"
class="org.apache.solr.handler.admin.AdminHandlers" />
This will register:
Luke/SystemInfo/PluginInfo/ThreadDump/PropertiesRequestHandler.
(ryan)
+
+35. SOLR-142: Added RawResponseWriter and ShowFileRequestHandler. This
returns config
+ files directly. If the AdminHandlers is configured, this will be added
automatically.
+ (ryan)
Changes in runtime behavior
Modified: lucene/solr/trunk/example/solr/conf/solrconfig.xml
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/example/solr/conf/solrconfig.xml?rev=608150&r1=608149&r2=608150&view=diff
==============================================================================
--- lucene/solr/trunk/example/solr/conf/solrconfig.xml (original)
+++ lucene/solr/trunk/example/solr/conf/solrconfig.xml Wed Jan 2 09:15:30 2008
@@ -502,7 +502,15 @@
<requestHandler name="/admin/plugins"
class="org.apache.solr.handler.admin.PluginInfoHandler" />
<requestHandler name="/admin/threads"
class="org.apache.solr.handler.admin.ThreadDumpHandler" />
<requestHandler name="/admin/properties"
class="org.apache.solr.handler.admin.PropertiesRequestHandler" />
+ <requestHandler name="/admin/file"
class="org.apache.solr.handler.admin.ShowFileRequestHandler" >
+ If you wish to hide files under ${solr.home}/conf, explicitly register the
ShowFileRequestHandler using:
+ <requestHandler name="/admin/file"
class="org.apache.solr.handler.admin.ShowFileRequestHandler" >
+ <lst name="invariants">
+ <str name="hidden">synonyms.txt</str>
+ <str name="hidden">anotherfile.txt</str>
+ </lst>
+ </requestHandler>
-->
<requestHandler name="/admin/"
class="org.apache.solr.handler.admin.AdminHandlers" />
Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?rev=608150&r1=608149&r2=608150&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java Wed Jan 2
09:15:30 2008
@@ -54,6 +54,7 @@
import org.apache.solr.request.JSONResponseWriter;
import org.apache.solr.request.PythonResponseWriter;
import org.apache.solr.request.QueryResponseWriter;
+import org.apache.solr.request.RawResponseWriter;
import org.apache.solr.request.RubyResponseWriter;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
@@ -968,7 +969,9 @@
if (responseWriters.get("ruby")==null) {
responseWriters.put("ruby", new RubyResponseWriter());
}
-
+ if (responseWriters.get("raw")==null) {
+ responseWriters.put("raw", new RawResponseWriter());
+ }
}
/** Finds a writer by name, or returns the default writer if not found. */
Modified:
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/AdminHandlers.java
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/admin/AdminHandlers.java?rev=608150&r1=608149&r2=608150&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/handler/admin/AdminHandlers.java
(original)
+++ lucene/solr/trunk/src/java/org/apache/solr/handler/admin/AdminHandlers.java
Wed Jan 2 09:15:30 2008
@@ -84,7 +84,8 @@
new StandardHandler( "system", new SystemInfoHandler() ),
new StandardHandler( "plugins", new PluginInfoHandler() ),
new StandardHandler( "threads", new ThreadDumpHandler() ),
- new StandardHandler( "properties", new PropertiesRequestHandler() )
+ new StandardHandler( "properties", new PropertiesRequestHandler() ),
+ new StandardHandler( "file", new ShowFileRequestHandler() )
};
for( StandardHandler handler : list ) {
Added:
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java?rev=608150&view=auto
==============================================================================
---
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
(added)
+++
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
Wed Jan 2 09:15:30 2008
@@ -0,0 +1,255 @@
+/**
+ * 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.admin;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.handler.RequestHandlerUtils;
+import org.apache.solr.request.RawResponseWriter;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrQueryResponse;
+
+/**
+ * This handler uses the RawResponseWriter to give client access to
+ * files inside ${solr.home}/conf
+ *
+ * If you want to selectively restrict access some configuration files, you
can list
+ * these files in the [EMAIL PROTECTED] #HIDDEN} invariants. For example to
hide
+ * synonyms.txt and anotherfile.txt, you would register:
+ *
+ * <pre>
+ * <requestHandler name="/admin/file"
class="org.apache.solr.handler.admin.ShowFileRequestHandler" >
+ * <lst name="defaults">
+ * <str name="echoParams">explicit</str>
+ * </lst>
+ * <lst name="invariants">
+ * <str name="hidden">synonyms.txt</str>
+ * <str name="hidden">anotherfile.txt</str>
+ * </lst>
+ * </requestHandler>
+ * </pre>
+ *
+ * The ShowFileRequestHandler uses the [EMAIL PROTECTED] RawResponseWriter}
(wt=raw) to return
+ * file contents. If you need to use a different writer, you will need to
change
+ * the registered invarient param for wt.
+ *
+ * If you want to override the contentType header returned for a given file,
you can
+ * set it directly using: [EMAIL PROTECTED] #USE_CONTENT_TYPE}. For example,
to get a plain text
+ * version of schema.xml, try:
+ * <pre>
+ *
http://localhost:8983/solr/admin/file?file=schema.xml&contentType=text/plain
+ * </pre>
+ *
+ * @version $Id$
+ * @since solr 1.3
+ */
+public class ShowFileRequestHandler extends RequestHandlerBase
+{
+ public static final String HIDDEN = "hidden";
+ public static final String USE_CONTENT_TYPE = "contentType";
+
+ protected Set<String> hiddenFiles;
+
+ private static ShowFileRequestHandler instance;
+ public ShowFileRequestHandler()
+ {
+ super();
+ instance = this; // used so that getFileContents can access hiddenFiles
+ }
+
+ @Override
+ public void init(NamedList args) {
+ super.init( args );
+
+ // by default, use wt=raw
+ ModifiableSolrParams params = new ModifiableSolrParams( invariants );
+ if( params.get( CommonParams.WT ) == null ) {
+ params.set( CommonParams.WT, "raw" );
+ }
+ this.invariants = params;
+
+ // Build a list of hidden files
+ hiddenFiles = new HashSet<String>();
+ if( invariants != null ) {
+ String[] hidden = invariants.getParams( HIDDEN );
+ if( hidden != null ) {
+ for( String s : hidden ) {
+ hiddenFiles.add( s.toUpperCase() );
+ }
+ }
+ }
+ }
+
+ @Override
+ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp)
throws IOException
+ {
+ File adminFile = null;
+
+ final SolrResourceLoader loader = req.getCore().getResourceLoader();
+ File configdir = new File( loader.getConfigDir() );
+ String fname = req.getParams().get("file", null);
+ if( fname == null ) {
+ adminFile = configdir;
+ }
+ else {
+ fname = fname.replace( '\\', '/' ); // normalize slashes
+ if( hiddenFiles.contains( fname.toUpperCase() ) ) {
+ throw new SolrException( ErrorCode.FORBIDDEN, "Can not access: "+fname
);
+ }
+ if( fname.indexOf( ".." ) >= 0 ) {
+ throw new SolrException( ErrorCode.FORBIDDEN, "Invalid path: "+fname
);
+ }
+ adminFile = new File( configdir, fname );
+ }
+
+ // Make sure the file exists, is readable and is not a hidden file
+ if( !adminFile.exists() ) {
+ throw new SolrException( ErrorCode.BAD_REQUEST, "Can not find:
"+adminFile.getName()
+ + " ["+adminFile.getAbsolutePath()+"]" );
+ }
+ if( !adminFile.canRead() || adminFile.isHidden() ) {
+ throw new SolrException( ErrorCode.BAD_REQUEST, "Can not show:
"+adminFile.getName()
+ + " ["+adminFile.getAbsolutePath()+"]" );
+ }
+
+ // Add a warning
+ RequestHandlerUtils.addExperimentalFormatWarning(rsp);
+
+ // Show a directory listing
+ if( adminFile.isDirectory() ) {
+
+ int basePath = configdir.getAbsolutePath().length() + 1;
+ NamedList<SimpleOrderedMap<Object>> files = new
SimpleOrderedMap<SimpleOrderedMap<Object>>();
+ for( File f : adminFile.listFiles() ) {
+ String path = f.getAbsolutePath().substring( basePath );
+ path = path.replace( '\\', '/' ); // normalize slashes
+ if( hiddenFiles.contains( path.toUpperCase() ) ) {
+ continue; // don't show 'hidden' files
+ }
+ if( f.isHidden() || f.getName().startsWith( "." ) ) {
+ continue; // skip hidden system files...
+ }
+
+ SimpleOrderedMap<Object> fileInfo = new SimpleOrderedMap<Object>();
+ files.add( path, fileInfo );
+ if( f.isDirectory() ) {
+ fileInfo.add( "directory", true );
+ }
+ else {
+ // TODO? content type
+ fileInfo.add( "size", f.length() );
+ }
+ fileInfo.add( "modified", new Date( f.lastModified() ) );
+ }
+ rsp.add( "files", files );
+ }
+ else {
+ // Check if they want the file as text
+ final String contentType = req.getParams().get( USE_CONTENT_TYPE );
+
+ final File file = adminFile;
+ //final URLConnection conn = adminFile.toURI().toURL().openConnection();
+
+ ContentStream stream = new ContentStream() {
+ public String getName() { return file.getName(); }
+ public Long getSize() { return file.length(); }
+ public String getSourceInfo() { return null; }
+
+ public String getContentType() {
+ if( contentType != null ) {
+ return contentType;
+ }
+ return null; //conn.getContentType();
+ }
+
+ public InputStream getStream() throws IOException {
+ return loader.openResource( file.getPath() );
//conn.getInputStream();
+ }
+
+ public Reader getReader() throws IOException {
+ return new FileReader( file );
+ }
+ };
+
+ rsp.add( RawResponseWriter.CONTENT, stream );
+ }
+ }
+
+ /**
+ * This is a utility function that lets you get the contents of an admin file
+ *
+ * It is only used so that we can get rid of "/admin/get-file.jsp" and
include
+ * "admin-extra.html" in "/admin/index.html" using jsp scriptlets
+ */
+ @Deprecated
+ public static String getFileContents( String path )
+ {
+ if( instance != null && instance.hiddenFiles != null ) {
+ if( instance.hiddenFiles.contains( path ) ) {
+ return ""; // ignore it...
+ }
+ }
+ try {
+ SolrCore core = SolrCore.getSolrCore();
+ InputStream input = core.getResourceLoader().openResource(path);
+ return IOUtils.toString( input );
+ }
+ catch( Exception ex ) {} // ignore it
+ return "";
+ }
+
+ //////////////////////// SolrInfoMBeans methods //////////////////////
+
+ @Override
+ public String getDescription() {
+ return "Admin Get File -- view config files directly";
+ }
+
+ @Override
+ public String getVersion() {
+ return "$Revision$";
+ }
+
+ @Override
+ public String getSourceId() {
+ return "$Id$";
+ }
+
+ @Override
+ public String getSource() {
+ return "$URL$";
+ }
+}
Propchange:
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added: lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java?rev=608150&view=auto
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java
(added)
+++ lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java
Wed Jan 2 09:15:30 2008
@@ -0,0 +1,91 @@
+/**
+ * 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.Writer;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * Writes a ContentStream directly to the output.
+ *
+ * <p>
+ * This writer is a special case that extends and alters the
+ * QueryResponseWriter contract. If SolrQueryResponse contains a
+ * ContentStream added with the key [EMAIL PROTECTED] #CONTENT}
+ * then this writer will output that stream exactly as is (with it's
+ * Content-Type). if no such ContentStream has been added, then a
+ * "base" QueryResponseWriter will be used to write the response
+ * according to the usual contract. The name of the "base" writer can
+ * be specified as an initialization param for this writer, or it
+ * defaults to the "standard" writer.
+ * </p>
+ *
+ * @version $Id$
+ * @since solr 1.3
+ */
+public class RawResponseWriter implements QueryResponseWriter
+{
+ /**
+ * The key that should be used to add a ContentStream to the
+ * SolrQueryResponse if you intend to use this Writer.
+ */
+ public static final String CONTENT = "content";
+ private String _baseWriter = null;
+
+ public void init(NamedList n) {
+ if( n != null ) {
+ Object base = n.get( "base" );
+ if( base != null ) {
+ _baseWriter = base.toString();
+ }
+ }
+ }
+
+ // Even if this is null, it should be ok
+ protected QueryResponseWriter getBaseWriter( SolrQueryRequest request )
+ {
+ return request.getCore().getQueryResponseWriter( _baseWriter );
+ }
+
+ public String getContentType(SolrQueryRequest request, SolrQueryResponse
response) {
+ Object obj = response.getValues().get( CONTENT );
+ if( obj != null && (obj instanceof ContentStream ) ) {
+ // copy the contents to the writer...
+ ContentStream content = (ContentStream)obj;
+ return content.getContentType();
+ }
+ return getBaseWriter( request ).getContentType( request, response );
+ }
+
+ public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse
response) throws IOException
+ {
+ Object obj = response.getValues().get( CONTENT );
+ if( obj != null && (obj instanceof ContentStream ) ) {
+ // copy the contents to the writer...
+ ContentStream content = (ContentStream)obj;
+ IOUtils.copy( content.getStream(), writer );
+ }
+ else {
+ getBaseWriter( request ).write( writer, request, response );
+ }
+ }
+}
Propchange:
lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
lucene/solr/trunk/src/java/org/apache/solr/request/RawResponseWriter.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: lucene/solr/trunk/src/webapp/resources/admin/get-file.jsp
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/resources/admin/get-file.jsp?rev=608150&r1=608149&r2=608150&view=diff
==============================================================================
--- lucene/solr/trunk/src/webapp/resources/admin/get-file.jsp (original)
+++ lucene/solr/trunk/src/webapp/resources/admin/get-file.jsp Wed Jan 2
09:15:30 2008
@@ -23,6 +23,13 @@
java.io.Reader,
java.util.StringTokenizer"%>
<%
+//
+// NOTE -- this file is Deprecated - should use the ShowFileRequestHandler
instead
+//
+
+System.out.println( "WARNING -- using deprecated jsp file: " +
request.getServletPath() );
+
+
Object ocore = request.getAttribute("org.apache.solr.SolrCore");
SolrCore core = ocore instanceof SolrCore? (SolrCore) ocore :
SolrCore.getSolrCore();
String fname = request.getParameter("file");
Modified: lucene/solr/trunk/src/webapp/resources/admin/index.jsp
URL:
http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/resources/admin/index.jsp?rev=608150&r1=608149&r2=608150&view=diff
==============================================================================
--- lucene/solr/trunk/src/webapp/resources/admin/index.jsp (original)
+++ lucene/solr/trunk/src/webapp/resources/admin/index.jsp Wed Jan 2 09:15:30
2008
@@ -34,8 +34,8 @@
<h3>Solr</h3>
</td>
<td>
- [<a href="get-file.jsp?file=<%=core.getSchemaFile()%>">Schema</a>]
- [<a href="get-file.jsp?file=<%=core.getConfigFile()%>">Config</a>]
+ [<a href="file/?file=<%=core.getSchemaFile()%>">Schema</a>]
+ [<a href="file/?file=<%=core.getConfigFile()%>">Config</a>]
[<a href="analysis.jsp?highlight=on">Analysis</a>]
<br>
[<a href="stats.jsp">Statistics</a>]
@@ -80,7 +80,10 @@
</tr>
-<jsp:include page="get-file.jsp?file=admin-extra.html&optional=y"
flush="true"/>
+<%
+ // a quick hack to get rid of get-file.jsp -- note this still spits out
invalid HTML
+ out.write(
org.apache.solr.handler.admin.ShowFileRequestHandler.getFileContents(
"admin-extra.html" ) );
+%>
</table><P>