Author: bdekruijff at gmail.com
Date: Mon Jan 31 11:08:15 2011
New Revision: 721
Log:
AMDATU-245 add resource extender module
Added:
branches/amdatu-dispatcher/amdatu-web/resource/
branches/amdatu-dispatcher/amdatu-web/resource/pom.xml
branches/amdatu-dispatcher/amdatu-web/resource/src/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/osgi/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/osgi/Activator.java
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/ResourceProviderListener.java
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/ResourceServlet.java
Modified:
branches/amdatu-dispatcher/amdatu-web/pom.xml
Modified: branches/amdatu-dispatcher/amdatu-web/pom.xml
==============================================================================
--- branches/amdatu-dispatcher/amdatu-web/pom.xml (original)
+++ branches/amdatu-dispatcher/amdatu-web/pom.xml Mon Jan 31 11:08:15 2011
@@ -41,6 +41,7 @@
<modules>
<module>dispatcher</module>
+ <module>resource</module>
<module>httpcontext</module>
<module>jsp</module>
<module>rest-jaxrs</module>
Added: branches/amdatu-dispatcher/amdatu-web/resource/pom.xml
==============================================================================
--- (empty file)
+++ branches/amdatu-dispatcher/amdatu-web/resource/pom.xml Mon Jan 31
11:08:15 2011
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.amdatu</groupId>
+ <artifactId>org.amdatu.web</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.amdatu.web</groupId>
+ <artifactId>resource</artifactId>
+ <packaging>bundle</packaging>
+ <name>Amdatu Web - Resource Support</name>
+ <description>Bundle providing Resource support</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.amdatu.web</groupId>
+ <artifactId>httpcontext</artifactId>
+ <scope>provided</scope>
+ <type>bundle</type>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+
<Bundle-Activator>org.amdatu.web.resource.osgi.Activator</Bundle-Activator>
+ <Bundle-SymbolicName>org.amdatu.web.resource</Bundle-SymbolicName>
+ <Embed-Dependency>*;scope=compile</Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ <Export-Package></Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
Added:
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/osgi/Activator.java
==============================================================================
--- (empty file)
+++
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/osgi/Activator.java
Mon Jan 31 11:08:15 2011
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.web.resource.osgi;
+
+import org.amdatu.web.httpcontext.ResourceProvider;
+import org.amdatu.web.resource.service.ResourceProviderListener;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+/**
+ * This is the activator for the resource support bundle.
+ */
+public class Activator extends DependencyActivatorBase {
+ public final static String RESOURCE_ID = "resourceservlet";
+
+ @Override
+ public void init(BundleContext context, DependencyManager manager) throws
Exception {
+ manager.add(
+ createComponent()
+ .setImplementation(ResourceProviderListener.class)
+
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+
.add(createServiceDependency().setService(ResourceProvider.class)
+ .setRequired(false)
+ .setCallbacks("resourceProviderAdded",
"resourceProviderRemoved")));
+ }
+
+ @Override
+ public void destroy(BundleContext context, DependencyManager manager)
throws Exception {
+ }
+}
Added:
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/ResourceProviderListener.java
==============================================================================
--- (empty file)
+++
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/ResourceProviderListener.java
Mon Jan 31 11:08:15 2011
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.web.resource.service;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.servlet.Servlet;
+
+import org.amdatu.web.httpcontext.ResourceProvider;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * This class is responsible for registration of Resource Servlets for each
+ * ResourceProvider that comes available.
+ */
+public class ResourceProviderListener {
+
+ private final Map<String, Component> m_servletComponents = new
HashMap<String, Component>();
+
+ private volatile DependencyManager m_dependencyManager;
+ private volatile BundleContext m_bundleContext;
+ private volatile LogService m_logService;
+
+ public void init() {
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+
+ public void destroy() {
+ }
+
+ public void resourceProviderAdded(ServiceReference serviceReference,
ResourceProvider resourceProvider) {
+
+ Dictionary<String, Object> properties = new Hashtable<String,
Object>();
+ properties.put("contextId", resourceProvider.getResourceId());
+ properties.put("alias",
getResourceAlias(resourceProvider.getResourceId()));
+
+ Component servletComponent = m_dependencyManager.createComponent();
+ servletComponent.setInterface(Servlet.class.getName(), properties);
+ servletComponent.setImplementation(new ResourceServlet(""));
+
+ m_dependencyManager.add(servletComponent);
+ m_servletComponents.put(resourceProvider.getResourceId(),
servletComponent);
+
+ m_logService.log(LogService.LOG_DEBUG,
+ "Resource servlet added for resource provider " +
resourceProvider.getResourceId());
+ }
+
+ public void resourceProviderRemoved(ResourceProvider resourceProvider) {
+
+ Component servletComponent =
m_servletComponents.remove(resourceProvider.getResourceId());
+ if (servletComponent != null)
+ m_dependencyManager.remove(servletComponent);
+
+ m_logService.log(LogService.LOG_DEBUG,
+ "Resource servlet removed for resource provider " +
resourceProvider.getResourceId());
+ }
+
+ private String getResourceAlias(String resourceId) {
+ String result = "";
+ if (!resourceId.startsWith("/")) {
+ result = "/" + resourceId;
+ }
+ else {
+ result = resourceId;
+ }
+ if (resourceId.endsWith("/")) {
+ result = result.substring(0, result.length() - 1);
+ }
+ return result;
+ }
+}
\ No newline at end of file
Added:
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/ResourceServlet.java
==============================================================================
--- (empty file)
+++
branches/amdatu-dispatcher/amdatu-web/resource/src/main/java/org/amdatu/web/resource/service/ResourceServlet.java
Mon Jan 31 11:08:15 2011
@@ -0,0 +1,140 @@
+/*
+ * 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.amdatu.web.resource.service;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+public final class ResourceServlet extends HttpServlet {
+
+ private final String path;
+
+ public ResourceServlet(String path) {
+ this.path = path;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
+ String target = req.getPathInfo();
+ if (target == null) {
+ target = "";
+ }
+
+ if (!target.startsWith("/")) {
+ target += "/" + target;
+ }
+
+ String resName = this.path + target;
+ URL url = getServletContext().getResource(resName);
+
+ if (url == null) {
+ res.sendError(HttpServletResponse.SC_NOT_FOUND);
+ }
+ else {
+ handle(req, res, url, resName);
+ }
+ }
+
+ private void handle(HttpServletRequest req, HttpServletResponse res, URL
url, String resName) throws IOException {
+ String contentType = getServletContext().getMimeType(resName);
+ if (contentType != null) {
+ res.setContentType(contentType);
+ }
+
+ long lastModified = getLastModified(url);
+ if (lastModified != 0) {
+ res.setDateHeader("Last-Modified", lastModified);
+ }
+
+ if (!resourceModified(lastModified,
req.getDateHeader("If-Modified-Since"))) {
+ res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ }
+ else {
+ copyResource(url, res);
+ }
+ }
+
+ private long getLastModified(URL url) {
+ long lastModified = 0;
+
+ try {
+ URLConnection conn = url.openConnection();
+ lastModified = conn.getLastModified();
+ }
+ catch (Exception e) {
+ // Do nothing
+ }
+
+ if (lastModified == 0) {
+ String filepath = url.getPath();
+ if (filepath != null) {
+ File f = new File(filepath);
+ if (f.exists()) {
+ lastModified = f.lastModified();
+ }
+ }
+ }
+
+ return lastModified;
+ }
+
+ private boolean resourceModified(long resTimestamp, long modSince) {
+ modSince /= 1000;
+ resTimestamp /= 1000;
+
+ return resTimestamp == 0 || modSince == -1 || resTimestamp > modSince;
+ }
+
+ private void copyResource(URL url, HttpServletResponse res)
+ throws IOException {
+ OutputStream os = null;
+ InputStream is = null;
+
+ try {
+ os = res.getOutputStream();
+ is = url.openStream();
+
+ int len = 0;
+ byte[] buf = new byte[1024];
+ int n;
+
+ while ((n = is.read(buf, 0, buf.length)) >= 0) {
+ os.write(buf, 0, n);
+ len += n;
+ }
+
+ res.setContentLength(len);
+ }
+ finally {
+ if (is != null) {
+ is.close();
+ }
+
+ if (os != null) {
+ os.close();
+ }
+ }
+ }
+}