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>
+ * &lt;requestHandler name="/admin/file" 
class="org.apache.solr.handler.admin.ShowFileRequestHandler" &gt;
+ *   &lt;lst name="defaults"&gt;
+ *    &lt;str name="echoParams"&gt;explicit&lt;/str&gt;
+ *   &lt;/lst&gt;
+ *   &lt;lst name="invariants"&gt;
+ *    &lt;str name="hidden"&gt;synonyms.txt&lt;/str&gt; 
+ *    &lt;str name="hidden"&gt;anotherfile.txt&lt;/str&gt; 
+ *   &lt;/lst&gt;
+ * &lt;/requestHandler&gt;
+ * </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>
 


Reply via email to