Author: ssmiweve
Date: 2008-02-16 11:40:22 +0100 (Sat, 16 Feb 2008)
New Revision: 6123
Added:
branches/2.16/war/src/main/java/no/sesat/search/http/filters/SiteJspLoaderFilter.java
branches/2.16/war/src/main/webapp/META-INF/context.xml
Modified:
branches/2.16/generic.sesam/
branches/2.16/generic.sesam/pom.xml
branches/2.16/generic.sesam/war/src/webapp/WEB-INF/web.xml
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/AbstractResourceLoader.java
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/UrlResourceLoader.java
branches/2.16/skinresourcefeed/src/main/java/no/sesat/commons/resourcefeed/ResourceServlet.java
branches/2.16/war/src/main/webapp/WEB-INF/web.xml
Log:
SEARCH-4290 - Design and code with JSPs in skins
Property changes on: branches/2.16/generic.sesam
___________________________________________________________________
Name: svn:ignore
+ target
Modified: branches/2.16/generic.sesam/pom.xml
===================================================================
--- branches/2.16/generic.sesam/pom.xml 2008-02-16 08:34:44 UTC (rev 6122)
+++ branches/2.16/generic.sesam/pom.xml 2008-02-16 10:40:22 UTC (rev 6123)
@@ -73,6 +73,8 @@
<include>*.html</include>
<include>**/*.vm</include>
<include>**/*.html</include>
+ <include>*.jsp</include>
+ <include>**/*.jsp</include>
</includes>
</resource>
<resource>
Modified: branches/2.16/generic.sesam/war/src/webapp/WEB-INF/web.xml
===================================================================
--- branches/2.16/generic.sesam/war/src/webapp/WEB-INF/web.xml 2008-02-16
08:34:44 UTC (rev 6122)
+++ branches/2.16/generic.sesam/war/src/webapp/WEB-INF/web.xml 2008-02-16
10:40:22 UTC (rev 6123)
@@ -42,11 +42,11 @@
</init-param>
<init-param>
<param-name>resources.restricted</param-name>
- <param-value>properties,xml,vm,html,class,jar</param-value>
+ <param-value>properties,xml,vm,html,class,jar,jsp</param-value>
</init-param>
<init-param>
<param-name>content.paths</param-name>
-
<param-value>properties=conf,xml=conf,vm=templates,html=templates,css=css,js=javascript,jpg=images,gif=images,png=images,class=classes,jar=lib</param-value>
+
<param-value>properties=conf,xml=conf,vm=templates,html=templates,css=css,js=javascript,jpg=images,gif=images,png=images,class=classes,jar=lib,jsp=jsp</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
@@ -55,11 +55,6 @@
<servlet-name>resource servlet</servlet-name>
<url-pattern>/javascript/*</url-pattern>
</servlet-mapping>
-
- <welcome-file-list>
- <welcome-file>/images/logo.jpg</welcome-file>
- </welcome-file-list>
-
<servlet-mapping>
<servlet-name>resource servlet</servlet-name>
<url-pattern>/css/*</url-pattern>
@@ -74,6 +69,10 @@
</servlet-mapping>
<servlet-mapping>
<servlet-name>resource servlet</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>resource servlet</servlet-name>
<url-pattern>/templates/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
Modified:
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/AbstractResourceLoader.java
===================================================================
---
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/AbstractResourceLoader.java
2008-02-16 08:34:44 UTC (rev 6122)
+++
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/AbstractResourceLoader.java
2008-02-16 10:40:22 UTC (rev 6123)
@@ -209,8 +209,12 @@
if (resourceType == Resource.BYTECODE) {
// Convert package structure to path.
- this.resource = resource.replace(".", "/") + ".class";
-
+ if(!resource.endsWith(".jsp")){
+ this.resource = resource.replace(".", "/") + ".class";
+ }else{
+ this.resource = resource;
+ }
+
if (jarFileName != null) {
// Construct the path portion of a JarUrl.
this.resource = jarFileName + "!/" + this.resource;
Modified:
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/UrlResourceLoader.java
===================================================================
---
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/UrlResourceLoader.java
2008-02-16 08:34:44 UTC (rev 6122)
+++
branches/2.16/site-spi/src/main/java/no/sesat/search/site/config/UrlResourceLoader.java
2008-02-16 10:40:22 UTC (rev 6123)
@@ -202,6 +202,8 @@
return "lib/";
} else if (resource.endsWith(".class")) {
return "classes/";
+ } else if (resource.endsWith(".jsp")) {
+ return "jsp/";
} else {
return "conf/";
}
Modified:
branches/2.16/skinresourcefeed/src/main/java/no/sesat/commons/resourcefeed/ResourceServlet.java
===================================================================
---
branches/2.16/skinresourcefeed/src/main/java/no/sesat/commons/resourcefeed/ResourceServlet.java
2008-02-16 08:34:44 UTC (rev 6122)
+++
branches/2.16/skinresourcefeed/src/main/java/no/sesat/commons/resourcefeed/ResourceServlet.java
2008-02-16 10:40:22 UTC (rev 6123)
@@ -170,18 +170,31 @@
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)+/","/");
+ final String pathInfo;
+ final String directory;
+ if(null != request.getPathInfo()){
+ // simple scenerio where servlet-mapping was a prefix match.
+ pathInfo = request.getPathInfo();
+ directory = request.getServletPath();
+ }else{
+ // servlet-mapping was extension based
+ pathInfo =
request.getServletPath().substring(request.getServletPath().indexOf('/', 1));
+ directory = request.getServletPath().substring(0,
request.getServletPath().indexOf('/', 1));
+ }
+ LOG.debug("pathInfo: " + pathInfo + " ; directory: " + directory);
+ assert null != pathInfo : "Invalid resource " + pathInfo;
- assert null != configName : "Invalid resource " +
request.getPathInfo();
- assert 0 < configName.trim().length() : "Invalid resource " +
request.getPathInfo();
- assert 0 < configName.lastIndexOf('.') : "Invalid resource extension "
+ request.getPathInfo();
+ final String configName = pathInfo.replaceAll("/(\\d)+/","/");
+
+ assert 0 < configName.trim().length() : "Invalid resource " + pathInfo;
+ assert 0 < configName.lastIndexOf('.') : "Invalid resource extension "
+ pathInfo;
if (configName != null && configName.trim().length() > 0) {
final String extension =
configName.substring(configName.lastIndexOf('.') + 1).toLowerCase();
- assert null != extension : "Invalid resource extension" +
request.getPathInfo();
- assert 0 < extension.trim().length() : "Invalid resource extension
" + request.getPathInfo();
+ assert null != extension : "Invalid resource extension" + pathInfo;
+ assert 0 < extension.trim().length() : "Invalid resource extension
" + pathInfo;
final String ipAddr = null !=
request.getAttribute(REMOTE_ADDRESS_KEY)
? (String) request.getAttribute(REMOTE_ADDRESS_KEY)
@@ -191,7 +204,6 @@
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.
Added:
branches/2.16/war/src/main/java/no/sesat/search/http/filters/SiteJspLoaderFilter.java
===================================================================
---
branches/2.16/war/src/main/java/no/sesat/search/http/filters/SiteJspLoaderFilter.java
(rev 0)
+++
branches/2.16/war/src/main/java/no/sesat/search/http/filters/SiteJspLoaderFilter.java
2008-02-16 10:40:22 UTC (rev 6123)
@@ -0,0 +1,260 @@
+/* Copyright (2006-2007) Schibsted Søk AS
+ * This file is part of SESAT.
+ *
+ * SESAT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SESAT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with SESAT. If not, see <http://www.gnu.org/licenses/>.
+ */
+package no.sesat.search.http.filters;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.net.MalformedURLException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Arrays;
+import no.sesat.search.site.config.ResourceLoadException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import no.sesat.search.site.Site;
+import no.sesat.search.site.SiteContext;
+import no.sesat.search.site.config.BytecodeLoader;
+import no.sesat.search.site.config.UrlResourceLoader;
+import org.apache.log4j.Logger;
+
+
+/**
+ * Downloads JSP files from skins into sesat to be compiled and used locally.
+ * This makes it look like jsps from the other skin web applications actually
are bundled into sesat. <br/><br/>
+ *
+ * Implementation issue: <a
href="https://jira.sesam.no/jira/browse/SEARCH-4290">Design and code with JSPs
in skins</a>
+ *
+ * <br/><br/>
+ *
+ * <b>Inclusion of jsps</b> may occurr with <jsp:include page="..."/>
+ * or some other requestDispatcher.include(..) approach.
+ * <%@ include file=".."/%> will not work.
+ *
+ *
+ * <br/><br/>
+ *
+ * <b>To enable JSP files</b> in a particular skin to be downloaded into sesat
the following configuration is required:
+ * <ul>
+ * <li>in the skin's web.xml add "jsp" to the resources.restricted init-param
for ResourceServlet,</li>
+ * <li>in the skin's web.xml add "jsp=jsp" to the content.paths init-param for
ResourceServlet,</li>
+ * <li>in the skin's web.xml add the servlet-mapping:
+ * <pre>
+ <servlet-mapping>
+ <servlet-name>resource servlet</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ </servlet-mapping>
+ * </pre> so to avoid the skin's JspServlet and to serve the jsp files are
resources back to sesat,</li>
+ * <li>in the skin's pom.xml add to the
<pre><directory>src/main/templates</directory></pre>
+ * the following to ensure jsps and bundled into the war file:
+ * <pre>
+ <include>*.jsp</include>
+ <include>**/*.jsp</include>
+ * </pre></li>
+ * </ul>
+ * This have already been done in the base skin sesat-kernel/generic.sesam and
can be used as an example.<br/><br/>
+ *
+ * <b>Tomcat, or the container used, must not use unpackWARs="false", or any
non-file based deployment implementation,
+ * as this class must be able to write files into the deployed webapps
directory.</b> <br/>
+ * Such files are written using a FileChannel obtained like
+ * <pre>new RandomFileAccess(new File(root +
"requested-jsp-name"),"rw").getChannel()</pre>
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Mck</a>
+ * @version $Id$
+ */
+public final class SiteJspLoaderFilter implements Filter {
+
+
+ private static final Logger LOG =
Logger.getLogger(SiteJspLoaderFilter.class);
+
+ private FilterConfig config;
+ private String root;
+
+ /** [EMAIL PROTECTED] **/
+ public void init(final FilterConfig filterConfig) throws ServletException {
+
+ config = filterConfig;
+ root = config.getServletContext().getRealPath("/");
+ }
+
+ /** [EMAIL PROTECTED] **/
+ public void doFilter(
+ final ServletRequest request,
+ final ServletResponse response,
+ final FilterChain chain) throws IOException, ServletException {
+
+ if( request instanceof HttpServletRequest){
+
+ final String jsp = getRequestedJsp((HttpServletRequest)request);
+ LOG.debug("jsp: " + jsp + "; resource: " +
config.getServletContext().getResource(jsp));
+
+ downloadJsp((HttpServletRequest)request, jsp);
+
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ /** [EMAIL PROTECTED] **/
+ public void destroy() {
+ }
+
+ // copied from JspServlet.serve(..)
+ private String getRequestedJsp(
+ final HttpServletRequest request){
+
+ String jspUri = null;
+
+ String jspFile = (String) request.getAttribute(JSP_FILE);
+ if (jspFile != null) {
+ // JSP is specified via <jsp-file> in <servlet> declaration
+ jspUri = jspFile;
+ } else {
+ /*
+ * Check to see if the requested JSP has been the target of a
+ * RequestDispatcher.include()
+ */
+ jspUri = (String) request.getAttribute(INC_SERVLET_PATH);
+ if (jspUri != null) {
+ /*
+ * Requested JSP has been target of
+ * RequestDispatcher.include(). Its path is assembled from the
+ * relevant javax.servlet.include.* request attributes
+ */
+ String pathInfo = (String)
request.getAttribute("javax.servlet.include.path_info");
+ if (pathInfo != null) {
+ jspUri += pathInfo;
+ }
+ } else {
+ /*
+ * Requested JSP has not been the target of a
+ * RequestDispatcher.include(). Reconstruct its path from the
+ * request's getServletPath() and getPathInfo()
+ */
+ jspUri = request.getServletPath();
+ String pathInfo = request.getPathInfo();
+ if (pathInfo != null) {
+ jspUri += pathInfo;
+ }
+ }
+ }
+ return jspUri;
+ }
+
+ private void downloadJsp(
+ final HttpServletRequest request,
+ final String jsp) throws MalformedURLException{
+
+ byte[] golden = new byte[0];
+
+ // search skins for the jsp and write it out to "golden"
+ for(Site site = (Site) request.getAttribute(Site.NAME_KEY); 0 ==
golden.length; site = site.getParent()){
+
+ if(null == site){
+ if(null == config.getServletContext().getResource(jsp)){
+ throw new ResourceLoadException("Unable to find " + jsp +
" in any skin");
+ }
+ break;
+ }
+
+ final Site finalSite = site;
+ final BytecodeLoader bcLoader =
UrlResourceLoader.newBytecodeLoader(
+ new SiteContext(){
+ public Site getSite() {
+ return finalSite;
+ }
+ },
+ jsp,
+ null
+ );
+ bcLoader.abut();
+ golden = bcLoader.getBytecode();
+ }
+
+ // if golden now contains data save it to a local (ie local web
application) file
+ if(0 < golden.length){
+ try {
+ final File file = new File(root + jsp);
+
+ // create the directory structure
+ file.getParentFile().mkdirs();
+
+ // check existing file
+ boolean needsUpdating = true;
+ final boolean fileExisted = file.exists();
+ if(!fileExisted){
+ file.createNewFile();
+ }
+ final RandomAccessFile fileAccess = new RandomAccessFile(file,
"rw");
+ final FileChannel channel = fileAccess.getChannel();
+
+ try{
+ channel.lock();
+
+ if(fileExisted){
+
+ final byte[] bytes = new byte[(int)channel.size()];
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+ int reads; do{ reads = channel.read(byteBuffer);
}while(0 < reads);
+
+ needsUpdating = !Arrays.equals(golden, bytes);
+ }
+
+ if(needsUpdating){
+ // download file from skin
+ channel.write(ByteBuffer.wrap(golden), 0);
+ channel.force(true);
+ file.deleteOnExit();
+
+ }
+ }finally{
+ channel.close();
+ LOG.debug("resource created as " +
config.getServletContext().getResource(jsp));
+
+ }
+
+ }catch (IOException ex) {
+ LOG.error(ex.getMessage(), ex);
+ }
+ }
+ }
+
+ //// Imported from org.catalina.jasper.Constants
+
+ /**
+ * Request attribute for <code><jsp-file></code> element of a
+ * servlet definition. If present on a request, this overrides the
+ * value returned by <code>request.getServletPath()</code> to select
+ * the JSP page to be executed.
+ */
+ public static final String JSP_FILE =
+ System.getProperty("org.apache.jasper.Constants.JSP_FILE",
"org.apache.catalina.jsp_file");
+
+ /**
+ * Servlet context and request attributes that the JSP engine
+ * uses.
+ */
+ public static final String INC_SERVLET_PATH =
"javax.servlet.include.servlet_path";
+
+}
Property changes on:
branches/2.16/war/src/main/java/no/sesat/search/http/filters/SiteJspLoaderFilter.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: branches/2.16/war/src/main/webapp/META-INF/context.xml
===================================================================
--- branches/2.16/war/src/main/webapp/META-INF/context.xml
(rev 0)
+++ branches/2.16/war/src/main/webapp/META-INF/context.xml 2008-02-16
10:40:22 UTC (rev 6123)
@@ -0,0 +1,2 @@
+<!-- Since we dynamically add files into our deployment directory we must turn
caching off. See SiteJspLoaderFilter.java-->
+<Context cachingAllowed="false" />
\ No newline at end of file
Modified: branches/2.16/war/src/main/webapp/WEB-INF/web.xml
===================================================================
--- branches/2.16/war/src/main/webapp/WEB-INF/web.xml 2008-02-16 08:34:44 UTC
(rev 6122)
+++ branches/2.16/war/src/main/webapp/WEB-INF/web.xml 2008-02-16 10:40:22 UTC
(rev 6123)
@@ -76,6 +76,10 @@
</init-param>
</filter>
+ <filter>
+ <filter-name>SiteJspLoaderFilter</filter-name>
+
<filter-class>no.sesat.search.http.filters.SiteJspLoaderFilter</filter-class>
+ </filter>
<filter>
<filter-name>UserFilter</filter-name>
@@ -102,7 +106,6 @@
<filter-mapping>
<filter-name>DataModelFilter</filter-name>
<url-pattern>/*</url-pattern>
- <!--dispatcher>INCLUDE</dispatcher--> <!-- avoid requests to jsps -->
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
@@ -127,6 +130,11 @@
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
+ <filter-mapping>
+ <filter-name>SiteJspLoaderFilter</filter-name>
+ <url-pattern>*.jsp</url-pattern>
+ <dispatcher>INCLUDE</dispatcher>
+ </filter-mapping>
<!-- Servlets -->
@@ -142,17 +150,17 @@
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
- <servlet-name>jsp</servlet-name>
- <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>development</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
- <param-name>reloading</param-name>
- <param-value>false</param-value>
+ <!-- Because SiteJspLoaderFilter dynamically updates our jsp files
check very frequently for changes -->s
+ <param-name>checkInterval</param-name>
+ <param-value>5</param-value>
</init-param>
-
<load-on-startup>3</load-on-startup>
</servlet>
_______________________________________________
Kernel-commits mailing list
[email protected]
http://sesat.no/mailman/listinfo/kernel-commits