Binary file WebContent/WEB-INF/lib/freemarker.jar has changed
Binary file WebContent/WEB-INF/lib/log4j-1.2.15.jar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WebContent/WEB-INF/log4j.properties Tue Mar 30 17:53:36 2010 +0200
@@ -0,0 +1,7 @@
+# This sets the global logging level and specifies the appenders
+log4j.rootLogger=INFO, consoleAppender
+
+# settings for the console appender
+log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender
+log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WebContent/WEB-INF/templates/info.ftl Tue Mar 30 17:53:36 2010 +0200
@@ -0,0 +1,32 @@
+<html>
+<head>
+ <title>Info on </title>
+</head>
+<body>
+ <h1>Informations</h1>
+ <table>
+ <thead>
+ <tr>
+ <th>Text</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tr>
+ <td>DATABASE PATH</td>
+ <td>${dbpath}</td>
+ </tr>
+ <tr>
+ <td>Segments</td>
+ <td>${segments_nb}</td>
+ </tr>
+ <tr>
+ <td>Segments in db</td>
+ <td>${segments_db_nb}</td>
+ </tr>
+ <tr>
+ <td>Tags</td>
+ <td>${tags_nb}</td>
+ </tr>
+ </table>
+</body>
+</html>
\ No newline at end of file
--- a/WebContent/WEB-INF/web.xml Wed Mar 24 12:41:26 2010 +0100
+++ b/WebContent/WEB-INF/web.xml Tue Mar 30 17:53:36 2010 +0200
@@ -15,8 +15,12 @@
fr.iri.thd.sonyengine.web.ServletContainer
</servlet-class>
<init-param>
- <param-name>initDatabasePath</param-name>
- <param-value>c:/tmp/db</param-value>
+ <param-name>com.sun.jersey.config.property.packages</param-name>
+ <param-value>fr.iri.thd.sonyengine.web</param-value>
+ </init-param>
+ <init-param>
+ <param-name>log4j-properties-location</param-name>
+ <param-value>/WEB-INF/log4j.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
@@ -24,4 +28,10 @@
<servlet-name>sonyengine</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <!--context-param>
+ <param-name>initDatabasePath</param-name>
+ <param-value>BAR</param-value>
+ </context-param-->
+ <!-- or in context.xml -->
+ <!--Parameter name="initDatabasePath" value="FOOBAR" /-->
</web-app>
\ No newline at end of file
--- a/src/HelloResource.java Wed Mar 24 12:41:26 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-
-@Path ("helloworld")
-public class HelloResource {
-
- @GET
- @Produces ("text/plain")
- public String sayHello() {
- return "Hello World";
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fr/iri/thd/sonyengine/web/FreemarkerViewProcessor.java Tue Mar 30 17:53:36 2010 +0200
@@ -0,0 +1,266 @@
+package fr.iri.thd.sonyengine.web;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.log4j.Logger;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.spi.template.ViewProcessor;
+
+import freemarker.cache.WebappTemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+
+/**
+* Match a Viewable-named view with a Freemarker template.
+*
+* <p>You can configure the location of your templates with the
+* context param 'freemarker.template.path'. If not assigned
+* we'll use a default of <tt>WEB-INF/templates</tt>. Note that this uses
+* Freemarker's {@link freemarker.cache.WebappTemplateLoader} to
+* load/cache the templates, so check its docs (or crank up the logging
+* under the 'freemarker.cache' package) if your templates
+* aren't getting loaded.</p>
+*
+* <p>This will put your Viewable's model object in the template
+* variable "it", unless the model is a Map. If so, the values
+* will be assigned to the template assuming the map is of
+* type <tt>Map<String,Object></tt>.</p>
+*
+* Example of configuring the template path:
+*
+* <pre>
+* <web-app ...
+* <display-name>Awesomeo 2000</display-name>
+* <context-param>
+* <param-name>freemarker.template.path</param-name>
+* <param-value>/WEB-INF/views</param-value>
+* </context-param>
+* ...
+*</pre>
+*
+* <p>You'll also need to tell Jersey the package where this provider
+* is stored. Typically this is through the servlet's init params -- for instance,
+* in the below configuration we could store this in <tt>com.myco.jersey</tt> and
+* my resources in <tt>com.myco.jersey.resource</tt></p>
+*
+* <pre>
+* <servlet>
+* <servlet-name>My REST App</servlet-name>
+* <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+* <init-param>
+* <param-name>com.sun.jersey.config.property.packages</param-name>
+* <param-value>com.myco.jersey;com.myco.jersey.resource</param-value>
+* </init-param>
+* </servlet>
+* </pre>
+*
+* <p>There are a number of methods you can override to change the behavior, such as
+* handling processing exceptions, changing the default template extension, or
+* adding variables to be assigned to every template context.
+*
+* @author Chris Winters <chris@cwinters.com>
+* @version $Revision: #5 $ (Last update: $DateTime: 2009/04/03 20:12:26 $ $Author: cwinters $)
+*/
+@Provider
+public class FreemarkerViewProcessor implements ViewProcessor<Template> {
+
+ private static final Logger log = Logger.getLogger( FreemarkerViewProcessor.class );
+
+ private static Configuration freemarkerConfig;
+
+ private String rootPath;
+ private ServletContext servletContext;
+
+ public FreemarkerViewProcessor() {
+ }
+
+ /**
+ * @return extension for templates, ".ftl" by default; if we don't see this at the
+ * end of your view we'll append it so we can find the template resource
+ */
+ protected String getDefaultExtension() {
+ return ".ftl";
+ }
+
+ /**
+ * Define additional variables to make available to the template.
+ * @param viewableVariables variables provided by whomever generated the viewable object;
+ * these are provided for reference only, there will be no effect if you modify this map
+ * @return new variables for the template context, which will override any defaults provided
+ */
+ protected Map<String,Object> getVariablesForTemplate(
+ final Map<String,Object> viewableVariables )
+ {
+ return new HashMap<String,Object>();
+ }
+
+ /**
+ * Catch any exception generated during template processing.
+ *
+ * @param t throwable caught
+ * @param templatePath path of template we're executing
+ * @param templateContext context use when evaluating this template
+ * @param out output stream from servlet container
+ * @throws IOException on any write errors, or if you want to rethrow
+ */
+ protected void onProcessException( final Throwable t, final Template template,
+ final Map<String,Object> templateContext,
+ final OutputStream out )
+ throws IOException
+ {
+ log.error( "Error processing freemarker template @ " + template.getName() + ": " + t.getMessage(), t );
+ out.write( "<pre>".getBytes() );
+ t.printStackTrace( new PrintStream( out ) );
+ out.write( "</pre>".getBytes() );
+ }
+
+ /**
+ * Modify freemarker configuration after we've created it and applied any
+ * settings from 'freemarker.properties' on the classpath.
+ *
+ * @param config configuration we've created so far
+ * @param context servlet context used to create the configuration
+ */
+ protected void assignFreemarkerConfig( final Configuration config,
+ final ServletContext context )
+ {
+ // don't always put a ',' in numbers (e.g., id=2000 vs id=2,000)
+ config.setNumberFormat( "0" );
+
+ // don't look for list.en.ftl when list.ftl requested
+ config.setLocalizedLookup( false );
+
+ // don't cache
+ config.setTemplateUpdateDelay(0);
+
+ log.info( "OK: Assigned default freemarker configuration" );
+
+ }
+
+ @Context
+ public void setServletContext( final ServletContext context )
+ {
+ this.servletContext = context;
+
+ freemarkerConfig = new Configuration();
+
+ rootPath = context.getInitParameter( "freemarker.template.path" );
+ if ( rootPath == null || rootPath.trim().length() == 0 ) {
+ log.info( "No 'freemarker.template.path' context-param, " +
+ "defaulting to '/WEB-INF/templates'" );
+ rootPath = "/WEB-INF/templates";
+ }
+ rootPath = rootPath.replaceAll( "/$", "" );
+
+ freemarkerConfig.setTemplateLoader( new WebappTemplateLoader( context, rootPath ) );
+
+ final InputStream fmProps = context.getResourceAsStream( "freemarker.properties" );
+ if ( fmProps != null ) {
+ try {
+ freemarkerConfig.setSettings( fmProps );
+ log.info( "OK: Assigned freemarker configuration from 'freemarker.properties'" );
+ return;
+ }
+ catch ( Throwable t ) {
+ log.warn( "Failed to load/assign freemarker.properties, will use default settings " +
+ "instead; error: " + t.getMessage() );
+ }
+ }
+ assignFreemarkerConfig( freemarkerConfig, context );
+ }
+
+ @Override
+ public Template resolve(String path) {
+
+ String resolvedPath = null;
+
+ if ( log.isDebugEnabled() )
+ log.debug( "Resolving freemarker template path (" + path + ")" );
+
+ // accept both '/path/to/template' and '/path/to/template.ftl'
+ final String defaultExtension = getDefaultExtension();
+ final String filePath = path.endsWith( defaultExtension ) ? path : path + defaultExtension;
+ try {
+ final String fullPath = rootPath + filePath;
+ final boolean templateFound = servletContext.getResource( fullPath ) != null;
+ if ( ! templateFound )
+ log.warn( "Template not found [Given path: " + path + "] " +
+ "[Servlet context path: " + fullPath + "]" );
+ resolvedPath = templateFound ? filePath : null;
+ }
+ catch ( MalformedURLException e ) {
+ log.warn( "Caught MalformedURLException when trying to get freemarker resource (" + filePath + ") " +
+ "from the servlet context: " + e.getMessage() );
+ resolvedPath = null;
+ }
+
+ if(resolvedPath != null) {
+ final Template template;
+ if ( log.isDebugEnabled() )
+ log.debug( "Evaluating freemarker template (" + resolvedPath + ")");
+ try {
+ template = freemarkerConfig.getTemplate( resolvedPath );
+ } catch (IOException e) {
+ log.warn( "Caught IOException when trying to get freemarker resource (" + filePath + ") " +
+ "from the servlet context: " + e.getMessage() );
+ return null;
+ }
+ if ( log.isDebugEnabled() )
+ log.debug( "OK: Resolved freemarker template" );
+ return template;
+
+ }
+ else
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void writeTo(final Template template, final Viewable viewable, final OutputStream out)
+ throws IOException {
+
+ out.flush(); // send status + headers
+
+ final Map<String,Object> vars = new HashMap<String, Object>();
+
+ final Object model = viewable.getModel();
+ if ( model instanceof Map<?, ?> ) {
+ vars.putAll( (Map<String, Object>) model );
+ }
+ else {
+ vars.put( "it", model );
+ }
+
+ final Map<String,Object> extraVars = getVariablesForTemplate( new HashMap<String, Object>( vars ) );
+ if ( extraVars != null ) {
+ vars.putAll( extraVars );
+ }
+
+ final OutputStreamWriter writer = new OutputStreamWriter( out );
+
+ try {
+ template.process( vars, writer );
+ if ( log.isDebugEnabled() )
+ log.debug( "OK: Processed freemarker template" );
+ }
+ catch ( Throwable t ) {
+ onProcessException( t, template, vars, out );
+ }
+
+ }
+
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fr/iri/thd/sonyengine/web/InfoResource.java Tue Mar 30 17:53:36 2010 +0200
@@ -0,0 +1,49 @@
+package fr.iri.thd.sonyengine.web;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+
+import thd.ThdEngine;
+
+import com.sun.jersey.api.view.Viewable;
+
+import fr.iri.thd.sonyengine.core.DataAccessor;
+import fr.iri.thd.sonyengine.core.DbEnv;
+
+@Path("info")
+public class InfoResource {
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable info(@Context ServletContext context) {
+ String dbpath = (String)context.getAttribute(ServletContainer.DB_PATH_ATTRIBUTE);
+
+ final int segments_nb = ThdEngine.getEngine().getAllMovieFragments().size();
+
+ final DbEnv dbenv = (DbEnv)context.getAttribute(ServletContainer.DB_ENV_ATTRIBUTE);
+ final DataAccessor da = new DataAccessor(dbenv.getEntityStore());
+ final long segments_db_nb = da.movieFragmentById.count();
+ final long tags_nb = da.tagById.count();
+
+
+ final Map<String,Object> vars = new HashMap<String, Object>();
+
+ vars.put("dbpath", dbpath);
+ vars.put("segments_nb", segments_nb);
+ vars.put("segments_db_nb", segments_db_nb);
+ vars.put("tags_nb", tags_nb);
+
+
+ Viewable view = new Viewable("/info", vars);
+
+ return view;
+ }
+
+}
--- a/src/fr/iri/thd/sonyengine/web/ServletContainer.java Wed Mar 24 12:41:26 2010 +0100
+++ b/src/fr/iri/thd/sonyengine/web/ServletContainer.java Tue Mar 30 17:53:36 2010 +0200
@@ -1,10 +1,17 @@
package fr.iri.thd.sonyengine.web;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.ws.rs.core.Application;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.PropertyConfigurator;
+
import thd.ThdEngine;
import com.sleepycat.persist.EntityCursor;
@@ -17,12 +24,15 @@
public class ServletContainer extends
com.sun.jersey.spi.container.servlet.ServletContainer {
+ public static final String INIT_DATABASE_PATH = "initDatabasePath";
+
/**
*
*/
private static final long serialVersionUID = -447765110849619632L;
public static final String DB_ENV_ATTRIBUTE = "DB_ENV";
+ public static final String DB_PATH_ATTRIBUTE = "DB_PATH";
public ServletContainer() {
}
@@ -37,24 +47,66 @@
public void init() throws ServletException {
+
+ String log4jLocation = this.getInitParameter("log4j-properties-location");
+ ServletContext sc = this.getServletContext();
+
+ if (log4jLocation == null) {
+ System.err.println("*** No log4j-properties-location init param, so initializing log4j with BasicConfigurator");
+ BasicConfigurator.configure();
+ }
+ else {
+
+ final Properties prop = new Properties();
+ final InputStream propStream = sc.getResourceAsStream(log4jLocation);
+ if (propStream != null) {
+ try {
+ prop.load(propStream);
+ } catch (IOException e) {
+ System.err.println("*** " + log4jLocation + " file not found, so initializing log4j with BasicConfigurator");
+ BasicConfigurator.configure();
+ }
+ finally {
+ try {
+ propStream.close();
+ }
+ catch (IOException e) {
+ // do nothing
+ }
+ }
+ System.out.println("Initializing log4j with: " + log4jLocation);
+ PropertyConfigurator.configure(prop);
+ }
+ else {
+ System.err.println("*** " + log4jLocation + " file not found, so initializing log4j with BasicConfigurator");
+ BasicConfigurator.configure();
+ }
+ }
+
super.init();
- String databasePath = this.getInitParameter("initDatabasePath");
+ String databasePath = this.getServletContext().getInitParameter(INIT_DATABASE_PATH);
- if(databasePath == null)
- return;
+ if(databasePath == null || databasePath.length() == 0)
+ throw new ServletException("Database path not found (null or empty)");
File databasePathFile = new File(databasePath);
- if(!databasePathFile.exists())
- {
+ try {
+ if(!databasePathFile.exists())
+ {
databasePathFile.mkdirs();
- }
+ }
+ }
+ catch(Exception e) {
+ throw new ServletException("Unable to create database path " + databasePath, e);
+ }
DbEnv env = new DbEnv();
env.setup(databasePathFile, false, true);
// set DbEnv in servlet context
- this.getServletContext().setAttribute(ServletContainer.DB_ENV_ATTRIBUTE, env);
+ sc.setAttribute(ServletContainer.DB_ENV_ATTRIBUTE, env);
+ sc.setAttribute(ServletContainer.DB_PATH_ATTRIBUTE, databasePath);
//load all entities
DataAccessor da = new DataAccessor(env.getEntityStore());