Author: ssmiweve
Date: 2007-06-17 13:27:33 +0200 (Sun, 17 Jun 2007)
New Revision: 5342

Added:
   trunk/skinresourcefeed/
   trunk/skinresourcefeed/LICENSE.txt
   trunk/skinresourcefeed/pom.xml
   trunk/skinresourcefeed/src/
   trunk/skinresourcefeed/src/main/
   trunk/skinresourcefeed/src/main/java/
   trunk/skinresourcefeed/src/main/java/no/
   trunk/skinresourcefeed/src/main/java/no/schibstedsok/
   trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/
   trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/resourcefeed/
   
trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/resourcefeed/ResourceServlet.java
Log:
commons-resourcefeed moved back into SESAT since it's only ever going to be 
used by sesat skins.
for history beyond this point look in its previous repository at 
https://dev.schibstedsok.no/svn/schibstedsok-commons/trunk/commons-resourcefeed/
 


Added: trunk/skinresourcefeed/LICENSE.txt
===================================================================
--- trunk/skinresourcefeed/LICENSE.txt                          (rev 0)
+++ trunk/skinresourcefeed/LICENSE.txt  2007-06-17 11:27:33 UTC (rev 5342)
@@ -0,0 +1 @@
+Copyright (2005-2006) Schibsted Søk AS
\ No newline at end of file

Added: trunk/skinresourcefeed/pom.xml
===================================================================
--- trunk/skinresourcefeed/pom.xml                              (rev 0)
+++ trunk/skinresourcefeed/pom.xml      2007-06-17 11:27:33 UTC (rev 5342)
@@ -0,0 +1,43 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+    <parent>
+      <groupId>schibstedsok</groupId>
+      <artifactId>search-portal</artifactId>
+      <version>2.14-SNAPSHOT</version>
+    </parent>
+    
+    <modelVersion>4.0.0</modelVersion>
+    <name>Skin Resource Feed</name>
+    <artifactId>skinresourcefeed</artifactId>
+    <packaging>jar</packaging>
+
+    <description>This is the project for SESAT's skins to serve resource 
documents.</description>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/conf</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>*.xml</include>
+                    <include>*.dtd</include>
+                    <include>**/*.xml</include>
+                    <include>**/*.dtd</include>
+                </includes>
+            </resource>
+        </resources>
+    </build>
+
+   
+    <dependencies>
+       <dependency>
+         <groupId>log4j</groupId>
+         <artifactId>log4j</artifactId>
+      </dependency>
+
+      <dependency>
+        <groupId>javax.servlet</groupId>
+        <artifactId>servlet-api</artifactId>
+      </dependency>
+  </dependencies>
+</project>


Property changes on: trunk/skinresourcefeed/pom.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: 
trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/resourcefeed/ResourceServlet.java
===================================================================
--- 
trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/resourcefeed/ResourceServlet.java
                              (rev 0)
+++ 
trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/resourcefeed/ResourceServlet.java
      2007-06-17 11:27:33 UTC (rev 5342)
@@ -0,0 +1,310 @@
+/* Copyright (2006-2007) Schibsted Søk AS
+ * ResourceServlet.java
+ *
+ * Created on 19 January 2006, 13:51
+ */
+
+package no.schibstedsok.commons.resourcefeed;
+
+
+import org.apache.log4j.Logger;
+
+import javax.servlet.ServletConfig;
+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.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/** Resource Provider.
+ * Serves configuration files (properties, xml), css, gifs, jpgs, javascript,
+ * classes, jar files and velocity templates for search-portal.
+ * Css, images, and javascript require direct access from client.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Michael Semb Wever</a>
+ * @version $Id$
+ */
+public final class ResourceServlet extends HttpServlet {
+
+    private static final Logger LOG = Logger.getLogger(ResourceServlet.class);
+
+    private static final String REMOTE_ADDRESS_KEY = "REMOTE_ADDR";
+    private static final String ERR_RESTRICTED_AREA = "<strong>Restricted 
Area!</strong>";
+    private static final String ERR_TRIED_TO_ACCESS = " tried to access 
Resource servlet!";
+    private static final String ERR_NOT_FOUND = "Failed to find resource ";
+    private static final String ERR_TRIED_TO_CROSS_REFERENCE = " tried to 
cross-reference resource!";
+
+    private static final String DEBUG_DEFAULT_MODIFCATION_TIMESTAMP = "Default 
modified timestamp set to ";
+    private static final String DEBUG_CLIENT_IP = "Client ipaddress ";
+
+    private static final Map<String,String> CONTENT_TYPES = new 
HashMap<String,String>();
+    private static final Map<String,String> CONTENT_PATHS = new 
HashMap<String,String>();
+    private static final Set<String> RESTRICTED = new HashSet<String>();
+
+    private long defaultLastModified = 0;
+    private String[] ipaddressesAllowed = new String[]{};
+
+    private ServletConfig servletConfig;
+
+    static {
+        // The different extension to content type mappings
+        // XXX is there an opensource library to do this?
+        CONTENT_TYPES.put("properties", "text/plain");
+        CONTENT_TYPES.put("xml", "text/xml");
+        CONTENT_TYPES.put("css", "text/css");
+        CONTENT_TYPES.put("js", "text/javascript");
+        CONTENT_TYPES.put("jpg", "image/jpeg");
+        CONTENT_TYPES.put("gif", "image/gif");
+        CONTENT_TYPES.put("png", "image/png");
+        CONTENT_TYPES.put("ico", "image/x-icon");
+        CONTENT_TYPES.put("vm", "text/plain");
+        CONTENT_TYPES.put("html", "text/plain");
+        CONTENT_TYPES.put("class", "application/java");
+        CONTENT_TYPES.put("jar", "application/java-archive");
+    }
+
+    /**
+     * [EMAIL PROTECTED]
+     */
+    @Override
+    public String getServletInfo() {
+
+        return "Servlet responsible for serving resources. Goes in hand with 
search-portal/site-spi";
+    }
+
+    /**
+     * [EMAIL PROTECTED]
+     */
+    @Override
+    public void init(final ServletConfig config) {
+
+        this.servletConfig = config;
+
+        defaultLastModified = System.currentTimeMillis();
+        LOG.info(DEBUG_DEFAULT_MODIFCATION_TIMESTAMP + defaultLastModified);
+
+        final String allowed = config.getInitParameter("ipaddresses.allowed");
+        LOG.info("allowing ipaddresses " + allowed);
+        if (null != allowed && allowed.length() >0) {
+            ipaddressesAllowed = allowed.split(",");
+        }
+
+        final String restricted = 
config.getInitParameter("resources.restricted");
+        LOG.info("restricted resources " + restricted);
+        if (null != restricted && restricted.length()>0) {
+            RESTRICTED.addAll(Arrays.asList(restricted.split(",")));
+        }
+
+        final String paths = config.getInitParameter("content.paths");
+        LOG.info("content path mappings " + paths);
+        if (null != paths && paths.length()>0) {
+            final String[] pathArr = paths.split(",");
+            for (String path : pathArr) {
+                final String[] pair = path.split("=");
+                CONTENT_PATHS.put(pair[0], pair[1]);
+            }
+        }
+    }
+
+    /**
+     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> 
methods.
+     * This servlet ignores URL parameters and POST content, as all the 
information is in the path,
+     * so it really doesn't matter if it is a GET or POST.
+     *
+     * Checks:
+     *  - resource exists,
+     *  - correct path is being used,
+     *  - configuration/template resources are only accessed by schibsted 
machines,
+     *
+     * The resource is served to the ServletOutputStream byte by byte from
+     *  getClass().getResourceAsStream(..)
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws javax.servlet.ServletException if ServletException occurs
+     * @throws java.io.IOException if IOException occurs
+     */
+    protected void processRequest(
+            final HttpServletRequest request,
+            final HttpServletResponse response)
+                throws ServletException, IOException {
+
+        request.setCharacterEncoding("UTF-8"); // correct encoding
+
+        // Get resource name. Also strip the version number out of the resource
+        final String configName = 
request.getPathInfo().replaceAll("/(\\d)+/","/");
+
+        if (configName != null && configName.trim().length() > 0) {
+
+
+            final String extension = 
configName.substring(configName.lastIndexOf('.') + 1).toLowerCase();
+            final String ipAddr = null != 
request.getAttribute(REMOTE_ADDRESS_KEY)
+                ? (String) request.getAttribute(REMOTE_ADDRESS_KEY)
+                : request.getRemoteAddr();
+
+            // Content-Type
+            response.setContentType(CONTENT_TYPES.get(extension) + 
";charset=UTF-8");
+
+            // Path check. Resource can only be loaded through correct path.
+            final String directory = request.getServletPath();
+            if (null != CONTENT_PATHS.get(extension) && 
directory.indexOf(CONTENT_PATHS.get(extension)) >= 0) {
+
+                // ok, check configuration resources are private.
+                LOG.trace(DEBUG_CLIENT_IP + ipAddr);
+
+                if (RESTRICTED.contains(extension) && !isIpAllowed(ipAddr)) {
+
+                    response.setContentType("text/html;charset=UTF-8");
+                    response.getOutputStream().print(ERR_RESTRICTED_AREA);
+                    LOG.warn(ipAddr + ERR_TRIED_TO_ACCESS);
+
+                }  else  {
+                    serveResource(configName, request, response);
+                }
+            }  else  {
+                // not allowed to cross-reference resources.
+                response.sendError(HttpServletResponse.SC_NOT_FOUND);
+                LOG.warn(ipAddr + ERR_TRIED_TO_CROSS_REFERENCE);
+            }
+        }
+    }
+
+    /**
+     * [EMAIL PROTECTED]
+     */
+    @Override
+    protected void doGet(
+            final HttpServletRequest request,
+            final HttpServletResponse response)
+                throws ServletException, IOException {
+
+        processRequest(request, response);
+    }
+
+    /**
+     * [EMAIL PROTECTED]
+     */
+    @Override
+    protected void doPost(
+            final HttpServletRequest request,
+            final HttpServletResponse response)
+                throws ServletException, IOException {
+
+        processRequest(request, response);
+    }
+
+    /** Assigned to the time when the servlet is initialised via the 
init(ServletConfig) method.
+     * Any redeployment of the skin results in an update in the last-modified 
response header.
+     * Editing the files "in-place" on disk will not have any effect on the 
last-modified header.
+     *
+     * @param req incoming HttpServletRequest request
+     * @return last-modified header (in milliseconds)
+     **/
+    @Override
+    protected long getLastModified(final HttpServletRequest req) {
+        return defaultLastModified;
+    }
+
+    private void serveResource(
+            final String configName,
+            final HttpServletRequest request,
+            final HttpServletResponse response)
+                throws ServletException, IOException {
+
+        InputStream is = null;
+
+        try  {
+            is = configName.endsWith(".jar")
+                    ? getJarStream(configName) : 
ResourceServlet.class.getResourceAsStream(configName);
+
+            if (is != null) {
+
+                // Write response headers before response data according to 
javadoc for HttpServlet.html#doGet(..)
+
+                // Allow this URL to be cached indefinitely.
+                //  Each jvm restart alters the number that appears in the URL 
being enough to ensure
+                //  nothing is cached across deployment versions.
+                response.setHeader("Cache-Control", "Public");
+                response.setDateHeader("Expires", Long.MAX_VALUE);
+
+                // Avoid writing out the response body if it's a HEAD request 
or a GET that the browser has cache for
+                boolean writeBody = !"HEAD".equals(request.getMethod());
+                writeBody &= request.getDateHeader("If-Modified-Since") <= 
defaultLastModified;
+
+                if (writeBody) {
+
+                    // Output the resource byte for byte
+                    final OutputStream os = response.getOutputStream();
+                    for (int b = is.read(); b >= 0; b = is.read()) {
+                         os.write(b);
+                    }
+
+                    // commit response now
+                    os.flush();
+                }
+
+            }  else  {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND);
+                LOG.info(ERR_NOT_FOUND + request.getPathInfo());
+            }
+
+        }  finally  {
+
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+
+    private InputStream getJarStream(final String resource) {
+        final Set paths = 
servletConfig.getServletContext().getResourcePaths("/WEB-INF/lib");
+
+        final String baseName = resource.replace(".jar", "").replace("/", "");
+
+        try {
+            for (final Iterator iterator = paths.iterator(); 
iterator.hasNext();) {
+
+                final String path = (String) iterator.next();
+
+                // Req. for jars can be done without the version suffix. A 
request for query-transform.jar might
+                // return the file query-transform-2.11-SNAPSHOT.jar.
+                if (path.contains(baseName)) {
+                    final URL url = 
servletConfig.getServletContext().getResource(path);
+                    return url.openConnection().getInputStream();
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns wether we allow the ipaddress or not.
+     * @param ipAddr the ipaddress to check.
+     *
+     * @return returns true if the ip address is trusted.
+     */
+   private boolean isIpAllowed(final String ipAddr) {
+
+        boolean allowed =
+                 ipAddr.startsWith("127.") || ipAddr.startsWith("10.") || 
ipAddr.startsWith("0:0:0:0:0:0:0:1%0");
+
+         for(String s : ipaddressesAllowed){
+             allowed |= ipAddr.startsWith(s);
+         }
+         return allowed;
+
+    }
+
+}


Property changes on: 
trunk/skinresourcefeed/src/main/java/no/schibstedsok/commons/resourcefeed/ResourceServlet.java
___________________________________________________________________
Name: svn:keywords
   + Id

_______________________________________________
Kernel-commits mailing list
[email protected]
http://sesat.no/mailman/listinfo/kernel-commits

Reply via email to