You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-commits@lucene.apache.org by ho...@apache.org on 2006/10/18 19:53:11 UTC

svn commit: r465317 - in /incubator/solr/trunk: ./ example/solr/conf/ example/solr/conf/xslt/ src/java/org/apache/solr/core/ src/java/org/apache/solr/request/ src/java/org/apache/solr/util/xslt/ src/test/org/apache/solr/ src/test/test-files/solr/ src/t...

Author: hossman
Date: Wed Oct 18 10:53:08 2006
New Revision: 465317

URL: http://svn.apache.org/viewvc?view=rev&rev=465317
Log:
SOLR-49 - new XSLTResponseWriter for server side XSLT processing, and a new QueryResponseWriter.init(NamedList) method

Added:
    incubator/solr/trunk/example/solr/conf/xslt/
    incubator/solr/trunk/example/solr/conf/xslt/example.xsl
    incubator/solr/trunk/src/java/org/apache/solr/request/XSLTResponseWriter.java   (with props)
    incubator/solr/trunk/src/java/org/apache/solr/util/xslt/
    incubator/solr/trunk/src/java/org/apache/solr/util/xslt/TransformerProvider.java   (with props)
    incubator/solr/trunk/src/test/test-files/solr/conf/xslt/
    incubator/solr/trunk/src/test/test-files/solr/conf/xslt/dummy.xsl
Modified:
    incubator/solr/trunk/CHANGES.txt
    incubator/solr/trunk/example/solr/conf/solrconfig.xml
    incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
    incubator/solr/trunk/src/java/org/apache/solr/request/JSONResponseWriter.java
    incubator/solr/trunk/src/java/org/apache/solr/request/PythonResponseWriter.java
    incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java
    incubator/solr/trunk/src/java/org/apache/solr/request/RubyResponseWriter.java
    incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java
    incubator/solr/trunk/src/test/org/apache/solr/OutputWriterTest.java
    incubator/solr/trunk/src/test/test-files/solr/crazy-path-to-config.xml

Modified: incubator/solr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/CHANGES.txt?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/CHANGES.txt (original)
+++ incubator/solr/trunk/CHANGES.txt Wed Oct 18 10:53:08 2006
@@ -55,7 +55,11 @@
     invariant params that can not overridden in the query. (hossman, SOLR-46)
 26. Default operator for query parsing can now be specified with q.op=AND|OR
     from the client request, overriding the schema value. (ehatcher)
-
+27. New XSLTResponseWriter does server side XSLT processing of XML Response.
+    In the process, an init(NamedList) method was added to QueryResponseWriter
+    which works the same way as SolrRequestHandler.
+    (Bertrand Delacretaz / SOLR-49 / hossman)
+    
 Changes in runtime behavior
  1. classes reorganized into different packages, package names changed to Apache
  2. force read of document stored fields in QuerySenderListener

Modified: incubator/solr/trunk/example/solr/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/example/solr/conf/solrconfig.xml?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/example/solr/conf/solrconfig.xml (original)
+++ incubator/solr/trunk/example/solr/conf/solrconfig.xml Wed Oct 18 10:53:08 2006
@@ -299,7 +299,16 @@
     <queryResponseWriter name="custom" class="com.example.MyResponseWriter"/>
   -->
 
-
+<!--
+    XSLT response writer (SOLR-49)
+    Changes to XSLT transforms are taken into account every xsltCacheLifetimeSeconds at most.
+   -->
+  <queryResponseWriter
+    name="xslt"
+    class="org.apache.solr.request.XSLTResponseWriter"
+   >
+     <int name="xsltCacheLifetimeSeconds">5</int>
+   </queryResponseWriter> 
     
   <!-- config for the admin interface --> 
   <admin>

Added: incubator/solr/trunk/example/solr/conf/xslt/example.xsl
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/example/solr/conf/xslt/example.xsl?view=auto&rev=465317
==============================================================================
--- incubator/solr/trunk/example/solr/conf/xslt/example.xsl (added)
+++ incubator/solr/trunk/example/solr/conf/xslt/example.xsl Wed Oct 18 10:53:08 2006
@@ -0,0 +1,78 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!-- 
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to HTML
+ -->
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+>
+
+  <xsl:output media-type="text/html"/>
+  
+  <xsl:variable name="title" select="concat('Solr search results (',response/result/@numFound,' documents)')"/>
+  
+  <xsl:template match='/'>
+    <html>
+      <head>
+        <title><xsl:value-of select="$title"/></title>
+        <xsl:call-template name="css"/>
+      </head>
+      <body>
+        <h1><xsl:value-of select="$title"/></h1>
+        <div class="note">
+          This has been formatted by the default query-to-html.xsl transform - use your own XSLT
+          to get a nicer page
+        </div>
+        <xsl:apply-templates select="response/result/doc"/>
+      </body>
+    </html>
+  </xsl:template>
+  
+  <xsl:template match="doc">
+    <div class="doc">
+      <table width="100%">
+        <xsl:apply-templates/>
+      </table>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="doc/*">
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <xsl:value-of select="."/>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="*"/>
+  
+  <xsl:template name="css">
+    <style type="text/css">
+      body { font-family: "Lucida Grande", sans-serif }
+      .doc { margin-top: 1em; border-top: solid grey 1px; }
+      td.name { font-style: italic; font-size:80%; }
+      td { vertical-align: top; }
+      .note { font-size:80%; }
+    </style>
+  </xsl:template>
+
+</xsl:stylesheet>

Modified: incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java (original)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java Wed Oct 18 10:53:08 2006
@@ -966,6 +966,7 @@
         log.info("adding queryResponseWriter "+name+"="+className);
           
         QueryResponseWriter writer = (QueryResponseWriter) Config.newInstance(className);
+        writer.init(DOMUtil.childNodesToNamedList(elm));
         responseWriters.put(name, writer);
       } catch (Exception ex) {
         SolrException.logOnce(log,null, ex);

Modified: incubator/solr/trunk/src/java/org/apache/solr/request/JSONResponseWriter.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/JSONResponseWriter.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/JSONResponseWriter.java (original)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/JSONResponseWriter.java Wed Oct 18 10:53:08 2006
@@ -20,6 +20,8 @@
 public class JSONResponseWriter implements QueryResponseWriter {
   static String CONTENT_TYPE_JSON_UTF8="text/x-json; charset=UTF-8";
 
+  public void init(NamedList n) {
+  }
 
   public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
     JSONWriter w = new JSONWriter(writer, req, rsp);
@@ -716,4 +718,4 @@
     }
     writer.write('\'');
   }
-}
\ No newline at end of file
+}

Modified: incubator/solr/trunk/src/java/org/apache/solr/request/PythonResponseWriter.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/PythonResponseWriter.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/PythonResponseWriter.java (original)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/PythonResponseWriter.java Wed Oct 18 10:53:08 2006
@@ -3,9 +3,15 @@
 import java.io.Writer;
 import java.io.IOException;
 
+import org.apache.solr.util.NamedList;
+
 public class PythonResponseWriter implements QueryResponseWriter {
   static String CONTENT_TYPE_PYTHON_ASCII="text/x-python;charset=US-ASCII";
 
+  public void init(NamedList n) {
+    /* NOOP */
+  }
+  
   public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
     PythonWriter w = new PythonWriter(writer, req, rsp);
     w.writeResponse();

Modified: incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java (original)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java Wed Oct 18 10:53:08 2006
@@ -19,6 +19,8 @@
 import java.io.Writer;
 import java.io.IOException;
 
+import org.apache.solr.util.NamedList;
+
 /**
  * Implementations of <code>QueryResponseWriter</code> are used to format responses to query requests.
  *
@@ -70,5 +72,12 @@
    * @return a Content-Type string, which may not be null.
    */
   public String getContentType(SolrQueryRequest request, SolrQueryResponse response);
+  
+  /** <code>init</code> will be called just once, immediately after creation.
+   * <p>The args are user-level initialization parameters that
+   * may be specified when declaring a response writer in
+   * solrconfig.xml
+   */
+  public void init(NamedList args);
 }
 

Modified: incubator/solr/trunk/src/java/org/apache/solr/request/RubyResponseWriter.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/RubyResponseWriter.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/RubyResponseWriter.java (original)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/RubyResponseWriter.java Wed Oct 18 10:53:08 2006
@@ -3,10 +3,16 @@
 import java.io.Writer;
 import java.io.IOException;
 
+import org.apache.solr.util.NamedList;
+
 public class RubyResponseWriter implements QueryResponseWriter {
   static String CONTENT_TYPE_RUBY_UTF8="text/x-ruby;charset=UTF-8";
 
-  public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
+  public void init(NamedList n) {
+    /* NOOP */
+  }
+  
+ public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
     RubyWriter w = new RubyWriter(writer, req, rsp);
     w.writeResponse();
   }

Modified: incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java (original)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java Wed Oct 18 10:53:08 2006
@@ -19,12 +19,19 @@
 import java.io.Writer;
 import java.io.IOException;
 
+import org.apache.solr.util.NamedList;
+
 /**
  * @author yonik
  * @version $Id$
  */
 
 public class XMLResponseWriter implements QueryResponseWriter {
+  public void init(NamedList n) {
+    /* NOOP */
+  }
+
+  
   public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
     XMLWriter.writeResponse(writer,req,rsp);
   }

Added: incubator/solr/trunk/src/java/org/apache/solr/request/XSLTResponseWriter.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/XSLTResponseWriter.java?view=auto&rev=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/XSLTResponseWriter.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/XSLTResponseWriter.java Wed Oct 18 10:53:08 2006
@@ -0,0 +1,119 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.BufferedReader;
+import java.io.CharArrayReader;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.solr.core.SolrConfig;
+import org.apache.solr.util.NamedList;
+import org.apache.solr.util.xslt.TransformerProvider;
+
+/** QueryResponseWriter which captures the output of the XMLWriter
+ *  (in memory for now, not optimal performancewise), and applies an XSLT transform
+ *  to it.
+ */
+public class XSLTResponseWriter implements QueryResponseWriter {
+
+  public static final String DEFAULT_CONTENT_TYPE = "text/xml";
+  public static final String TRANSFORM_PARAM = "tr";
+  public static final String CONTEXT_TRANSFORMER_KEY = "xsltwriter.transformer";
+  
+  private Integer xsltCacheLifetimeSeconds = null; 
+  public static final int XSLT_CACHE_DEFAULT = 60;
+  private static final String XSLT_CACHE_PARAM = "xsltCacheLifetimeSeconds"; 
+
+  private static final Logger log = Logger.getLogger(XSLTResponseWriter.class.getName());
+  
+  public void init(NamedList n) {
+      final SolrParams p = SolrParams.toSolrParams(n);
+      xsltCacheLifetimeSeconds = p.getInt(XSLT_CACHE_PARAM,XSLT_CACHE_DEFAULT);
+      log.info("xsltCacheLifetimeSeconds=" + xsltCacheLifetimeSeconds);
+  }
+
+  
+  public String getContentType(SolrQueryRequest request, SolrQueryResponse response) {
+    Transformer t = null;
+    try {
+      t = getTransformer(request);
+    } catch(Exception e) {
+      // TODO should our parent interface throw (IO)Exception?
+      throw new RuntimeException("getTransformer fails in getContentType",e);
+    }
+    
+    final String mediaTypeFromXslt = t.getOutputProperty("media-type");
+    if(mediaTypeFromXslt == null || mediaTypeFromXslt.length()==0) {
+      // This did not happen in my tests, mediaTypeFromXslt is set to "text/xml"
+      // if the XSLT transform does not contain an xsl:output element. Not sure
+      // if this is standard behavior or if it's just my JVM/libraries
+      return DEFAULT_CONTENT_TYPE;
+    }
+    return mediaTypeFromXslt;
+  }
+
+  public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {
+    final Transformer t = getTransformer(request);
+    
+    // capture the output of the XMLWriter
+    final CharArrayWriter w = new CharArrayWriter();
+    XMLWriter.writeResponse(w,request,response);
+    
+    // and write transformed result to our writer
+    final Reader r = new BufferedReader(new CharArrayReader(w.toCharArray()));
+    final StreamSource source = new StreamSource(r);
+    final StreamResult result = new StreamResult(writer);
+    try {
+      t.transform(source, result);
+    } catch(TransformerException te) {
+      final IOException ioe = new IOException("XSLT transformation error");
+      ioe.initCause(te);
+      throw ioe;
+    }
+  }
+  
+  /** Get Transformer from request context, or from TransformerProvider.
+   *  This allows either getContentType(...) or write(...) to instantiate the Transformer,
+   *  depending on which one is called first, then the other one reuses the same Transformer
+   */
+  protected Transformer getTransformer(SolrQueryRequest request) throws IOException {
+    final String xslt = request.getParams().get(TRANSFORM_PARAM,null);
+    if(xslt==null) {
+      throw new IOException("'" + TRANSFORM_PARAM + "' request parameter is required to use the XSLTResponseWriter");
+    }
+    
+    // no need to synchronize access to context, right? 
+    // Nothing else happens with it at the same time
+    final Map<Object,Object> ctx = request.getContext();
+    Transformer result = (Transformer)ctx.get(CONTEXT_TRANSFORMER_KEY);
+    if(result==null) {
+      result = TransformerProvider.instance.getTransformer(xslt,xsltCacheLifetimeSeconds.intValue());
+      ctx.put(CONTEXT_TRANSFORMER_KEY,result);
+    }
+    return result;
+  }
+}

Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/XSLTResponseWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/solr/trunk/src/java/org/apache/solr/util/xslt/TransformerProvider.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/util/xslt/TransformerProvider.java?view=auto&rev=465317
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/util/xslt/TransformerProvider.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/util/xslt/TransformerProvider.java Wed Oct 18 10:53:08 2006
@@ -0,0 +1,118 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.util.xslt;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletException;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.solr.core.Config;
+import org.apache.solr.core.SolrConfig;
+import org.apache.solr.request.XSLTResponseWriter;
+
+/** Singleton that creates a Transformer for the XSLTServletFilter.
+ *  For now, only caches the last created Transformer, but
+ *  could evolve to use an LRU cache of Transformers.
+ *  
+ *  See http://www.javaworld.com/javaworld/jw-05-2003/jw-0502-xsl_p.html for
+ *  one possible way of improving caching. 
+ */
+
+public class TransformerProvider {
+  public static TransformerProvider instance = new TransformerProvider();
+
+  private final TransformerFactory tFactory = TransformerFactory.newInstance();
+  private String lastFilename;
+  private Templates lastTemplates = null;
+  private long cacheExpires = 0;
+  
+  private static Logger log;
+  
+  /** singleton */
+  private TransformerProvider() {
+    log = Logger.getLogger(TransformerProvider.class.getName());
+    
+    // tell'em: currently, we only cache the last used XSLT transform, and blindly recompile it
+    // once cacheLifetimeSeconds expires
+    log.warning(
+        "The TransformerProvider's simplistic XSLT caching mechanism is not appropriate "
+        + "for high load scenarios, unless a single XSLT transform is used"
+        + " and xsltCacheLifetimeSeconds is set to a sufficiently high value."
+    );
+  }
+  
+  /** Return a new Transformer, possibly created from our cached Templates object  
+   * @throws TransformerConfigurationException 
+   */ 
+  public synchronized Transformer getTransformer(String filename,int cacheLifetimeSeconds) throws IOException {
+    // For now, the Templates are blindly reloaded once cacheExpires is over.
+    // It'd be better to check the file modification time to reload only if needed.
+    if(lastTemplates!=null && filename.equals(lastFilename) && System.currentTimeMillis() < cacheExpires) {
+      if(log.isLoggable(Level.FINE)) {
+        log.fine("Using cached Templates:" + filename);
+      }
+    } else {
+      lastTemplates = getTemplates(filename,cacheLifetimeSeconds);
+    }
+    
+    Transformer result = null;
+    
+    try {
+      result = lastTemplates.newTransformer();
+    } catch(TransformerConfigurationException tce) {
+      log.throwing(getClass().getName(), "getTransformer", tce);
+      final IOException ioe = new IOException("newTransformer fails ( " + lastFilename + ")");
+      ioe.initCause(tce);
+      throw ioe;
+    }
+    
+    return result;
+  }
+  
+  /** Return a Templates object for the given filename */
+  private Templates getTemplates(String filename,int cacheLifetimeSeconds) throws IOException {
+    
+    Templates result = null;
+    lastFilename = null;
+    try {
+      if(log.isLoggable(Level.FINE)) {
+        log.fine("compiling XSLT templates:" + filename);
+      }
+      final InputStream xsltStream = Config.openResource("xslt/" + filename);
+      result = tFactory.newTemplates(new StreamSource(xsltStream));
+    } catch (Exception e) {
+      log.throwing(getClass().getName(), "newTemplates", e);
+      final IOException ioe = new IOException("Unable to initialize Templates '" + filename + "'");
+      ioe.initCause(e);
+      throw ioe;
+    }
+    
+    lastFilename = filename;
+    lastTemplates = result;
+    cacheExpires = System.currentTimeMillis() + (cacheLifetimeSeconds * 1000);
+    
+    return result;
+  }
+}

Propchange: incubator/solr/trunk/src/java/org/apache/solr/util/xslt/TransformerProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/solr/trunk/src/test/org/apache/solr/OutputWriterTest.java
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/test/org/apache/solr/OutputWriterTest.java?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/test/org/apache/solr/OutputWriterTest.java (original)
+++ incubator/solr/trunk/src/test/org/apache/solr/OutputWriterTest.java Wed Oct 18 10:53:08 2006
@@ -22,6 +22,7 @@
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrQueryResponse;
 import org.apache.solr.util.AbstractSolrTestCase;
+import org.apache.solr.util.NamedList;
 import org.apache.solr.util.TestHarness;
 
 /** Tests the ability to configure multiple query output writers, and select those
@@ -34,7 +35,6 @@
     /** The XML string that's output for testing purposes. */
     public static final String USELESS_OUTPUT = "useless output";
     
-    
     public String getSchemaFile() { return "solr/crazy-path-to-schema.xml"; }
     
     public String getSolrConfigFile() { return "solr/crazy-path-to-config.xml"; }
@@ -54,6 +54,14 @@
         assertEquals(USELESS_OUTPUT, out);
     }
     
+    public void testTrivialXsltWriter() throws Exception {
+        lrf.args.put("wt", "xslt");
+        lrf.args.put("tr", "dummy.xsl");
+        String out = h.query(req("foo"));
+        System.out.println(out);
+        assertTrue(out.contains("DUMMY"));
+    }
+    
     
     ////////////////////////////////////////////////////////////////////////////
     /** An output writer that doesn't do anything useful. */
@@ -62,11 +70,10 @@
         
         public UselessOutputWriter() {}
 
-
+        public void init(NamedList n) {}
         
         public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response)
         throws IOException {
-            
             writer.write(USELESS_OUTPUT);
         }
 

Added: incubator/solr/trunk/src/test/test-files/solr/conf/xslt/dummy.xsl
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/test/test-files/solr/conf/xslt/dummy.xsl?view=auto&rev=465317
==============================================================================
--- incubator/solr/trunk/src/test/test-files/solr/conf/xslt/dummy.xsl (added)
+++ incubator/solr/trunk/src/test/test-files/solr/conf/xslt/dummy.xsl Wed Oct 18 10:53:08 2006
@@ -0,0 +1,38 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!-- 
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ -->
+
+<!-- 
+
+
+Simple Dummy transform to demonstrate XSLTResponseWriter
+
+
+ -->
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+>
+
+  <xsl:output media-type="text/plain"/>
+  
+  <xsl:variable name="dumb" select="concat('DUM','MY')"/>
+  
+  <xsl:template match='/'>
+    <xsl:value-of select="$dumb"/>
+  </xsl:template>
+
+</xsl:stylesheet>

Modified: incubator/solr/trunk/src/test/test-files/solr/crazy-path-to-config.xml
URL: http://svn.apache.org/viewvc/incubator/solr/trunk/src/test/test-files/solr/crazy-path-to-config.xml?view=diff&rev=465317&r1=465316&r2=465317
==============================================================================
--- incubator/solr/trunk/src/test/test-files/solr/crazy-path-to-config.xml (original)
+++ incubator/solr/trunk/src/test/test-files/solr/crazy-path-to-config.xml Wed Oct 18 10:53:08 2006
@@ -46,6 +46,7 @@
   
   <queryResponseWriter name="standard" class="org.apache.solr.request.XMLResponseWriter"/>
   <queryResponseWriter name="useless" class="org.apache.solr.OutputWriterTest$UselessOutputWriter"/>
+  <queryResponseWriter name="xslt" class="org.apache.solr.request.XSLTResponseWriter"/>
 
 
   <admin>