click-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From med...@apache.org
Subject svn commit: r791369 - in /incubator/click/trunk/click: examples/webapp/WEB-INF/ framework/src/org/apache/click/ framework/src/org/apache/click/service/
Date Mon, 06 Jul 2009 04:09:23 GMT
Author: medgar
Date: Mon Jul  6 04:09:23 2009
New Revision: 791369

URL: http://svn.apache.org/viewvc?rev=791369&view=rev
Log:
CLK-564

Added:
    incubator/click/trunk/click/framework/src/org/apache/click/service/ClickResourceService.java
    incubator/click/trunk/click/framework/src/org/apache/click/service/ResourceService.java
Modified:
    incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml
    incubator/click/trunk/click/framework/src/org/apache/click/ClickServlet.java
    incubator/click/trunk/click/framework/src/org/apache/click/service/ConfigService.java
    incubator/click/trunk/click/framework/src/org/apache/click/service/XmlConfigService.java

Modified: incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml?rev=791369&r1=791368&r2=791369&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml (original)
+++ incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml Mon Jul  6 04:09:23 2009
@@ -151,6 +151,11 @@
 		<servlet-name>ClickServlet</servlet-name>
 		<url-pattern>*.htm</url-pattern>
 	</servlet-mapping>
+
+	<servlet-mapping>
+		<servlet-name>ClickServlet</servlet-name>
+		<url-pattern>/click/*</url-pattern>
+	</servlet-mapping>
 	
 	<!-- Wecome Files -->
 

Modified: incubator/click/trunk/click/framework/src/org/apache/click/ClickServlet.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/ClickServlet.java?rev=791369&r1=791368&r2=791369&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/ClickServlet.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/ClickServlet.java Mon Jul 
6 04:09:23 2009
@@ -19,6 +19,7 @@
 package org.apache.click;
 
 import java.io.IOException;
+import java.io.OutputStream;
 import java.io.Writer;
 import java.lang.reflect.Field;
 import java.util.Date;
@@ -43,6 +44,7 @@
 
 import org.apache.click.service.ConfigService;
 import org.apache.click.service.LogService;
+import org.apache.click.service.ResourceService;
 import org.apache.click.service.XmlConfigService;
 import org.apache.click.service.ConfigService.AutoBinding;
 import org.apache.click.util.ClickUtils;
@@ -102,8 +104,6 @@
  * A single application {@link ConfigService} instance is created by the ClickServlet at
  * startup. Once the ConfigService has been initialized it is stored in the
  * ServletContext using the key "<tt>org.apache.click.service.ConfigService</tt>".
- *
- * @author Malcolm Edgar
  */
 public class ClickServlet extends HttpServlet {
 
@@ -286,9 +286,16 @@
      * @param request the servlet request to process
      * @param response the servlet response to render the results to
      * @param isPost determines whether the request is a POST
+     * @throws IOException if resource request could not be served
      */
     protected void handleRequest(HttpServletRequest request,
-        HttpServletResponse response, boolean isPost) {
+        HttpServletResponse response, boolean isPost) throws IOException {
+
+        // Handle requests for static click resources
+        if (isResourceRequest(request)) {
+            handleResourceRequest(request, response);
+            return;
+        }
 
         long startTime = System.currentTimeMillis();
 
@@ -304,6 +311,7 @@
             logger.debug(buffer);
         }
 
+        // Handle click page requests
         Page page = null;
         try {
 
@@ -386,6 +394,26 @@
     }
 
     /**
+     * Return true if the request is for a static click resource
+     *
+     * @param request the servlet request
+     * @return true if the request is for a static click resource
+     */
+    protected boolean isResourceRequest(HttpServletRequest request) {
+        String resourcePath = ClickUtils.getResourcePath(request);
+        if (resourcePath.startsWith("/click/")) {
+
+            // If not a click page and not JSP and not a directory
+            return !resourcePath.endsWith(".htm")
+                && !resourcePath.endsWith(".jsp")
+                && !resourcePath.endsWith("/");
+
+        } else {
+            return false;
+        }
+    }
+
+    /**
      * Provides the application exception handler. The application exception
      * will be delegated to the configured error page. The default error page is
      * {@link ErrorPage} and the page template is "click/error.htm" <p/>
@@ -481,6 +509,46 @@
     }
 
     /**
+     * Handle the given static /click/ resource servlet request and render the
+     * results to the servlet response.
+     *
+     * @param request the servlet request
+     * @param response the servlet response to render the results to
+     * @throws IOException if the response data could not be rendered
+     */
+    protected void handleResourceRequest(HttpServletRequest request,
+            HttpServletResponse response) throws IOException {
+
+        String resourcePath = ClickUtils.getResourcePath(request);
+
+        ResourceService resourceService = getConfigService().getResourceService();
+
+        byte[] resourceData = resourceService.getResourceData(resourcePath);
+
+        if (resourceData != null) {
+            String mimeType = ClickUtils.getMimeType(resourcePath);
+
+            OutputStream outputStream = null;
+            try {
+                if (mimeType != null) {
+                    response.setContentType(mimeType);
+                }
+                response.setContentLength(resourceData.length);
+
+                outputStream = response.getOutputStream();
+                outputStream.write(resourceData);
+                outputStream.flush();
+
+            } finally {
+                ClickUtils.close(outputStream);
+            }
+
+        } else {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+        }
+    }
+
+    /**
      * Process the given page invoking its "on" event callback methods
      * and directing the response.
      * <p/>

Added: incubator/click/trunk/click/framework/src/org/apache/click/service/ClickResourceService.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/service/ClickResourceService.java?rev=791369&view=auto
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/service/ClickResourceService.java
(added)
+++ incubator/click/trunk/click/framework/src/org/apache/click/service/ClickResourceService.java
Mon Jul  6 04:09:23 2009
@@ -0,0 +1,285 @@
+/*
+ * 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.click.service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import javax.servlet.ServletContext;
+
+import org.apache.click.util.ClickUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.TrueFileFilter;
+
+/**
+ * Provides a default Click static resource service class.
+ * <p/>
+ * TODO
+ */
+public class ClickResourceService implements ResourceService {
+
+    /** The click resources cache. */
+    protected Map<String, byte[]> resourceCache = new HashMap<String, byte[]>();
+
+    /** The application log service. */
+    protected LogService logService;
+
+    /**
+     * @see ResourceService#onInit(ServletContext)
+     *
+     * @param servletContext the application servlet context
+     * @throws IOException if an IO error occurs initializing the service
+     */
+    public void onInit(ServletContext servletContext) throws IOException {
+
+        ConfigService configService = ClickUtils.getConfigService(servletContext);
+        logService = configService.getLogService();
+
+        // Load all JAR resources
+        loadAllJarResources();
+
+        // Load all file system resources
+        loadClickDirResources(servletContext);
+    }
+
+    /**
+     * @see ResourceService#onDestroy()
+     */
+    public void onDestroy() {
+        resourceCache.clear();
+    }
+
+    /**
+     * @see ResourceService#getResourceData(String)
+     *
+     * @param resourcePath the path of the resource to lookup
+     * @return the resource data byte array if found or null otherwise
+     */
+    public byte[] getResourceData(String resourcePath) {
+        return resourceCache.get(resourcePath);
+    }
+
+    // Private Methods --------------------------------------------------------
+
+    private void loadAllJarResources() throws IOException {
+
+        // Find all jars under WEB-INF/lib and deploy all resources from these jars
+        long startTime = System.currentTimeMillis();
+
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+        Enumeration<URL> en = classLoader.getResources("META-INF/web");
+        while (en.hasMoreElements()) {
+            URL url = en.nextElement();
+            String path = url.getFile();
+
+            // Decode the url, esp on Windows where file paths can have their
+            // spaces encoded. decodeURL will convert C:\Program%20Files\project
+            // to C:\Program Files\project
+            path = ClickUtils.decodeURL(path);
+
+            // Strip file prefix
+            if (path.startsWith("file:")) {
+                path = path.substring(5);
+            }
+
+            String jarPath = null;
+
+            // Check if path represents a jar
+            if (path.indexOf('!') > 0) {
+                jarPath = path.substring(0, path.indexOf('!'));
+
+                File jar = new File(jarPath);
+
+                if (jar.exists()) {
+                    loadFilesInJar(jar);
+
+                } else {
+                    logService.error("Could not load the jar '" + jarPath
+                        + "'. Please ensure this file exists in the specified"
+                        + " location.");
+                }
+            } else {
+                File dir = new File(path);
+                loadFilesInJarDir(dir);
+            }
+        }
+
+        if (logService.isTraceEnabled()) {
+            logService.trace("loaded files from jars and folders - "
+                + (System.currentTimeMillis() - startTime) + " ms");
+        }
+    }
+
+    private void loadFilesInJar(File jar) throws IOException {
+        if (jar == null) {
+            throw new IllegalArgumentException("Jar cannot be null");
+        }
+
+        InputStream inputStream = null;
+        JarInputStream jarInputStream = null;
+
+        try {
+
+            inputStream = new FileInputStream(jar);
+            jarInputStream = new JarInputStream(inputStream);
+            JarEntry jarEntry = null;
+
+            // Indicates whether feedback should be logged about the files deployed
+            // from jar
+            boolean logFeedback = true;
+            while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
+                // jarEntryName example -> META-INF/web/click/table.css
+                String jarEntryName = jarEntry.getName();
+
+                // Only deploy resources from "META-INF/web/"
+                int pathIndex = jarEntryName.indexOf("META-INF/web/");
+                if (pathIndex == 0) {
+                    if (logFeedback && logService.isTraceEnabled()) {
+                        logService.trace("loaded files from jar -> "
+                                         + jar.getCanonicalPath());
+
+                        // Only provide feedback once per jar
+                        logFeedback = false;
+                    }
+                    loadJarFile(jarEntryName, "META-INF/web/");
+                }
+            }
+        } finally {
+            ClickUtils.close(jarInputStream);
+            ClickUtils.close(inputStream);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void loadFilesInJarDir(File dir) throws IOException {
+        if (dir == null) {
+            throw new IllegalArgumentException("Dir cannot be null");
+        }
+
+        if (!dir.exists()) {
+            logService.trace("There are no files in the folder '"
+                + dir.getAbsolutePath() + "'");
+            return;
+        }
+
+        Iterator files = FileUtils.iterateFiles(dir,
+                                                TrueFileFilter.INSTANCE,
+                                                TrueFileFilter.INSTANCE);
+
+        boolean logFeedback = true;
+        while (files.hasNext()) {
+            // file example -> META-INF/web/click/table.css
+            File file = (File) files.next();
+            String fileName = file.getCanonicalPath().replace('\\', '/');
+
+            // Only deploy resources from "META-INF/web/"
+            int pathIndex = fileName.indexOf("META-INF/web/");
+            if (pathIndex != -1) {
+                if (logFeedback && logService.isTraceEnabled()) {
+                    logService.trace("load files from folder -> "
+                        + dir.getAbsolutePath());
+
+                    // Only provide feedback once per dir
+                    logFeedback = false;
+                }
+                fileName = fileName.substring(pathIndex);
+                loadJarFile(fileName, "META-INF/web/");
+            }
+        }
+    }
+
+    private void loadJarFile(String file, String prefix) throws IOException {
+        // Only deploy resources containing the prefix
+        int pathIndex = file.indexOf(prefix);
+        if (pathIndex == 0) {
+            pathIndex += prefix.length();
+
+            // resourceName example -> click/table.css
+            String resourceName = file.substring(pathIndex);
+
+            if (resourceName.length() > 0) {
+                byte[] resourceBytes = getResourceByteArray(file);
+
+                resourceCache.put("/" + resourceName, resourceBytes);
+            }
+        }
+    }
+
+    private byte[] getResourceByteArray(String name)
+        throws IOException {
+
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+        InputStream inputStream = classLoader.getResourceAsStream(name);
+        if (inputStream == null) {
+            inputStream = getClass().getResourceAsStream(name);
+        }
+
+        try {
+            byte[] resourceData = IOUtils.toByteArray(inputStream);
+
+            return resourceData;
+
+        } finally {
+            ClickUtils.close(inputStream);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void loadClickDirResources(ServletContext servletContext)
+        throws IOException {
+
+        Set resources = servletContext.getResourcePaths("/click/");
+
+        // Add all resources withtin web application
+        for (Iterator i = resources.iterator(); i.hasNext();) {
+            String resource = (String) i.next();
+
+            if (!resource.endsWith(".htm")
+                && !resource.endsWith(".jsp")
+                && !resource.endsWith("/")) {
+
+                InputStream inputStream = null;
+                try {
+                    inputStream = servletContext.getResourceAsStream(resource);
+
+                    byte[] resourceData = IOUtils.toByteArray(inputStream);
+
+                     resourceCache.put(resource, resourceData);
+
+                } finally {
+                    ClickUtils.close(inputStream);
+                }
+            }
+        }
+    }
+
+}

Modified: incubator/click/trunk/click/framework/src/org/apache/click/service/ConfigService.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/service/ConfigService.java?rev=791369&r1=791368&r2=791369&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/service/ConfigService.java
(original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/service/ConfigService.java
Mon Jul  6 04:09:23 2009
@@ -90,8 +90,6 @@
  * ...
  *
  * &lt;/web-app&gt; </pre>
- *
- * @author Malcolm Edgar
  */
 public interface ConfigService {
 
@@ -138,8 +136,9 @@
 
     /**
      * Destroy the ConfigurationService. This method will also invoke the
-     * <tt>onDestory()</tt> methods on the <tt>FileUploadService</tt>
and the
-     * <tt>TemplateService</tt>.
+     * <tt>onDestory()</tt> methods on the <tt>FileUploadService</tt>,
+     * <tt>TemplateService</tt>, <tt>ResourceService</tt> and the
+     * <tt>LogService</tt> in that order.
      */
     public void onDestroy();
 
@@ -152,6 +151,20 @@
     public FileUploadService getFileUploadService();
 
     /**
+     * Return the application log service.
+     *
+     * @return the application log service.
+     */
+    public LogService getLogService();
+
+    /**
+     * Return the application resource service.
+     *
+     * @return the application resource service.
+     */
+    public ResourceService getResourceService();
+
+    /**
      * Return the application templating service.
      *
      * @return the application templating service
@@ -227,13 +240,6 @@
     public Locale getLocale();
 
     /**
-     * Return the Click application log service.
-     *
-     * @return the application log service.
-     */
-    public LogService getLogService();
-
-    /**
      * Return the path for the given page Class.
      *
      * @param pageClass the class of the Page to lookup the path for

Added: incubator/click/trunk/click/framework/src/org/apache/click/service/ResourceService.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/service/ResourceService.java?rev=791369&view=auto
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/service/ResourceService.java
(added)
+++ incubator/click/trunk/click/framework/src/org/apache/click/service/ResourceService.java
Mon Jul  6 04:09:23 2009
@@ -0,0 +1,71 @@
+/*
+ * 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.click.service;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Provides a static resource service interface.
+ *
+ * <h3>Configuration</h3>
+ * The default ResourceService is {@link ClickResourceService}.
+ * <p/>
+ * However you can instruct Click to use a different implementation by adding
+ * the following element to your <tt>click.xml</tt> configuration file.
+ *
+ * <pre class="codeConfig">
+ * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
+ * &lt;click-app charset="UTF-8"&gt;
+ *
+ *     &lt;pages package="com.mycorp.page"/&gt;
+ *
+ *     &lt;<span class="red">resource-service</span> classname="<span
class="blue">com.mycorp.service.DynamicResourceService</span>"&gt;
+ *
+ * &lt;/click-app&gt; </pre>
+ */
+public interface ResourceService {
+
+    /**
+     * Initialize the ResourceService with the given application configuration
+     * service instance.
+     * <p/>
+     * This method is invoked after the ResourceService has been constructed.
+     *
+     * @param servletContext the application servlet context
+     * @throws IOException if an IO error occurs initializing the service
+     */
+    public void onInit(ServletContext servletContext) throws IOException;
+
+    /**
+     * Destroy the ResourceService.
+     */
+    public void onDestroy();
+
+    /**
+     * Return the resource data byte array for the given resource path or null
+     * if not resource was found.
+     *
+     * @param resourcePath the path of the resource to lookup
+     * @return the resource data byte array if found or null otherwise
+     */
+    public byte[] getResourceData(String resourcePath);
+
+}

Modified: incubator/click/trunk/click/framework/src/org/apache/click/service/XmlConfigService.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/service/XmlConfigService.java?rev=791369&r1=791368&r2=791369&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/service/XmlConfigService.java
(original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/service/XmlConfigService.java
Mon Jul  6 04:09:23 2009
@@ -73,8 +73,6 @@
  * <p/>
  * However you can instruct Click to use a different service implementation.
  * Please see {@link ConfigService} for more details.
- *
- * @author Malcolm Edgar
  */
 public class XmlConfigService implements ConfigService, EntityResolver {
 
@@ -192,6 +190,9 @@
     /** The ServletContext instance. */
     private ServletContext servletContext;
 
+    /** The application ResourceService. */
+    private ResourceService resourceService;
+
     /** The application TemplateService. */
     private TemplateService templateService;
 
@@ -252,6 +253,9 @@
             // Load the Templating service
             loadTemplateService(rootElm);
 
+            // Load the Resource service
+            loadResourceService(rootElm);
+
         } finally {
             ClickUtils.close(inputStream);
         }
@@ -267,6 +271,9 @@
         if (getTemplateService() != null) {
             getTemplateService().onDestroy();
         }
+        if (getResourceService() != null) {
+            getResourceService().onDestroy();
+        }
         if (getLogService() != null) {
             getLogService().onDestroy();
         }
@@ -303,9 +310,27 @@
     }
 
     /**
+     * @see ConfigService#getLogService()
+     *
+     * @return the application log service.
+     */
+    public LogService getLogService() {
+        return logService;
+    }
+
+    /**
+     * @see ConfigService#getResourceService()
+     *
+     * @return the resource service
+     */
+    public ResourceService getResourceService() {
+        return resourceService;
+    }
+
+    /**
      * @see ConfigService#getTemplateService()
      *
-     * @return the FileUpload service
+     * @return the template service
      */
     public TemplateService getTemplateService() {
         return templateService;
@@ -335,15 +360,6 @@
     }
 
     /**
-     * @see ConfigService#getLogService()
-     *
-     * @return the application log service.
-     */
-    public LogService getLogService() {
-        return logService;
-    }
-
-    /**
      * @see ConfigService#getAutoBindingMode()
      *
      * @return the Page field auto binding mode { PUBLIC, ANNOTATION, NONE }
@@ -1190,7 +1206,6 @@
         }
     }
 
-
     /**
      * Deploy files from the specified directory.
      * <p/>
@@ -1486,6 +1501,43 @@
         }
     }
 
+    private void loadResourceService(Element rootElm) throws Exception {
+
+        Element resourceServiceElm = ClickUtils.getChild(rootElm, "resource-service");
+
+        if (resourceServiceElm != null) {
+            Class resourceServiceClass = CommonsFileUploadService.class;
+
+            String classname = resourceServiceElm.getAttribute("classname");
+
+            if (StringUtils.isNotBlank(classname)) {
+                resourceServiceClass = ClickUtils.classForName(classname);
+            }
+
+            resourceService = (ResourceService) resourceServiceClass.newInstance();
+
+            Map propertyMap = loadPropertyMap(resourceServiceElm);
+
+            for (Iterator i = propertyMap.keySet().iterator(); i.hasNext();) {
+                String name = i.next().toString();
+                String value = propertyMap.get(name).toString();
+
+                Ognl.setValue(name, resourceService, value);
+            }
+
+        } else {
+            resourceService = new ClickResourceService();
+        }
+
+        if (getLogService().isDebugEnabled()) {
+            String msg = "initializing ResourceService: "
+                + resourceService.getClass().getName();
+            getLogService().debug(msg);
+        }
+
+        resourceService.onInit(servletContext);
+    }
+
     private void loadTemplateService(Element rootElm) throws Exception {
         Element templateServiceElm = ClickUtils.getChild(rootElm, "template-service");
 



Mime
View raw message