Added patch equinox servlet bridge:
1) Filter support from http://angelozerr.wordpress.com/2010/09/08/osgi-equinox-in-a-servlet-container-step4/ 2) Modify to work with OSGi web container ( geminiweb ) instead of normal servlet container
This commit is contained in:
parent
30853d1196
commit
cc5708c8d0
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.adempiere.eclipse.equinox.http.servlet</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,8 @@
|
|||
#Fri Dec 24 14:42:06 MYT 2010
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,4 @@
|
|||
#Fri Dec 24 14:42:06 MYT 2010
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
|
@ -0,0 +1,20 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
|
||||
Bundle-SymbolicName: org.adempiere.eclipse.equinox.http.servlet
|
||||
Eclipse-LazyStart: true
|
||||
Eclipse-SourceReferences: scm:cvs:pserver:dev.eclipse.org:/cvsroot/rt:
|
||||
org.eclipse.equinox/compendium/bundles/org.eclipse.equinox.http.servl
|
||||
et;tag=v20100503
|
||||
Bundle-Activator: org.eclipse.equinox.http.servlet.internal.Activator
|
||||
Export-Package: org.eclipse.equinox.http.servlet;version="1.1.0"
|
||||
Bundle-Version: 1.1.0.v20100503
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Name: %bundleName
|
||||
Comment-Header: Both Eclipse-LazyStart and Bundle-ActivationPolicy are
|
||||
specified for compatibility with 3.2
|
||||
Import-Package: javax.servlet;version="2.3",javax.servlet.http;version
|
||||
="2.3",org.osgi.framework;version="1.3.0",org.osgi.service.http;versi
|
||||
on="1.2.0"
|
||||
Bundle-ManifestVersion: 2
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
|
||||
<title>About</title>
|
||||
</head>
|
||||
<body lang="EN-US">
|
||||
<h2>About This Content</h2>
|
||||
|
||||
<p>January 30, 2007</p>
|
||||
<h3>License</h3>
|
||||
|
||||
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
|
||||
indicated below, the Content is provided to you under the terms and conditions of the
|
||||
Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
|
||||
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
|
||||
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||
|
||||
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
|
||||
being redistributed by another party ("Redistributor") and different terms and conditions may
|
||||
apply to your use of any object code in the Content. Check the Redistributor's license that was
|
||||
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
|
||||
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
|
||||
and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
|
@ -0,0 +1,4 @@
|
|||
##Source Bundle Localization
|
||||
#Thu Jun 24 08:34:29 EDT 2010
|
||||
bundleName=Http Services Servlet Source
|
||||
providerName=Eclipse.org - Equinox
|
|
@ -0,0 +1,55 @@
|
|||
package org.eclipse.equinox.http.servlet;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.ServletException;
|
||||
import org.osgi.service.http.*;
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface ExtendedHttpService extends HttpService {
|
||||
/**
|
||||
* @param alias name in the URI namespace at which the filter is registered
|
||||
* @param filter the filter object to register
|
||||
* @param initparams initialization arguments for the filter or
|
||||
* <code>null</code> if there are none. This argument is used by the
|
||||
* filter's <code>FilterConfig</code> object.
|
||||
* @param context the <code>HttpContext</code> object for the registered
|
||||
* filter, or <code>null</code> if a default <code>HttpContext</code> is
|
||||
* to be created and used.
|
||||
* @throws javax.servlet.ServletException if the filter's <code>init</code>
|
||||
* method throws an exception, or the given filter object has
|
||||
* already been registered at a different alias.
|
||||
* @throws java.lang.IllegalArgumentException if any of the arguments are
|
||||
* invalid
|
||||
*/
|
||||
public void registerFilter(String alias, Filter filter, Dictionary initparams, HttpContext context) throws ServletException, NamespaceException;
|
||||
|
||||
/**
|
||||
* Unregisters a previous filter registration done by the
|
||||
* <code>registerFilter</code> method.
|
||||
*
|
||||
* <p>
|
||||
* After this call, the registered filter will no
|
||||
* longer be available. The Http Service must call the <code>destroy</code>
|
||||
* method of the filter before returning.
|
||||
* <p>
|
||||
* If the bundle which performed the registration is stopped or otherwise
|
||||
* "unget"s the Http Service without calling {@link #unregisterFilter} then the Http
|
||||
* Service must automatically unregister the filter registration. However, the
|
||||
* <code>destroy</code> method of the filter will not be called in this case since
|
||||
* the bundle may be stopped.
|
||||
* {@link #unregisterFilter} must be explicitly called to cause the
|
||||
* <code>destroy</code> method of the filter to be called. This can be done
|
||||
* in the <code>BundleActivator.stop</code> method of the
|
||||
* bundle registering the filter.
|
||||
*
|
||||
* @param filter the filter object to unregister
|
||||
* @throws java.lang.IllegalArgumentException if there is no registration
|
||||
* for the filter or the calling bundle was not the bundle which
|
||||
* registered the filter.
|
||||
*/
|
||||
public void unregisterFilter(Filter filter);
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2008 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet;
|
||||
|
||||
import org.eclipse.equinox.http.servlet.internal.ProxyServlet;
|
||||
|
||||
/**
|
||||
* The HttpServiceServlet is the "public" side of a Servlet that when registered (and init() called) in a servlet container
|
||||
* will in-turn register and provide an OSGi Http Service implementation.
|
||||
* This class is not meant for extending or even using directly and is purely meant for registering
|
||||
* in a servlet container.
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class HttpServiceServlet extends ProxyServlet {
|
||||
private static final long serialVersionUID = -3647550992964861187L;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.ServletConfig;
|
||||
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
|
||||
import org.osgi.framework.*;
|
||||
import org.osgi.service.http.HttpService;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
|
||||
private static final String DEFAULT_SERVICE_DESCRIPTION = "Equinox Servlet Bridge"; //$NON-NLS-1$
|
||||
private static final String DEFAULT_SERVICE_VENDOR = "Eclipse.org"; //$NON-NLS-1$
|
||||
private static final String[] HTTP_SERVICES_CLASSES = new String[] {HttpService.class.getName(), ExtendedHttpService.class.getName()};
|
||||
|
||||
private static BundleContext context;
|
||||
private static Map serviceRegistrations = new HashMap();
|
||||
|
||||
public void start(BundleContext bundleContext) throws Exception {
|
||||
startHttpServiceProxy(bundleContext);
|
||||
}
|
||||
|
||||
public void stop(BundleContext bundleContext) throws Exception {
|
||||
stopHttpServiceProxy(bundleContext);
|
||||
}
|
||||
|
||||
private static synchronized void startHttpServiceProxy(BundleContext bundleContext) {
|
||||
context = bundleContext;
|
||||
Object[] proxyServlets = serviceRegistrations.keySet().toArray();
|
||||
for (int i = 0; i < proxyServlets.length; ++i) {
|
||||
ServiceRegistration registration = registerHttpService((ProxyServlet) proxyServlets[i]);
|
||||
serviceRegistrations.put(proxyServlets[i], registration);
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized void stopHttpServiceProxy(BundleContext bundleContext) {
|
||||
Object[] proxyServlets = serviceRegistrations.keySet().toArray();
|
||||
for (int i = 0; i < proxyServlets.length; ++i) {
|
||||
ServiceRegistration registration = (ServiceRegistration) serviceRegistrations.put(proxyServlets[i], null);
|
||||
registration.unregister();
|
||||
}
|
||||
context = null;
|
||||
}
|
||||
|
||||
static synchronized void addProxyServlet(ProxyServlet proxyServlet) {
|
||||
ServiceRegistration registration = null;
|
||||
if (context != null)
|
||||
registration = registerHttpService(proxyServlet);
|
||||
|
||||
serviceRegistrations.put(proxyServlet, registration);
|
||||
}
|
||||
|
||||
private static ServiceRegistration registerHttpService(ProxyServlet proxyServlet) {
|
||||
HttpServiceFactory factory = new HttpServiceFactory(proxyServlet);
|
||||
Dictionary serviceProperties = new Hashtable(2);
|
||||
ServletConfig config = proxyServlet.getServletConfig();
|
||||
Enumeration initparameterNames = config.getInitParameterNames();
|
||||
while (initparameterNames.hasMoreElements()) {
|
||||
String name = (String) initparameterNames.nextElement();
|
||||
serviceProperties.put(name, config.getInitParameter(name));
|
||||
}
|
||||
|
||||
if (serviceProperties.get(Constants.SERVICE_VENDOR) == null)
|
||||
serviceProperties.put(Constants.SERVICE_VENDOR, DEFAULT_SERVICE_VENDOR);
|
||||
|
||||
if (serviceProperties.get(Constants.SERVICE_DESCRIPTION) == null)
|
||||
serviceProperties.put(Constants.SERVICE_DESCRIPTION, DEFAULT_SERVICE_DESCRIPTION);
|
||||
|
||||
return context.registerService(HTTP_SERVICES_CLASSES, factory, serviceProperties);
|
||||
}
|
||||
|
||||
static synchronized void removeProxyServlet(ProxyServlet proxyServlet) {
|
||||
ServiceRegistration registration = (ServiceRegistration) serviceRegistrations.remove(proxyServlet);
|
||||
if (registration != null)
|
||||
registration.unregister();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
public class DefaultHttpContext implements HttpContext {
|
||||
|
||||
private Bundle bundle;
|
||||
|
||||
public DefaultHttpContext(Bundle bundle) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
// default behaviour assumes the container has already performed authentication
|
||||
return true;
|
||||
}
|
||||
|
||||
public URL getResource(String name) {
|
||||
return bundle.getResource(name);
|
||||
}
|
||||
|
||||
public String getMimeType(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class FilterChainImpl implements FilterChain {
|
||||
|
||||
private List matchingFilterRegistrations;
|
||||
private ServletRegistration registration;
|
||||
private int filterIndex = 0;
|
||||
private int filterCount;
|
||||
|
||||
public FilterChainImpl(List matchingFilterRegistrations, ServletRegistration registration) {
|
||||
this.matchingFilterRegistrations = matchingFilterRegistrations;
|
||||
this.registration = registration;
|
||||
this.filterCount = matchingFilterRegistrations.size();
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
if (filterIndex < filterCount) {
|
||||
FilterRegistration filterRegistration = (FilterRegistration) matchingFilterRegistrations.get(filterIndex++);
|
||||
filterRegistration.doFilter((HttpServletRequest) request, (HttpServletResponse) response, this);
|
||||
return;
|
||||
}
|
||||
registration.service((HttpServletRequest) request, (HttpServletResponse) response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
|
||||
public class FilterConfigImpl implements FilterConfig {
|
||||
|
||||
private static final Dictionary EMPTY_PARAMS = new Hashtable(0);
|
||||
private static final String FILTER_NAME = "filter-name"; //$NON-NLS-1$
|
||||
private Filter filter;
|
||||
private Dictionary initparams;
|
||||
private ServletContext servletContext;
|
||||
|
||||
public FilterConfigImpl(Filter filter, Dictionary initparams, ServletContext servletContext) {
|
||||
this.filter = filter;
|
||||
this.initparams = (initparams != null) ? initparams : EMPTY_PARAMS;
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see javax.servlet.FilterConfig#getFilterName()
|
||||
*
|
||||
* The OSGi Http Service does not specify a way to set a filter name at the API level. This
|
||||
* implementation will try to use the value of the "filter-name" initial parameter if available.
|
||||
*/
|
||||
public String getFilterName() {
|
||||
String filterName = (String) initparams.get(FILTER_NAME);
|
||||
return (filterName != null) ? filterName : filter.getClass().getName();
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return servletContext;
|
||||
}
|
||||
|
||||
public String getInitParameter(String name) {
|
||||
return (String) initparams.get(name);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return initparams.keys();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
//This class wraps the filter object registered in the HttpService.registerFilter call, to manage the context classloader when handleRequests are being asked.
|
||||
public class FilterRegistration extends Registration implements Comparable {
|
||||
|
||||
private static long nextSequenceNumber = 1L;
|
||||
|
||||
private final Filter filter; //The actual filter object registered against the http service. All filter requests will eventually be delegated to it.
|
||||
private final HttpContext httpContext; //The context used during the registration of the filter
|
||||
private final ClassLoader registeredContextClassLoader;
|
||||
private final String prefix;
|
||||
private final String suffix;
|
||||
private final int priority;
|
||||
private final long sequenceNumber;
|
||||
|
||||
public FilterRegistration(Filter filter, HttpContext context, String alias, int priority) {
|
||||
this.filter = filter;
|
||||
this.httpContext = context;
|
||||
registeredContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
int lastSlash = alias.lastIndexOf('/');
|
||||
String lastSegment = alias.substring(alias.lastIndexOf('/') + 1);
|
||||
if (lastSegment.startsWith("*.")) { //$NON-NLS-1$
|
||||
prefix = alias.substring(0, lastSlash);
|
||||
suffix = lastSegment.substring(1);
|
||||
} else {
|
||||
prefix = alias.equals("/") ? "" : alias; //$NON-NLS-1$//$NON-NLS-2$
|
||||
suffix = null;
|
||||
}
|
||||
|
||||
this.priority = priority;
|
||||
synchronized (FilterRegistration.class) {
|
||||
this.sequenceNumber = nextSequenceNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
|
||||
super.destroy();
|
||||
filter.destroy();
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
//Delegate the init call to the actual filter
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
|
||||
filter.init(filterConfig);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
//Delegate the handling of the request to the actual filter
|
||||
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
|
||||
if (httpContext.handleSecurity(request, response))
|
||||
filter.doFilter(request, response, chain);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
public Filter getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public HttpContext getHttpContext() {
|
||||
return httpContext;
|
||||
}
|
||||
|
||||
public boolean matches(String dispatchPathInfo) {
|
||||
if (!dispatchPathInfo.startsWith(prefix))
|
||||
return false;
|
||||
|
||||
// perfect match
|
||||
if (prefix.length() == dispatchPathInfo.length())
|
||||
return suffix == null;
|
||||
|
||||
// check the next character is a path separator
|
||||
if (dispatchPathInfo.charAt(prefix.length()) != '/')
|
||||
return false;
|
||||
|
||||
// check for an extension match
|
||||
if (suffix == null)
|
||||
return true;
|
||||
|
||||
return dispatchPathInfo.endsWith(suffix) && dispatchPathInfo.length() > prefix.length() + suffix.length();
|
||||
}
|
||||
|
||||
public int compareTo(Object other) {
|
||||
FilterRegistration otherFilterRegistration = (FilterRegistration) other;
|
||||
int priorityDifference = priority - otherFilterRegistration.priority;
|
||||
if (priorityDifference != 0)
|
||||
return -priorityDifference;
|
||||
|
||||
return (sequenceNumber > otherFilterRegistration.sequenceNumber) ? 1 : -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import org.osgi.framework.*;
|
||||
|
||||
// Factory to create http services. This is because the service needs to be customized for each bundle in order to implement the default resource lookups.
|
||||
public class HttpServiceFactory implements ServiceFactory {
|
||||
|
||||
private ProxyServlet proxy;
|
||||
|
||||
public HttpServiceFactory(ProxyServlet proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Object getService(Bundle bundle, ServiceRegistration registration) {
|
||||
return new HttpServiceImpl(bundle, proxy);
|
||||
}
|
||||
|
||||
public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
|
||||
((HttpServiceImpl) service).shutdown();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2010 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.service.http.*;
|
||||
|
||||
public class HttpServiceImpl implements HttpService, ExtendedHttpService {
|
||||
|
||||
private Bundle bundle; //The bundle associated with this instance of http service
|
||||
|
||||
private ProxyServlet proxy; //The proxy that does the dispatching of the incoming requests
|
||||
|
||||
private Set aliases = new HashSet(); //Aliases registered against this particular instance of the service
|
||||
private Set filters = new HashSet(); //Filters registered against this particular instance of the service
|
||||
|
||||
private boolean shutdown = false; // We prevent use of this instance if HttpServiceFactory.ungetService has called unregisterAliases.
|
||||
|
||||
public HttpServiceImpl(Bundle bundle, ProxyServlet proxy) {
|
||||
this.bundle = bundle;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
//Clean up method
|
||||
synchronized void shutdown() {
|
||||
for (Iterator it = aliases.iterator(); it.hasNext();) {
|
||||
String alias = (String) it.next();
|
||||
proxy.unregister(alias, false);
|
||||
}
|
||||
aliases.clear();
|
||||
|
||||
for (Iterator it = filters.iterator(); it.hasNext();) {
|
||||
Filter filter = (Filter) it.next();
|
||||
proxy.unregisterFilter(filter, false);
|
||||
}
|
||||
filters.clear();
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
private void checkShutdown() {
|
||||
if (shutdown)
|
||||
throw new IllegalStateException("Service instance is already shutdown"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HttpService#registerServlet(String, Servlet, Dictionary, HttpContext)
|
||||
*/
|
||||
public synchronized void registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext context) throws ServletException, NamespaceException {
|
||||
checkShutdown();
|
||||
if (context == null) {
|
||||
context = createDefaultHttpContext();
|
||||
}
|
||||
proxy.registerServlet(alias, servlet, initparams, context);
|
||||
aliases.add(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HttpService#registerResources(String, String, HttpContext)
|
||||
*/
|
||||
public synchronized void registerResources(String alias, String name, HttpContext context) throws NamespaceException {
|
||||
checkShutdown();
|
||||
if (context == null) {
|
||||
context = createDefaultHttpContext();
|
||||
}
|
||||
proxy.registerResources(alias, name, context);
|
||||
aliases.add(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HttpService#unregister(String)
|
||||
*/
|
||||
public synchronized void unregister(String alias) {
|
||||
checkShutdown();
|
||||
if (aliases.remove(alias)) {
|
||||
proxy.unregister(alias, true);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Alias not found: " + alias); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HttpService#createDefaultHttpContext()
|
||||
*/
|
||||
public synchronized HttpContext createDefaultHttpContext() {
|
||||
checkShutdown();
|
||||
return new DefaultHttpContext(bundle);
|
||||
}
|
||||
|
||||
public void registerFilter(String alias, Filter filter, Dictionary initparams, HttpContext context) throws ServletException {
|
||||
checkShutdown();
|
||||
if (context == null) {
|
||||
context = createDefaultHttpContext();
|
||||
}
|
||||
proxy.registerFilter(alias, filter, initparams, context);
|
||||
filters.add(filter);
|
||||
}
|
||||
|
||||
public void unregisterFilter(Filter filter) {
|
||||
checkShutdown();
|
||||
if (filters.remove(filter)) {
|
||||
proxy.unregisterFilter(filter, true);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Filter not found."); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
* Angelo Zerr <angelo.zerr@gmail.com> - give the capability to use resources (JSP, HTML, Servlet...)
|
||||
* from the Bridge webapp with HTTP Filter.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
public class HttpServletRequestAdaptor extends HttpServletRequestWrapper {
|
||||
|
||||
private String alias;
|
||||
private Servlet servlet;
|
||||
private boolean isRequestDispatcherInclude;
|
||||
private boolean calledByFilter;
|
||||
|
||||
static final String INCLUDE_REQUEST_URI_ATTRIBUTE = "javax.servlet.include.request_uri"; //$NON-NLS-1$
|
||||
static final String INCLUDE_CONTEXT_PATH_ATTRIBUTE = "javax.servlet.include.context_path"; //$NON-NLS-1$
|
||||
static final String INCLUDE_SERVLET_PATH_ATTRIBUTE = "javax.servlet.include.servlet_path"; //$NON-NLS-1$
|
||||
static final String INCLUDE_PATH_INFO_ATTRIBUTE = "javax.servlet.include.path_info"; //$NON-NLS-1$
|
||||
|
||||
public HttpServletRequestAdaptor(HttpServletRequest req, String alias, Servlet servlet, FilterChain filterChain) {
|
||||
super(req);
|
||||
this.alias = alias;
|
||||
this.servlet = servlet;
|
||||
isRequestDispatcherInclude = req.getAttribute(HttpServletRequestAdaptor.INCLUDE_REQUEST_URI_ATTRIBUTE) != null;
|
||||
this.calledByFilter = (filterChain != null);
|
||||
}
|
||||
|
||||
public String getAuthType() {
|
||||
String authType = (String) super.getAttribute(HttpContext.AUTHENTICATION_TYPE);
|
||||
if (authType != null)
|
||||
return authType;
|
||||
|
||||
return super.getAuthType();
|
||||
}
|
||||
|
||||
public String getRemoteUser() {
|
||||
String remoteUser = (String) super.getAttribute(HttpContext.REMOTE_USER);
|
||||
if (remoteUser != null)
|
||||
return remoteUser;
|
||||
|
||||
return super.getRemoteUser();
|
||||
}
|
||||
|
||||
public String getPathInfo() {
|
||||
String pathInfo = getPathInfo(super.getPathInfo(), super.getContextPath(), super.getRequestURI(), this.calledByFilter);
|
||||
if (isRequestDispatcherInclude)
|
||||
return pathInfo;
|
||||
|
||||
if (alias.equals("/")) { //$NON-NLS-1$
|
||||
return pathInfo;
|
||||
}
|
||||
pathInfo = pathInfo.substring(alias.length());
|
||||
if (pathInfo.length() == 0)
|
||||
return null;
|
||||
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
public String getServletPath() {
|
||||
if (isRequestDispatcherInclude)
|
||||
return super.getServletPath();
|
||||
|
||||
if (alias.equals("/")) { //$NON-NLS-1$
|
||||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
return alias;
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
if (isRequestDispatcherInclude)
|
||||
return super.getContextPath();
|
||||
if (!calledByFilter)
|
||||
// Not called with HTTP Filter, servlet case.
|
||||
return super.getContextPath() + super.getServletPath();
|
||||
// HTTP Filter case.
|
||||
return super.getContextPath();
|
||||
}
|
||||
|
||||
public Object getAttribute(String attributeName) {
|
||||
if (isRequestDispatcherInclude) {
|
||||
if (attributeName.equals(HttpServletRequestAdaptor.INCLUDE_CONTEXT_PATH_ATTRIBUTE)) {
|
||||
String contextPath = (String) super.getAttribute(HttpServletRequestAdaptor.INCLUDE_CONTEXT_PATH_ATTRIBUTE);
|
||||
if (contextPath == null || contextPath.equals("/")) //$NON-NLS-1$
|
||||
contextPath = ""; //$NON-NLS-1$
|
||||
|
||||
String servletPath = (String) super.getAttribute(HttpServletRequestAdaptor.INCLUDE_SERVLET_PATH_ATTRIBUTE);
|
||||
if (servletPath == null || servletPath.equals("/")) //$NON-NLS-1$
|
||||
servletPath = ""; //$NON-NLS-1$
|
||||
|
||||
return contextPath + servletPath;
|
||||
} else if (attributeName.equals(HttpServletRequestAdaptor.INCLUDE_SERVLET_PATH_ATTRIBUTE)) {
|
||||
if (alias.equals("/")) { //$NON-NLS-1$
|
||||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
return alias;
|
||||
} else if (attributeName.equals(HttpServletRequestAdaptor.INCLUDE_PATH_INFO_ATTRIBUTE)) {
|
||||
String pathInfo = (String) super.getAttribute(HttpServletRequestAdaptor.INCLUDE_PATH_INFO_ATTRIBUTE);
|
||||
if (alias.equals("/")) { //$NON-NLS-1$
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
pathInfo = pathInfo.substring(alias.length());
|
||||
if (pathInfo.length() == 0)
|
||||
return null;
|
||||
|
||||
return pathInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return super.getAttribute(attributeName);
|
||||
}
|
||||
|
||||
public RequestDispatcher getRequestDispatcher(String arg0) {
|
||||
return new RequestDispatcherAdaptor(super.getRequestDispatcher(super.getServletPath() + arg0));
|
||||
}
|
||||
|
||||
public static String getDispatchPathInfo(HttpServletRequest req, FilterChain filterChain) {
|
||||
if (req.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE) != null)
|
||||
return (String) req.getAttribute(INCLUDE_PATH_INFO_ATTRIBUTE);
|
||||
return getPathInfo(req.getPathInfo(), req.getContextPath(), req.getRequestURI(), filterChain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path info pathInfo if not null otherwise compute it (in Filter case) by using contextPath + requestURI.
|
||||
*
|
||||
* @param pathInfo the path info coming from the request.getPathInfo().
|
||||
* @param contextPath the context path coming from the request.getContextPath().
|
||||
* @param requestURI the request URI coming from the request.getRequestURI().
|
||||
* @param filterChain the filter chain or null if this method is not called with Filter.
|
||||
* @return the path info pathInfo if not null otherwise compute it (in Filter case) by using contextPath + requestURI.
|
||||
*/
|
||||
private static String getPathInfo(String pathInfo, String contextPath, String requestURI, FilterChain filterChain) {
|
||||
return getPathInfo(pathInfo, contextPath, requestURI, filterChain != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path info pathInfo if not null otherwise compute it (in Filter case) by using contextPath + requestURI.
|
||||
*
|
||||
* @param pathInfo the path info coming from the request.getPathInfo().
|
||||
* @param contextPath the context path coming from the request.getContextPath().
|
||||
* @param requestURI the request URI coming from the request.getRequestURI().
|
||||
* @param calledByFilter true if this method is called with Filter and false otherwise.
|
||||
* @return the path info pathInfo if not null otherwise compute it (in Filter case) by using contextPath + requestURI.
|
||||
*/
|
||||
private static String getPathInfo(String pathInfo, String contextPath, String requestURI, boolean calledByFilter) {
|
||||
if (pathInfo != null) {
|
||||
return pathInfo;
|
||||
}
|
||||
if (!calledByFilter) {
|
||||
// Not called with HTTP Filter, servlet case.
|
||||
return null;
|
||||
}
|
||||
|
||||
// HTTP Filter case, pathInfo is null, compute it by using contextPath and requestURI
|
||||
return requestURI.substring(contextPath.length(), requestURI.length());
|
||||
}
|
||||
|
||||
public static String getDispatchServletPath(HttpServletRequest req) {
|
||||
if (req.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE) != null) {
|
||||
String servletPath = (String) req.getAttribute(INCLUDE_SERVLET_PATH_ATTRIBUTE);
|
||||
return (servletPath == null) ? "" : servletPath; //$NON-NLS-1$
|
||||
}
|
||||
return req.getServletPath();
|
||||
}
|
||||
|
||||
public HttpSession getSession() {
|
||||
HttpSession session = super.getSession();
|
||||
if (session != null)
|
||||
return new HttpSessionAdaptor(session, servlet);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpSession getSession(boolean create) {
|
||||
HttpSession session = super.getSession(create);
|
||||
if (session != null)
|
||||
return new HttpSessionAdaptor(session, servlet);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
// This class adapts HttpSessions in order to return the right ServletContext
|
||||
public class HttpSessionAdaptor implements HttpSession {
|
||||
|
||||
private HttpSession session;
|
||||
private Servlet servlet;
|
||||
|
||||
public HttpSessionAdaptor(HttpSession session, Servlet servlet) {
|
||||
this.session = session;
|
||||
this.servlet = servlet;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return servlet.getServletConfig().getServletContext();
|
||||
}
|
||||
|
||||
public Object getAttribute(String arg0) {
|
||||
return session.getAttribute(arg0);
|
||||
}
|
||||
|
||||
public Enumeration getAttributeNames() {
|
||||
return session.getAttributeNames();
|
||||
}
|
||||
|
||||
public long getCreationTime() {
|
||||
return session.getCreationTime();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return session.getId();
|
||||
}
|
||||
|
||||
public long getLastAccessedTime() {
|
||||
return session.getLastAccessedTime();
|
||||
}
|
||||
|
||||
public int getMaxInactiveInterval() {
|
||||
return session.getMaxInactiveInterval();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public javax.servlet.http.HttpSessionContext getSessionContext() {
|
||||
return session.getSessionContext();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public Object getValue(String arg0) {
|
||||
return session.getValue(arg0);
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public String[] getValueNames() {
|
||||
return session.getValueNames();
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
session.invalidate();
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
return session.isNew();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public void putValue(String arg0, Object arg1) {
|
||||
session.putValue(arg0, arg1);
|
||||
}
|
||||
|
||||
public void removeAttribute(String arg0) {
|
||||
session.removeAttribute(arg0);
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public void removeValue(String arg0) {
|
||||
session.removeValue(arg0);
|
||||
}
|
||||
|
||||
public void setAttribute(String arg0, Object arg1) {
|
||||
session.setAttribute(arg0, arg1);
|
||||
}
|
||||
|
||||
public void setMaxInactiveInterval(int arg0) {
|
||||
session.setMaxInactiveInterval(arg0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
/**
|
||||
* The ProxyContext provides something similar to a ServletContext for all servlets and resources under a particular ProxyServlet.
|
||||
* In particular it holds and represent the concept of "context path" through the Proxy Servlets servlet path.
|
||||
* The Http Service also requires a ServletContext namespaced by each individual HttpContext. The ProxyContext provides support for the
|
||||
* attribute map of a ServletContext again namespaced by HttpContext as specified in the Http Service specification. The ContextAttributes
|
||||
* are reference counted so that when the HttpContext is no longer referenced the associated context attributes can be
|
||||
* garbage collected and the context temp dir deleteted.
|
||||
*/
|
||||
public class ProxyContext {
|
||||
private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir"; //$NON-NLS-1$
|
||||
|
||||
private String servletPath;
|
||||
private HashMap attributesMap = new HashMap();
|
||||
File proxyContextTempDir;
|
||||
|
||||
public ProxyContext(ServletContext servletContext) {
|
||||
File tempDir = (File) servletContext.getAttribute(JAVAX_SERVLET_CONTEXT_TEMPDIR);
|
||||
if (tempDir != null) {
|
||||
proxyContextTempDir = new File(tempDir, "proxytemp"); //$NON-NLS-1$
|
||||
deleteDirectory(proxyContextTempDir);
|
||||
proxyContextTempDir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (proxyContextTempDir != null)
|
||||
deleteDirectory(proxyContextTempDir);
|
||||
}
|
||||
|
||||
synchronized void initializeServletPath(HttpServletRequest req, FilterChain filterChain) {
|
||||
if (servletPath == null) {
|
||||
if (filterChain != null)
|
||||
servletPath = "/";
|
||||
else
|
||||
servletPath = HttpServletRequestAdaptor.getDispatchServletPath(req);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized String getServletPath() {
|
||||
return servletPath;
|
||||
}
|
||||
|
||||
synchronized void createContextAttributes(HttpContext httpContext) {
|
||||
ContextAttributes attributes = (ContextAttributes) attributesMap.get(httpContext);
|
||||
if (attributes == null) {
|
||||
attributes = new ContextAttributes(httpContext);
|
||||
attributesMap.put(httpContext, attributes);
|
||||
}
|
||||
attributes.addReference();
|
||||
}
|
||||
|
||||
synchronized void destroyContextAttributes(HttpContext httpContext) {
|
||||
ContextAttributes attributes = (ContextAttributes) attributesMap.get(httpContext);
|
||||
attributes.removeReference();
|
||||
if (attributes.referenceCount() == 0) {
|
||||
attributesMap.remove(httpContext);
|
||||
attributes.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized Dictionary getContextAttributes(HttpContext httpContext) {
|
||||
return (Dictionary) attributesMap.get(httpContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* deleteDirectory is a convenience method to recursively delete a directory
|
||||
* @param directory - the directory to delete.
|
||||
* @return was the delete succesful
|
||||
*/
|
||||
protected static boolean deleteDirectory(File directory) {
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
File[] files = directory.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isDirectory()) {
|
||||
deleteDirectory(files[i]);
|
||||
} else {
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
return directory.delete();
|
||||
}
|
||||
|
||||
public class ContextAttributes extends Hashtable {
|
||||
private static final long serialVersionUID = 1916670423277243587L;
|
||||
private int referenceCount;
|
||||
|
||||
public ContextAttributes(HttpContext httpContext) {
|
||||
if (proxyContextTempDir != null) {
|
||||
File contextTempDir = new File(proxyContextTempDir, "hc_" + httpContext.hashCode()); //$NON-NLS-1$
|
||||
contextTempDir.mkdirs();
|
||||
put(JAVAX_SERVLET_CONTEXT_TEMPDIR, contextTempDir);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
File contextTempDir = (File) get(JAVAX_SERVLET_CONTEXT_TEMPDIR);
|
||||
if (contextTempDir != null)
|
||||
deleteDirectory(contextTempDir);
|
||||
}
|
||||
|
||||
public void addReference() {
|
||||
referenceCount++;
|
||||
}
|
||||
|
||||
public void removeReference() {
|
||||
referenceCount--;
|
||||
}
|
||||
|
||||
public int referenceCount() {
|
||||
return referenceCount;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
* Angelo Zerr <angelo.zerr@gmail.com> - give the capability to use resources (JSP, HTML, Servlet...)
|
||||
* from the Bridge webapp with HTTP Filter.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
import org.osgi.service.http.NamespaceException;
|
||||
|
||||
/**
|
||||
* The ProxyServlet is the private side of a Servlet that when registered (and init() called) in a servlet container
|
||||
* will in-turn register and provide an OSGi Http Service implementation.
|
||||
* This class is not meant for extending or even using directly and is purely meant for registering
|
||||
* in a servlet container.
|
||||
*/
|
||||
public class ProxyServlet extends HttpServlet implements Filter {
|
||||
|
||||
private static final long serialVersionUID = 4117456123807468871L;
|
||||
private Map servletRegistrations = new HashMap(); //alias --> servlet registration
|
||||
private Set registeredServlets = new HashSet(); //All the servlets objects that have been registered
|
||||
|
||||
private Map filterRegistrations = new HashMap(); //filter --> filter registration;
|
||||
private ProxyContext proxyContext;
|
||||
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
proxyContext = new ProxyContext(config.getServletContext());
|
||||
Activator.addProxyServlet(this);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
Activator.removeProxyServlet(this);
|
||||
proxyContext.destroy();
|
||||
proxyContext = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HttpServlet#service(ServletRequest, ServletResponse)
|
||||
*/
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
process(req, resp, null);
|
||||
}
|
||||
|
||||
protected void process(HttpServletRequest req, HttpServletResponse resp, FilterChain filterChain) throws ServletException, IOException {
|
||||
proxyContext.initializeServletPath(req, filterChain);
|
||||
String alias = HttpServletRequestAdaptor.getDispatchPathInfo(req, filterChain);
|
||||
if (alias == null)
|
||||
alias = "/"; //$NON-NLS-1$
|
||||
|
||||
// perfect match
|
||||
if (processAlias(req, resp, alias, null, filterChain))
|
||||
return;
|
||||
|
||||
String extensionAlias = findExtensionAlias(alias);
|
||||
alias = alias.substring(0, alias.lastIndexOf('/'));
|
||||
|
||||
// longest path match
|
||||
while (alias.length() != 0) {
|
||||
if (processAlias(req, resp, alias, extensionAlias, filterChain))
|
||||
return;
|
||||
alias = alias.substring(0, alias.lastIndexOf('/'));
|
||||
}
|
||||
|
||||
// default handler match
|
||||
if (extensionAlias != null)
|
||||
extensionAlias = extensionAlias.substring(1); // remove the leading '/'
|
||||
if (processAlias(req, resp, "/", extensionAlias, filterChain)) //Handle '/' aliases //$NON-NLS-1$
|
||||
return;
|
||||
|
||||
// Cannot find the Servlet or Filter from the OSGi registry services :
|
||||
if (filterChain != null) {
|
||||
// Delegate the HTTP request to the Web server container.
|
||||
filterChain.doFilter(req, resp);
|
||||
|
||||
} else {
|
||||
// Send HTTP 4040 Error.
|
||||
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "ProxyServlet: " + req.getRequestURI()); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private String findExtensionAlias(String alias) {
|
||||
String lastSegment = alias.substring(alias.lastIndexOf('/') + 1);
|
||||
int dot = lastSegment.lastIndexOf('.');
|
||||
if (dot == -1)
|
||||
return null;
|
||||
String extension = lastSegment.substring(dot + 1);
|
||||
if (extension.length() == 0)
|
||||
return null;
|
||||
return "/*." + extension; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private boolean processAlias(HttpServletRequest req, HttpServletResponse resp, String alias, String extensionAlias, FilterChain filterChain) throws ServletException, IOException {
|
||||
ServletRegistration registration = null;
|
||||
List matchingFilterRegistrations = Collections.EMPTY_LIST;
|
||||
String dispatchPathInfo = HttpServletRequestAdaptor.getDispatchPathInfo(req, filterChain);
|
||||
synchronized (this) {
|
||||
if (extensionAlias == null)
|
||||
registration = (ServletRegistration) servletRegistrations.get(alias);
|
||||
else {
|
||||
registration = (ServletRegistration) servletRegistrations.get(alias + extensionAlias);
|
||||
if (registration != null) {
|
||||
// for regular ServletRegistrations extensions should be handled on the full alias
|
||||
if (!(registration.getServlet() instanceof ResourceServlet))
|
||||
alias = HttpServletRequestAdaptor.getDispatchPathInfo(req, filterChain);
|
||||
} else
|
||||
registration = (ServletRegistration) servletRegistrations.get(alias);
|
||||
}
|
||||
if (registration != null) {
|
||||
registration.addReference();
|
||||
if (!filterRegistrations.isEmpty()) {
|
||||
matchingFilterRegistrations = new ArrayList();
|
||||
for (Iterator it = filterRegistrations.values().iterator(); it.hasNext();) {
|
||||
FilterRegistration filterRegistration = (FilterRegistration) it.next();
|
||||
if (filterRegistration.matches(dispatchPathInfo)) {
|
||||
matchingFilterRegistrations.add(filterRegistration);
|
||||
filterRegistration.addReference();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (registration != null) {
|
||||
try {
|
||||
HttpServletRequest wrappedRequest = new HttpServletRequestAdaptor(req, alias, registration.getServlet(), filterChain);
|
||||
if (matchingFilterRegistrations.isEmpty()) {
|
||||
registration.service(wrappedRequest, resp);
|
||||
} else {
|
||||
Collections.sort(matchingFilterRegistrations);
|
||||
FilterChain chain = new FilterChainImpl(matchingFilterRegistrations, registration);
|
||||
chain.doFilter(wrappedRequest, resp);
|
||||
}
|
||||
} finally {
|
||||
registration.removeReference();
|
||||
for (Iterator it = matchingFilterRegistrations.iterator(); it.hasNext();) {
|
||||
FilterRegistration filterRegistration = (FilterRegistration) it.next();
|
||||
filterRegistration.removeReference();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Effective unregistration of servlet and resources as defined in HttpService#unregister()
|
||||
synchronized void unregister(String alias, boolean destroy) {
|
||||
ServletRegistration removedRegistration = (ServletRegistration) servletRegistrations.remove(alias);
|
||||
if (removedRegistration != null) {
|
||||
registeredServlets.remove(removedRegistration.getServlet());
|
||||
try {
|
||||
if (destroy)
|
||||
removedRegistration.destroy();
|
||||
} finally {
|
||||
proxyContext.destroyContextAttributes(removedRegistration.getHttpContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Effective registration of the servlet as defined HttpService#registerServlet()
|
||||
synchronized void registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext httpContext) throws ServletException, NamespaceException {
|
||||
checkAlias(alias);
|
||||
if (servletRegistrations.containsKey(alias))
|
||||
throw new NamespaceException("The alias '" + alias + "' is already in use."); //$NON-NLS-1$//$NON-NLS-2$
|
||||
|
||||
if (servlet == null)
|
||||
throw new IllegalArgumentException("Servlet cannot be null"); //$NON-NLS-1$
|
||||
|
||||
if (registeredServlets.contains(servlet))
|
||||
throw new ServletException("This servlet has already been registered."); //$NON-NLS-1$
|
||||
|
||||
ServletRegistration registration = new ServletRegistration(servlet, httpContext);
|
||||
ServletContext wrappedServletContext = new ServletContextAdaptor(proxyContext, getServletContext(), httpContext, AccessController.getContext());
|
||||
ServletConfig servletConfig = new ServletConfigImpl(servlet, initparams, wrappedServletContext);
|
||||
|
||||
boolean initialized = false;
|
||||
proxyContext.createContextAttributes(httpContext);
|
||||
try {
|
||||
registration.init(servletConfig);
|
||||
initialized = true;
|
||||
} finally {
|
||||
if (!initialized)
|
||||
proxyContext.destroyContextAttributes(httpContext);
|
||||
}
|
||||
registeredServlets.add(servlet);
|
||||
servletRegistrations.put(alias, registration);
|
||||
}
|
||||
|
||||
//Effective registration of the resources as defined HttpService#registerResources()
|
||||
synchronized void registerResources(String alias, String name, HttpContext httpContext) throws NamespaceException {
|
||||
checkName(name);
|
||||
Servlet resourceServlet = new ResourceServlet(name, httpContext, AccessController.getContext());
|
||||
try {
|
||||
registerServlet(alias, resourceServlet, null, httpContext);
|
||||
} catch (ServletException e) {
|
||||
throw new IllegalStateException("Unexpected ServletException throw when registering resources at alias " + alias + "."); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
||||
private void checkName(String name) {
|
||||
if (name == null)
|
||||
throw new IllegalArgumentException("Name cannot be null"); //$NON-NLS-1$
|
||||
|
||||
if (name.endsWith("/") && !name.equals("/")) //$NON-NLS-1$ //$NON-NLS-2$
|
||||
throw new IllegalArgumentException("Invalid Name '" + name + "'"); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
|
||||
private void checkAlias(String alias) {
|
||||
if (alias == null)
|
||||
throw new IllegalArgumentException("Alias cannot be null"); //$NON-NLS-1$
|
||||
|
||||
if (!alias.startsWith("/") || (alias.endsWith("/") && !alias.equals("/"))) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
|
||||
throw new IllegalArgumentException("Invalid alias '" + alias + "'"); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
|
||||
public synchronized void unregisterFilter(Filter filter, boolean destroy) {
|
||||
FilterRegistration removedRegistration = (FilterRegistration) filterRegistrations.remove(filter);
|
||||
if (removedRegistration != null) {
|
||||
try {
|
||||
if (destroy)
|
||||
removedRegistration.destroy();
|
||||
} finally {
|
||||
proxyContext.destroyContextAttributes(removedRegistration.getHttpContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void registerFilter(String alias, Filter filter, Dictionary initparams, HttpContext httpContext) throws ServletException {
|
||||
checkAlias(alias);
|
||||
if (filter == null)
|
||||
throw new IllegalArgumentException("Filter cannot be null"); //$NON-NLS-1$
|
||||
|
||||
if (filterRegistrations.containsKey(filter))
|
||||
throw new ServletException("This filter has already been registered."); //$NON-NLS-1$
|
||||
|
||||
int filterPriority = findFilterPriority(initparams);
|
||||
FilterRegistration registration = new FilterRegistration(filter, httpContext, alias, filterPriority);
|
||||
ServletContext wrappedServletContext = new ServletContextAdaptor(proxyContext, getServletContext(), httpContext, AccessController.getContext());
|
||||
FilterConfig filterConfig = new FilterConfigImpl(filter, initparams, wrappedServletContext);
|
||||
|
||||
boolean initialized = false;
|
||||
proxyContext.createContextAttributes(httpContext);
|
||||
try {
|
||||
registration.init(filterConfig);
|
||||
initialized = true;
|
||||
} finally {
|
||||
if (!initialized)
|
||||
proxyContext.destroyContextAttributes(httpContext);
|
||||
}
|
||||
filterRegistrations.put(filter, registration);
|
||||
}
|
||||
|
||||
private int findFilterPriority(Dictionary initparams) {
|
||||
if (initparams == null)
|
||||
return 0;
|
||||
String filterPriority = (String) initparams.get("filter-priority"); //$NON-NLS-1$
|
||||
if (filterPriority == null)
|
||||
return 0;
|
||||
|
||||
try {
|
||||
int result = Integer.parseInt(filterPriority);
|
||||
if (result >= -1000 && result <= 1000)
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
// fall through
|
||||
}
|
||||
throw new IllegalArgumentException("filter-priority must be an integer between -1000 and 1000 but was: " + filterPriority); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
ServletConfig servletConfig = new ServletConfigAdaptor(filterConfig);
|
||||
this.init(servletConfig);
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest req = (HttpServletRequest) request;
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
process(req, resp, chain);
|
||||
}
|
||||
|
||||
private static class ServletConfigAdaptor implements ServletConfig {
|
||||
|
||||
private FilterConfig filterConfig;
|
||||
|
||||
public ServletConfigAdaptor(FilterConfig filterConfig) {
|
||||
this.filterConfig = filterConfig;
|
||||
}
|
||||
|
||||
public String getInitParameter(String arg0) {
|
||||
return filterConfig.getInitParameter(arg0);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return filterConfig.getInitParameterNames();
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return filterConfig.getServletContext();
|
||||
}
|
||||
|
||||
public String getServletName() {
|
||||
return filterConfig.getFilterName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
public abstract class Registration {
|
||||
|
||||
protected int referenceCount;
|
||||
|
||||
public synchronized void addReference() {
|
||||
++referenceCount;
|
||||
}
|
||||
|
||||
public synchronized void removeReference() {
|
||||
--referenceCount;
|
||||
if (referenceCount == 0) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void destroy() {
|
||||
boolean interrupted = false;
|
||||
try {
|
||||
while (referenceCount != 0) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
// wait until the servlet is inactive but save the interrupted status
|
||||
interrupted = true;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (interrupted)
|
||||
Thread.currentThread().interrupt(); //restore the interrupted state
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.*;
|
||||
|
||||
//This class unwraps the request so it can be processed by the underlying servlet container.
|
||||
public class RequestDispatcherAdaptor implements RequestDispatcher {
|
||||
|
||||
private RequestDispatcher requestDispatcher;
|
||||
|
||||
public RequestDispatcherAdaptor(RequestDispatcher requestDispatcher) {
|
||||
this.requestDispatcher = requestDispatcher;
|
||||
}
|
||||
|
||||
public void forward(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
|
||||
if (req instanceof HttpServletRequestAdaptor)
|
||||
req = ((HttpServletRequestAdaptor) req).getRequest();
|
||||
|
||||
requestDispatcher.forward(req, resp);
|
||||
}
|
||||
|
||||
public void include(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
|
||||
if (req instanceof HttpServletRequestAdaptor)
|
||||
req = ((HttpServletRequestAdaptor) req).getRequest();
|
||||
|
||||
requestDispatcher.include(req, resp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005-2007 Cognos Incorporated, IBM Corporation and others
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
* Angelo Zerr <angelo.zerr@gmail.com> - give the capability to use resources (JSP, HTML, Servlet...)
|
||||
* from the Bridge webapp with HTTP Filter.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.*;
|
||||
import javax.servlet.http.*;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
public class ResourceServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 3586876493076122102L;
|
||||
private static final String LAST_MODIFIED = "Last-Modified"; //$NON-NLS-1$
|
||||
private static final String IF_MODIFIED_SINCE = "If-Modified-Since"; //$NON-NLS-1$
|
||||
private static final String IF_NONE_MATCH = "If-None-Match"; //$NON-NLS-1$
|
||||
private static final String ETAG = "ETag"; //$NON-NLS-1$
|
||||
|
||||
private String internalName;
|
||||
HttpContext httpContext;
|
||||
private AccessControlContext acc;
|
||||
|
||||
public ResourceServlet(String internalName, HttpContext context, AccessControlContext acc) {
|
||||
this.internalName = internalName;
|
||||
if (internalName.equals("/")) { //$NON-NLS-1$
|
||||
this.internalName = ""; //$NON-NLS-1$
|
||||
}
|
||||
this.httpContext = context;
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
public void service(HttpServletRequest req, final HttpServletResponse resp) throws IOException {
|
||||
String method = req.getMethod();
|
||||
if (method.equals("GET") || method.equals("POST") || method.equals("HEAD")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||
String pathInfo = HttpServletRequestAdaptor.getDispatchPathInfo(req, null);
|
||||
if (pathInfo == null)
|
||||
pathInfo = ""; //$NON-NLS-1$
|
||||
String resourcePath = internalName + pathInfo;
|
||||
URL resourceURL = httpContext.getResource(resourcePath);
|
||||
if (resourceURL != null)
|
||||
writeResource(req, resp, resourcePath, resourceURL);
|
||||
else
|
||||
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "ProxyServlet: " + req.getRequestURI()); //$NON-NLS-1$
|
||||
} else {
|
||||
resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeResource(final HttpServletRequest req, final HttpServletResponse resp, final String resourcePath, final URL resourceURL) throws IOException {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
|
||||
public Object run() throws Exception {
|
||||
URLConnection connection = resourceURL.openConnection();
|
||||
long lastModified = connection.getLastModified();
|
||||
int contentLength = connection.getContentLength();
|
||||
|
||||
String etag = null;
|
||||
if (lastModified != -1 && contentLength != -1)
|
||||
etag = "W/\"" + contentLength + "-" + lastModified + "\""; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
|
||||
|
||||
// Check for cache revalidation.
|
||||
// We should prefer ETag validation as the guarantees are stronger and all HTTP 1.1 clients should be using it
|
||||
String ifNoneMatch = req.getHeader(IF_NONE_MATCH);
|
||||
if (ifNoneMatch != null && etag != null && ifNoneMatch.indexOf(etag) != -1) {
|
||||
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
long ifModifiedSince = req.getDateHeader(IF_MODIFIED_SINCE);
|
||||
// for purposes of comparison we add 999 to ifModifiedSince since the fidelity
|
||||
// of the IMS header generally doesn't include milli-seconds
|
||||
if (ifModifiedSince > -1 && lastModified > 0 && lastModified <= (ifModifiedSince + 999)) {
|
||||
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
// return the full contents regularly
|
||||
if (contentLength != -1)
|
||||
resp.setContentLength(contentLength);
|
||||
|
||||
String contentType = httpContext.getMimeType(resourcePath);
|
||||
if (contentType == null)
|
||||
contentType = getServletConfig().getServletContext().getMimeType(resourcePath);
|
||||
|
||||
if (contentType != null)
|
||||
resp.setContentType(contentType);
|
||||
|
||||
if (lastModified > 0)
|
||||
resp.setDateHeader(LAST_MODIFIED, lastModified);
|
||||
|
||||
if (etag != null)
|
||||
resp.setHeader(ETAG, etag);
|
||||
|
||||
if (contentLength != 0) {
|
||||
// open the input stream
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = connection.getInputStream();
|
||||
// write the resource
|
||||
try {
|
||||
OutputStream os = resp.getOutputStream();
|
||||
int writtenContentLength = writeResourceToOutputStream(is, os);
|
||||
if (contentLength == -1 || contentLength != writtenContentLength)
|
||||
resp.setContentLength(writtenContentLength);
|
||||
} catch (IllegalStateException e) { // can occur if the response output is already open as a Writer
|
||||
Writer writer = resp.getWriter();
|
||||
writeResourceToWriter(is, writer);
|
||||
// Since ContentLength is a measure of the number of bytes contained in the body
|
||||
// of a message when we use a Writer we lose control of the exact byte count and
|
||||
// defer the problem to the Servlet Engine's Writer implementation.
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
// FileNotFoundException may indicate the following scenarios
|
||||
// - url is a directory
|
||||
// - url is not accessible
|
||||
sendError(resp, HttpServletResponse.SC_FORBIDDEN);
|
||||
} catch (SecurityException e) {
|
||||
// SecurityException may indicate the following scenarios
|
||||
// - url is not accessible
|
||||
sendError(resp, HttpServletResponse.SC_FORBIDDEN);
|
||||
} finally {
|
||||
if (is != null)
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (IOException) e.getException();
|
||||
}
|
||||
}
|
||||
|
||||
void sendError(final HttpServletResponse resp, int sc) throws IOException {
|
||||
|
||||
try {
|
||||
// we need to reset headers for 302 and 403
|
||||
resp.reset();
|
||||
resp.sendError(sc);
|
||||
} catch (IllegalStateException e) {
|
||||
// this could happen if the response has already been committed
|
||||
}
|
||||
}
|
||||
|
||||
int writeResourceToOutputStream(InputStream is, OutputStream os) throws IOException {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead = is.read(buffer);
|
||||
int writtenContentLength = 0;
|
||||
while (bytesRead != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
writtenContentLength += bytesRead;
|
||||
bytesRead = is.read(buffer);
|
||||
}
|
||||
return writtenContentLength;
|
||||
}
|
||||
|
||||
void writeResourceToWriter(InputStream is, Writer writer) throws IOException {
|
||||
Reader reader = new InputStreamReader(is);
|
||||
try {
|
||||
char[] buffer = new char[8192];
|
||||
int charsRead = reader.read(buffer);
|
||||
while (charsRead != -1) {
|
||||
writer.write(buffer, 0, charsRead);
|
||||
charsRead = reader.read(buffer);
|
||||
}
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
reader.close(); // will also close input stream
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
|
||||
public class ServletConfigImpl implements ServletConfig {
|
||||
|
||||
private static final Dictionary EMPTY_PARAMS = new Hashtable(0);
|
||||
private static final String SERVLET_NAME = "servlet-name"; //$NON-NLS-1$
|
||||
private Servlet servlet;
|
||||
private Dictionary initparams;
|
||||
private ServletContext servletContext;
|
||||
|
||||
public ServletConfigImpl(Servlet servlet, Dictionary initparams, ServletContext servletContext) {
|
||||
this.servlet = servlet;
|
||||
this.initparams = (initparams != null) ? initparams : EMPTY_PARAMS;
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see javax.servlet.ServletConfig#getServletName()
|
||||
*
|
||||
* The OSGi Http Service does not specify a way to set a servlet name at the API level. This
|
||||
* implementation will try to use the value of the "servlet-name" initial parameter if available.
|
||||
*/
|
||||
public String getServletName() {
|
||||
String servletName = (String) initparams.get(SERVLET_NAME);
|
||||
return (servletName != null) ? servletName : servlet.getClass().getName();
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return servletContext;
|
||||
}
|
||||
|
||||
public String getInitParameter(String name) {
|
||||
return (String) initparams.get(name);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return initparams.keys();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
public class ServletContextAdaptor implements ServletContext {
|
||||
|
||||
private ServletContext servletContext;
|
||||
HttpContext httpContext;
|
||||
private AccessControlContext acc;
|
||||
private ProxyContext proxyContext;
|
||||
|
||||
public ServletContextAdaptor(ProxyContext proxyContext, ServletContext servletContext, HttpContext httpContext, AccessControlContext acc) {
|
||||
this.servletContext = servletContext;
|
||||
this.httpContext = httpContext;
|
||||
this.acc = acc;
|
||||
this.proxyContext = proxyContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
|
||||
*
|
||||
* This method was added in the Servlet 2.3 API however the OSGi HttpService currently does not provide
|
||||
* support for this method in the HttpContext interface. To support "getResourcePaths(...) this
|
||||
* implementation uses reflection to check for and then call the associated HttpContext.getResourcePaths(...)
|
||||
* method opportunistically. Null is returned if the method is not present or fails.
|
||||
*/
|
||||
public Set getResourcePaths(String name) {
|
||||
if (name == null || !name.startsWith("/")) //$NON-NLS-1$
|
||||
return null;
|
||||
try {
|
||||
Method getResourcePathsMethod = httpContext.getClass().getMethod("getResourcePaths", new Class[] {String.class}); //$NON-NLS-1$
|
||||
if (!getResourcePathsMethod.isAccessible())
|
||||
getResourcePathsMethod.setAccessible(true);
|
||||
return (Set) getResourcePathsMethod.invoke(httpContext, new Object[] {name});
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getAttribute(String attributeName) {
|
||||
Dictionary attributes = proxyContext.getContextAttributes(httpContext);
|
||||
return attributes.get(attributeName);
|
||||
}
|
||||
|
||||
public Enumeration getAttributeNames() {
|
||||
Dictionary attributes = proxyContext.getContextAttributes(httpContext);
|
||||
return attributes.keys();
|
||||
}
|
||||
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
Dictionary attributes = proxyContext.getContextAttributes(httpContext);
|
||||
attributes.put(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
public void removeAttribute(String attributeName) {
|
||||
Dictionary attributes = proxyContext.getContextAttributes(httpContext);
|
||||
attributes.remove(attributeName);
|
||||
}
|
||||
|
||||
public String getMimeType(String name) {
|
||||
String mimeType = httpContext.getMimeType(name);
|
||||
return (mimeType != null) ? mimeType : servletContext.getMimeType(name);
|
||||
}
|
||||
|
||||
public URL getResource(final String name) {
|
||||
try {
|
||||
return (URL) AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
return httpContext.getResource(name);
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException e) {
|
||||
log(e.getException().getMessage(), e.getException());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
URL url = getResource(name);
|
||||
if (url != null) {
|
||||
try {
|
||||
return url.openStream();
|
||||
} catch (IOException e) {
|
||||
log("Error opening stream for resource '" + name + "'", e); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ServletContext getContext(String arg0) {
|
||||
return servletContext.getContext(arg0);
|
||||
}
|
||||
|
||||
public String getInitParameter(String arg0) {
|
||||
return servletContext.getInitParameter(arg0);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return servletContext.getInitParameterNames();
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
return servletContext.getMajorVersion();
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
return servletContext.getMinorVersion();
|
||||
}
|
||||
|
||||
public RequestDispatcher getNamedDispatcher(String arg0) {
|
||||
return new RequestDispatcherAdaptor(servletContext.getNamedDispatcher(arg0));
|
||||
}
|
||||
|
||||
public String getRealPath(String arg0) {
|
||||
return servletContext.getRealPath(arg0);
|
||||
}
|
||||
|
||||
public RequestDispatcher getRequestDispatcher(String arg0) {
|
||||
return new RequestDispatcherAdaptor(servletContext.getRequestDispatcher(proxyContext.getServletPath() + arg0));
|
||||
}
|
||||
|
||||
public String getServerInfo() {
|
||||
return servletContext.getServerInfo();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public Servlet getServlet(String arg0) throws ServletException {
|
||||
return servletContext.getServlet(arg0);
|
||||
}
|
||||
|
||||
public String getServletContextName() {
|
||||
return servletContext.getServletContextName();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public Enumeration getServletNames() {
|
||||
return servletContext.getServletNames();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public Enumeration getServlets() {
|
||||
return servletContext.getServlets();
|
||||
}
|
||||
|
||||
/**@deprecated*/
|
||||
public void log(Exception arg0, String arg1) {
|
||||
servletContext.log(arg0, arg1);
|
||||
}
|
||||
|
||||
public void log(String arg0, Throwable arg1) {
|
||||
servletContext.log(arg0, arg1);
|
||||
}
|
||||
|
||||
public void log(String arg0) {
|
||||
servletContext.log(arg0);
|
||||
}
|
||||
|
||||
// Added in Servlet 2.5
|
||||
public String getContextPath() {
|
||||
try {
|
||||
Method getContextPathMethod = servletContext.getClass().getMethod("getContextPath", null); //$NON-NLS-1$
|
||||
return (String) getContextPathMethod.invoke(servletContext, null) + proxyContext.getServletPath();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005-2007 Cognos Incorporated, IBM Corporation and others
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servlet.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
//This class wraps the servlet object registered in the HttpService.registerServlet call, to manage the context classloader when handleRequests are being asked.
|
||||
public class ServletRegistration extends Registration {
|
||||
|
||||
private Servlet servlet; //The actual servlet object registered against the http service. All requests will eventually be delegated to it.
|
||||
private HttpContext httpContext; //The context used during the registration of the servlet
|
||||
private ClassLoader registeredContextClassLoader;
|
||||
|
||||
public ServletRegistration(Servlet servlet, HttpContext context) {
|
||||
this.servlet = servlet;
|
||||
this.httpContext = context;
|
||||
registeredContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
|
||||
super.destroy();
|
||||
servlet.destroy();
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
//Delegate the init call to the actual servlet
|
||||
public void init(ServletConfig servletConfig) throws ServletException {
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
|
||||
servlet.init(servletConfig);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
//Delegate the handling of the request to the actual servlet
|
||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
|
||||
if (httpContext.handleSecurity(req, resp))
|
||||
servlet.service(req, resp);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
public Servlet getServlet() {
|
||||
return servlet;
|
||||
}
|
||||
|
||||
public HttpContext getHttpContext() {
|
||||
return httpContext;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.adempiere.eclipse.equinox.http.servletbridge</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,8 @@
|
|||
#Fri Dec 24 14:43:16 MYT 2010
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,4 @@
|
|||
#Fri Dec 24 14:43:16 MYT 2010
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
|
@ -0,0 +1,18 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
|
||||
Bundle-Name: %bundleName
|
||||
Bundle-SymbolicName: org.adempiere.eclipse.equinox.http.servletbridge;singleton:=true
|
||||
Eclipse-SourceReferences: scm:cvs:pserver:dev.eclipse.org:/cvsroot/rt:
|
||||
org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.http.serv
|
||||
letbridge;tag=v20100503
|
||||
Bundle-Activator: org.eclipse.equinox.http.servletbridge.internal.Acti
|
||||
vator
|
||||
Bundle-Version: 1.0.200.v20100503
|
||||
Import-Package: javax.servlet;version="2.3",javax.servlet.http;version
|
||||
="2.3",org.eclipse.equinox.http.servlet;version="1.0.0",org.eclipse.e
|
||||
quinox.servletbridge;version="1.0.0",org.osgi.framework;version="1.3.
|
||||
0",org.osgi.service.http;version="1.2.0"
|
||||
Bundle-ManifestVersion: 2
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
|
||||
<title>About</title>
|
||||
</head>
|
||||
<body lang="EN-US">
|
||||
<h2>About This Content</h2>
|
||||
|
||||
<p>January 30, 2007</p>
|
||||
<h3>License</h3>
|
||||
|
||||
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
|
||||
indicated below, the Content is provided to you under the terms and conditions of the
|
||||
Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
|
||||
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
|
||||
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||
|
||||
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
|
||||
being redistributed by another party ("Redistributor") and different terms and conditions may
|
||||
apply to your use of any object code in the Content. Check the Redistributor's license that was
|
||||
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
|
||||
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
|
||||
and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
|
@ -0,0 +1,4 @@
|
|||
##Source Bundle Localization
|
||||
#Thu Jun 24 08:29:00 EDT 2010
|
||||
bundleName=Servletbridge Http Service Source
|
||||
providerName=Eclipse.org - Equinox
|
|
@ -0,0 +1,32 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.http.servletbridge.internal;
|
||||
|
||||
import org.eclipse.equinox.http.servlet.HttpServiceServlet;
|
||||
import org.eclipse.equinox.servletbridge.BridgeServlet;
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
|
||||
private HttpServiceServlet httpServiceServlet;
|
||||
|
||||
public void start(BundleContext context) throws Exception {
|
||||
httpServiceServlet = new HttpServiceServlet();
|
||||
BridgeServlet.registerServletDelegate(httpServiceServlet);
|
||||
}
|
||||
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
BridgeServlet.unregisterServletDelegate(httpServiceServlet);
|
||||
httpServiceServlet = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.adempiere.eclipse.equinox.servletbridge</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,8 @@
|
|||
#Fri Dec 24 14:44:01 MYT 2010
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,4 @@
|
|||
#Fri Dec 24 14:44:01 MYT 2010
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
|
@ -0,0 +1,14 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
|
||||
Bundle-Name: %bundleName
|
||||
Bundle-SymbolicName: org.adempiere.eclipse.equinox.servletbridge;singleton:=true
|
||||
Eclipse-SourceReferences: scm:cvs:pserver:dev.eclipse.org:/cvsroot/rt:
|
||||
org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.servletbr
|
||||
idge;tag=v20100503
|
||||
Bundle-Version: 1.2.0.v20100503
|
||||
Export-Package: org.eclipse.equinox.servletbridge;version="1.1.0"
|
||||
Import-Package: javax.servlet;version="2.3.0",javax.servlet.http;versi
|
||||
on="2.3.0"
|
||||
Bundle-ManifestVersion: 2
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
|
||||
<title>About</title>
|
||||
</head>
|
||||
<body lang="EN-US">
|
||||
<h2>About This Content</h2>
|
||||
|
||||
<p>January 30, 2007</p>
|
||||
<h3>License</h3>
|
||||
|
||||
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
|
||||
indicated below, the Content is provided to you under the terms and conditions of the
|
||||
Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
|
||||
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
|
||||
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||
|
||||
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
|
||||
being redistributed by another party ("Redistributor") and different terms and conditions may
|
||||
apply to your use of any object code in the Content. Check the Redistributor's license that was
|
||||
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
|
||||
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
|
||||
and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
|
@ -0,0 +1,4 @@
|
|||
##Source Bundle Localization
|
||||
#Thu Jun 24 08:29:00 EDT 2010
|
||||
bundleName=Servletbridge Source
|
||||
providerName=Eclipse.org - Equinox
|
|
@ -0,0 +1,89 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Angelo Zerr and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Angelo Zerr <angelo.zerr@gmail.com> - give the capability to use resources (JSP, HTML, Servlet...)
|
||||
* from the Bridge webapp with HTTP Filter.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.servletbridge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* {@link BridgeServlet} which implements HTTP {@link Filter} to declare "BridgeServlet" as an HTTP Filter (see >=2.3 Servlet spec):
|
||||
*
|
||||
* <pre>
|
||||
* <filter id="bridge">
|
||||
* <filter-name>equinoxbridgeservlet</filter-name>
|
||||
* <filter-class>org.eclipse.equinox.servletbridge.BridgeFilter</filter-class>
|
||||
* </filter>
|
||||
* ...
|
||||
* <filter-mapping>
|
||||
<filter-name>equinoxbridgeservlet</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class BridgeFilter extends BridgeServlet implements Filter {
|
||||
|
||||
private static final long serialVersionUID = 1309373924501049438L;
|
||||
|
||||
private ServletConfigAdaptor servletConfig;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
this.servletConfig = new ServletConfigAdaptor(filterConfig);
|
||||
super.init();
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest req = (HttpServletRequest) request;
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
// Call process class with FilterChain.
|
||||
super.process(req, resp, chain);
|
||||
}
|
||||
|
||||
public ServletConfig getServletConfig() {
|
||||
return servletConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Class which adapt {@link FilterConfig} to a {@link ServletConfig}.
|
||||
*
|
||||
*/
|
||||
private static class ServletConfigAdaptor implements ServletConfig {
|
||||
|
||||
private FilterConfig filterConfig;
|
||||
|
||||
public ServletConfigAdaptor(FilterConfig filterConfig) {
|
||||
this.filterConfig = filterConfig;
|
||||
}
|
||||
|
||||
public String getInitParameter(String arg0) {
|
||||
return filterConfig.getInitParameter(arg0);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return filterConfig.getInitParameterNames();
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return filterConfig.getServletContext();
|
||||
}
|
||||
|
||||
public String getServletName() {
|
||||
return filterConfig.getFilterName();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2008 Cognos Incorporated, IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Cognos Incorporated - initial API and implementation
|
||||
* IBM Corporation - bug fixes and enhancements
|
||||
* Angelo Zerr <angelo.zerr@gmail.com> - give the capability to use resources (JSP, HTML, Servlet...)
|
||||
* from the Bridge webapp with HTTP Filter.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.equinox.servletbridge;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/**
|
||||
* The BridgeServlet provides a means to bridge the servlet and OSGi
|
||||
* runtimes. This class has 3 main responsibilities:
|
||||
* 1) Control the lifecycle of the associated FrameworkLauncher in line with its own lifecycle
|
||||
* 2) Provide a servlet "hook" that allows all servlet requests to be delegated to the registered servlet
|
||||
* 3) Provide means to manually control the framework lifecycle
|
||||
*/
|
||||
public class BridgeServlet extends HttpServlet {
|
||||
|
||||
static final String INCLUDE_REQUEST_URI_ATTRIBUTE = "javax.servlet.include.request_uri"; //$NON-NLS-1$
|
||||
static final String INCLUDE_SERVLET_PATH_ATTRIBUTE = "javax.servlet.include.servlet_path"; //$NON-NLS-1$
|
||||
static final String INCLUDE_PATH_INFO_ATTRIBUTE = "javax.servlet.include.path_info"; //$NON-NLS-1$
|
||||
|
||||
private static final long serialVersionUID = 2825667412474494674L;
|
||||
private static BridgeServlet instance;
|
||||
private static HttpServlet servletDelegateInstance;
|
||||
private HttpServlet delegate;
|
||||
// true if current HttpServlet is an HTTP Filter and false otherwise.
|
||||
private boolean delegateIsFilter;
|
||||
private int delegateReferenceCount;
|
||||
|
||||
/**
|
||||
* init() is called by the Servlet Container and used to instantiate the frameworkLauncher which MUST be an instance of FrameworkLauncher.
|
||||
* After instantiating the framework init, deploy, and start are called.
|
||||
*/
|
||||
public void init() throws ServletException {
|
||||
super.init();
|
||||
setInstance(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy() is called by the Servlet Container and used to first stop and then destroy the framework.
|
||||
*/
|
||||
public void destroy() {
|
||||
setInstance(null);
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* service is called by the Servlet Container and will first determine if the request is a
|
||||
* framework control and will otherwise try to delegate to the registered servlet delegate
|
||||
*
|
||||
*/
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
process(req, resp, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search from OSGi registry the servlet, ressources... to executed according the path of the HTTP request. If no service are founded :
|
||||
* <ul>
|
||||
* <li>if {@link FilterChain} is not null : {@link FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} is called.</li>
|
||||
* <li>otherwise throw 404 error.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param req
|
||||
* @param resp
|
||||
* @param chain
|
||||
* @throws ServletException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void process(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws ServletException, IOException {
|
||||
String pathInfo = getDispatchPathInfo(req, chain);
|
||||
// Check if this is being handled by an extension mapping
|
||||
if (pathInfo == null && isExtensionMapping(req.getServletPath()))
|
||||
req = new ExtensionMappingRequest(req);
|
||||
|
||||
if (req.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE) == null) {
|
||||
} else {
|
||||
String includePathInfo = (String) req.getAttribute(INCLUDE_PATH_INFO_ATTRIBUTE);
|
||||
// Check if this is being handled by an extension mapping
|
||||
if (includePathInfo == null || includePathInfo.length() == 0) {
|
||||
String servletPath = (String) req.getAttribute(INCLUDE_SERVLET_PATH_ATTRIBUTE);
|
||||
if (isExtensionMapping(servletPath))
|
||||
req = new IncludedExtensionMappingRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
HttpServlet servletReference = acquireDelegateReference();
|
||||
if (servletReference == null) {
|
||||
// Cannot find the HttpServletService from OSGi registry services :
|
||||
if (chain != null) {
|
||||
// Delegate the HTTP request to the Web server container.
|
||||
chain.doFilter(req, resp);
|
||||
|
||||
} else {
|
||||
// Send HTTP 4040 Error.
|
||||
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "BridgeServlet: " + req.getRequestURI()); //$NON-NLS-1$
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (delegateIsFilter && chain != null) {
|
||||
((Filter) servletReference).doFilter(req, resp, chain);
|
||||
} else {
|
||||
servletReference.service(req, resp);
|
||||
}
|
||||
} finally {
|
||||
releaseDelegateReference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExtensionMapping(String servletPath) {
|
||||
if (servletPath == null)
|
||||
return false;
|
||||
|
||||
String lastSegment = servletPath;
|
||||
int lastSlash = servletPath.lastIndexOf('/');
|
||||
if (lastSlash != -1)
|
||||
lastSegment = servletPath.substring(lastSlash + 1);
|
||||
|
||||
return lastSegment.indexOf('.') != -1;
|
||||
}
|
||||
|
||||
private static synchronized void setInstance(BridgeServlet servlet) {
|
||||
if ((instance != null) && (servlet != null))
|
||||
throw new IllegalStateException("instance already set"); //$NON-NLS-1$
|
||||
instance = servlet;
|
||||
if (instance == null)
|
||||
servletDelegateInstance = null;
|
||||
else if (servletDelegateInstance != null)
|
||||
registerServletDelegate(servletDelegateInstance);
|
||||
}
|
||||
|
||||
private synchronized void releaseDelegateReference() {
|
||||
--delegateReferenceCount;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
private synchronized HttpServlet acquireDelegateReference() {
|
||||
if (delegate != null)
|
||||
++delegateReferenceCount;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* registerServletDelegate is the hook method called from inside the OSGi runtime to register
|
||||
* a servlet for which all future servlet calls will be delegated. If not null and no delegate
|
||||
* is currently registered, init(ServletConfig) will be called on the servletDelegate before
|
||||
* returning.
|
||||
* @param servletDelegate - the servlet to register for delegation
|
||||
*/
|
||||
public static synchronized void registerServletDelegate(HttpServlet servletDelegate) {
|
||||
if (instance == null) {
|
||||
servletDelegateInstance = servletDelegate;
|
||||
return;
|
||||
}
|
||||
|
||||
servletDelegateInstance = null;
|
||||
|
||||
if (servletDelegate == null)
|
||||
throw new NullPointerException("cannot register a null servlet delegate"); //$NON-NLS-1$
|
||||
|
||||
synchronized (instance) {
|
||||
if (instance.delegate != null)
|
||||
throw new IllegalStateException("A Servlet Proxy is already registered"); //$NON-NLS-1$
|
||||
|
||||
try {
|
||||
// cache the flag if HttpServlet servlet delegate is an HTTP Filter.
|
||||
instance.delegateIsFilter = (servletDelegate instanceof Filter);
|
||||
// initialize the servlet delegate.
|
||||
servletDelegate.init(instance.getServletConfig());
|
||||
} catch (ServletException e) {
|
||||
instance.getServletContext().log("Error initializing servlet delegate", e); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
instance.delegate = servletDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unregisterServletDelegate is the hook method called from inside the OSGi runtime to unregister a delegate.
|
||||
* If the servletDelegate matches the current registered delegate destroy() is called on the servletDelegate.
|
||||
* destroy() will not be called until the delegate is finished servicing any previous requests.
|
||||
* @param servletDelegate - the servlet to unregister
|
||||
*/
|
||||
public static synchronized void unregisterServletDelegate(HttpServlet servletDelegate) {
|
||||
if (instance == null) {
|
||||
// shutdown already
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (instance) {
|
||||
if (instance.delegate == null)
|
||||
throw new IllegalStateException("No servlet delegate is registered"); //$NON-NLS-1$
|
||||
|
||||
if (instance.delegate != servletDelegate)
|
||||
throw new IllegalStateException("Servlet delegate does not match registered servlet delegate"); //$NON-NLS-1$
|
||||
|
||||
HttpServlet oldProxy = instance.delegate;
|
||||
instance.delegate = null;
|
||||
instance.delegateIsFilter = false;
|
||||
while (instance.delegateReferenceCount != 0) {
|
||||
try {
|
||||
instance.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// keep waiting for all requests to finish
|
||||
}
|
||||
}
|
||||
oldProxy.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
static class ExtensionMappingRequest extends HttpServletRequestWrapper {
|
||||
|
||||
public ExtensionMappingRequest(HttpServletRequest req) {
|
||||
super(req);
|
||||
}
|
||||
|
||||
public String getPathInfo() {
|
||||
return super.getServletPath();
|
||||
}
|
||||
|
||||
public String getServletPath() {
|
||||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
static class IncludedExtensionMappingRequest extends HttpServletRequestWrapper {
|
||||
|
||||
public IncludedExtensionMappingRequest(HttpServletRequest req) {
|
||||
super(req);
|
||||
}
|
||||
|
||||
public Object getAttribute(String attributeName) {
|
||||
if (attributeName.equals(INCLUDE_SERVLET_PATH_ATTRIBUTE)) {
|
||||
return ""; //$NON-NLS-1$
|
||||
} else if (attributeName.equals(INCLUDE_PATH_INFO_ATTRIBUTE)) {
|
||||
String servletPath = (String) super.getAttribute(INCLUDE_SERVLET_PATH_ATTRIBUTE);
|
||||
return servletPath;
|
||||
}
|
||||
return super.getAttribute(attributeName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path info of the HTTP request.
|
||||
*
|
||||
* @param req
|
||||
* @param chain
|
||||
* @return the path info of the HTTP request.
|
||||
*/
|
||||
private static String getDispatchPathInfo(HttpServletRequest req, FilterChain chain) {
|
||||
// if (req.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE) != null)
|
||||
// return (String) req.getAttribute(INCLUDE_PATH_INFO_ATTRIBUTE);
|
||||
|
||||
String pathInfo = req.getPathInfo();
|
||||
if (pathInfo != null) {
|
||||
return pathInfo;
|
||||
}
|
||||
if (chain == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// HTTP Filter case, pathInfo is null, compute it by using contextPath and requestURI
|
||||
String contextPath = req.getContextPath();
|
||||
String requestURI = req.getRequestURI();
|
||||
return requestURI.substring(contextPath.length(), requestURI.length());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2009 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* The java.net.URLClassLoader class allows one to load resources from arbitrary URLs and in particular is optimized to handle
|
||||
* "jar" URLs. Unfortunately for jar files this optimization ends up holding the file open which ultimately prevents the file from
|
||||
* being deleted or update until the VM is shutdown.
|
||||
*
|
||||
* The CloseableURLClassLoader is meant to replace the URLClassLoader and provides an additional method to allow one to "close" any
|
||||
* resources left open. In the current version the CloseableURLClassLoader will only ensure the closing of jar file resources. The
|
||||
* jar handling behavior in this class will also provides a construct to allow one to turn off jar file verification in performance
|
||||
* sensitive situations where the verification us not necessary.
|
||||
*
|
||||
* also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=190279
|
||||
*/
|
||||
|
||||
package org.eclipse.equinox.servletbridge;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import java.util.jar.Attributes.Name;
|
||||
|
||||
public class CloseableURLClassLoader extends URLClassLoader {
|
||||
static final String DOT_CLASS = ".class"; //$NON-NLS-1$
|
||||
static final String BANG_SLASH = "!/"; //$NON-NLS-1$
|
||||
static final String JAR = "jar"; //$NON-NLS-1$
|
||||
|
||||
// @GuardedBy("loaders")
|
||||
final ArrayList loaders = new ArrayList(); // package private to avoid synthetic access.
|
||||
// @GuardedBy("loaders")
|
||||
private final ArrayList loaderURLs = new ArrayList(); // note: protected by loaders
|
||||
// @GuardedBy("loaders")
|
||||
boolean closed = false; // note: protected by loaders, package private to avoid synthetic access.
|
||||
|
||||
private final AccessControlContext context;
|
||||
private final boolean verifyJars;
|
||||
|
||||
private static class CloseableJarURLConnection extends JarURLConnection {
|
||||
private final JarFile jarFile;
|
||||
// @GuardedBy("this")
|
||||
private JarEntry entry;
|
||||
|
||||
public CloseableJarURLConnection(URL url, JarFile jarFile) throws MalformedURLException {
|
||||
super(url);
|
||||
this.jarFile = jarFile;
|
||||
}
|
||||
|
||||
public void connect() throws IOException {
|
||||
internalGetEntry();
|
||||
}
|
||||
|
||||
private synchronized JarEntry internalGetEntry() throws IOException {
|
||||
if (entry != null)
|
||||
return entry;
|
||||
entry = jarFile.getJarEntry(getEntryName());
|
||||
if (entry == null)
|
||||
throw new FileNotFoundException(getEntryName());
|
||||
return entry;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return jarFile.getInputStream(internalGetEntry());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IOException
|
||||
* Documented to avoid warning
|
||||
*/
|
||||
public JarFile getJarFile() throws IOException {
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
public JarEntry getJarEntry() throws IOException {
|
||||
return internalGetEntry();
|
||||
}
|
||||
}
|
||||
|
||||
private static class CloseableJarURLStreamHandler extends URLStreamHandler {
|
||||
private final JarFile jarFile;
|
||||
|
||||
public CloseableJarURLStreamHandler(JarFile jarFile) {
|
||||
this.jarFile = jarFile;
|
||||
}
|
||||
|
||||
protected URLConnection openConnection(URL u) throws IOException {
|
||||
return new CloseableJarURLConnection(u, jarFile);
|
||||
}
|
||||
|
||||
protected void parseURL(URL u, String spec, int start, int limit) {
|
||||
setURL(u, JAR, null, 0, null, null, spec.substring(start, limit), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CloseableJarFileLoader {
|
||||
private final JarFile jarFile;
|
||||
private final Manifest manifest;
|
||||
private final CloseableJarURLStreamHandler jarURLStreamHandler;
|
||||
private final String jarFileURLPrefixString;
|
||||
|
||||
public CloseableJarFileLoader(File file, boolean verify) throws IOException {
|
||||
this.jarFile = new JarFile(file, verify);
|
||||
this.manifest = jarFile.getManifest();
|
||||
this.jarURLStreamHandler = new CloseableJarURLStreamHandler(jarFile);
|
||||
this.jarFileURLPrefixString = file.toURL().toString() + BANG_SLASH;
|
||||
}
|
||||
|
||||
public URL getURL(String name) {
|
||||
if (jarFile.getEntry(name) != null)
|
||||
try {
|
||||
return new URL(JAR, null, -1, jarFileURLPrefixString + name, jarURLStreamHandler);
|
||||
} catch (MalformedURLException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Manifest getManifest() {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param urls the array of URLs to use for loading resources
|
||||
* @see URLClassLoader
|
||||
*/
|
||||
public CloseableURLClassLoader(URL[] urls) {
|
||||
this(urls, ClassLoader.getSystemClassLoader(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param urls the URLs from which to load classes and resources
|
||||
* @param parent the parent class loader used for delegation
|
||||
* @see URLClassLoader
|
||||
*/
|
||||
public CloseableURLClassLoader(URL[] urls, ClassLoader parent) {
|
||||
this(excludeFileJarURLS(urls), parent, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param urls the URLs from which to load classes and resources
|
||||
* @param parent the parent class loader used for delegation
|
||||
* @param verifyJars flag to determine if jar file verification should be performed
|
||||
* @see URLClassLoader
|
||||
*/
|
||||
public CloseableURLClassLoader(URL[] urls, ClassLoader parent, boolean verifyJars) {
|
||||
super(excludeFileJarURLS(urls), parent);
|
||||
this.context = AccessController.getContext();
|
||||
this.verifyJars = verifyJars;
|
||||
for (int i = 0; i < urls.length; i++) {
|
||||
if (isFileJarURL(urls[i])) {
|
||||
loaderURLs.add(urls[i]);
|
||||
safeAddLoader(urls[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @GuardedBy("loaders")
|
||||
private void safeAddLoader(URL url) {
|
||||
String path = url.getPath();
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
loaders.add(new CloseableJarFileLoader(file, verifyJars));
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static URL[] excludeFileJarURLS(URL[] urls) {
|
||||
ArrayList urlList = new ArrayList();
|
||||
for (int i = 0; i < urls.length; i++) {
|
||||
if (!isFileJarURL(urls[i]))
|
||||
urlList.add(urls[i]);
|
||||
}
|
||||
return (URL[]) urlList.toArray(new URL[urlList.size()]);
|
||||
}
|
||||
|
||||
private static boolean isFileJarURL(URL url) {
|
||||
if (!url.getProtocol().equals("file")) //$NON-NLS-1$
|
||||
return false;
|
||||
|
||||
String path = url.getPath();
|
||||
if (path != null && path.endsWith("/")) //$NON-NLS-1$
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.net.URLClassLoader#findClass(java.lang.String)
|
||||
*/
|
||||
protected Class findClass(final String name) throws ClassNotFoundException {
|
||||
try {
|
||||
Class clazz = (Class) AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
public Object run() throws ClassNotFoundException {
|
||||
String resourcePath = name.replace('.', '/') + DOT_CLASS;
|
||||
CloseableJarFileLoader loader = null;
|
||||
URL resourceURL = null;
|
||||
synchronized (loaders) {
|
||||
if (closed)
|
||||
return null;
|
||||
for (Iterator iterator = loaders.iterator(); iterator.hasNext();) {
|
||||
loader = (CloseableJarFileLoader) iterator.next();
|
||||
resourceURL = loader.getURL(resourcePath);
|
||||
if (resourceURL != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (resourceURL != null) {
|
||||
try {
|
||||
return defineClass(name, resourceURL, loader.getManifest());
|
||||
} catch (IOException e) {
|
||||
throw new ClassNotFoundException(name, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, context);
|
||||
if (clazz != null)
|
||||
return clazz;
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (ClassNotFoundException) e.getException();
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
|
||||
// package private to avoid synthetic access.
|
||||
Class defineClass(String name, URL resourceURL, Manifest manifest) throws IOException {
|
||||
JarURLConnection connection = (JarURLConnection) resourceURL.openConnection();
|
||||
int lastDot = name.lastIndexOf('.');
|
||||
if (lastDot != -1) {
|
||||
String packageName = name.substring(0, lastDot + 1);
|
||||
Package pkg = getPackage(packageName);
|
||||
if (pkg != null) {
|
||||
checkForSealedPackage(pkg, packageName, manifest, connection.getJarFileURL());
|
||||
} else {
|
||||
definePackage(packageName, manifest, connection.getJarFileURL());
|
||||
}
|
||||
}
|
||||
JarEntry entry = connection.getJarEntry();
|
||||
byte[] bytes = new byte[(int) entry.getSize()];
|
||||
DataInputStream is = null;
|
||||
try {
|
||||
is = new DataInputStream(connection.getInputStream());
|
||||
is.readFully(bytes, 0, bytes.length);
|
||||
CodeSource cs = new CodeSource(connection.getJarFileURL(), entry.getCertificates());
|
||||
return defineClass(name, bytes, 0, bytes.length, cs);
|
||||
} finally {
|
||||
if (is != null)
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForSealedPackage(Package pkg, String packageName, Manifest manifest, URL jarFileURL) {
|
||||
if (pkg.isSealed() && !pkg.isSealed(jarFileURL))
|
||||
throw new SecurityException("The package '" + packageName + "' was previously loaded and is already sealed."); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
String entryPath = packageName.replace('.', '/') + "/"; //$NON-NLS-1$
|
||||
Attributes entryAttributes = manifest.getAttributes(entryPath);
|
||||
String sealed = null;
|
||||
if (entryAttributes != null)
|
||||
sealed = entryAttributes.getValue(Name.SEALED);
|
||||
|
||||
if (sealed == null) {
|
||||
Attributes mainAttributes = manifest.getMainAttributes();
|
||||
if (mainAttributes != null)
|
||||
sealed = mainAttributes.getValue(Name.SEALED);
|
||||
}
|
||||
if (Boolean.valueOf(sealed).booleanValue())
|
||||
throw new SecurityException("The package '" + packageName + "' was previously loaded unsealed. Cannot seal package."); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.net.URLClassLoader#findResource(java.lang.String)
|
||||
*/
|
||||
public URL findResource(final String name) {
|
||||
URL url = (URL) AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
synchronized (loaders) {
|
||||
if (closed)
|
||||
return null;
|
||||
for (Iterator iterator = loaders.iterator(); iterator.hasNext();) {
|
||||
CloseableJarFileLoader loader = (CloseableJarFileLoader) iterator.next();
|
||||
URL resourceURL = loader.getURL(name);
|
||||
if (resourceURL != null)
|
||||
return resourceURL;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, context);
|
||||
if (url != null)
|
||||
return url;
|
||||
return super.findResource(name);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.net.URLClassLoader#findResources(java.lang.String)
|
||||
*/
|
||||
public Enumeration findResources(final String name) throws IOException {
|
||||
final List resources = new ArrayList();
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
synchronized (loaders) {
|
||||
if (closed)
|
||||
return null;
|
||||
for (Iterator iterator = loaders.iterator(); iterator.hasNext();) {
|
||||
CloseableJarFileLoader loader = (CloseableJarFileLoader) iterator.next();
|
||||
URL resourceURL = loader.getURL(name);
|
||||
if (resourceURL != null)
|
||||
resources.add(resourceURL);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, context);
|
||||
Enumeration e = super.findResources(name);
|
||||
while (e.hasMoreElements())
|
||||
resources.add(e.nextElement());
|
||||
|
||||
return Collections.enumeration(resources);
|
||||
}
|
||||
|
||||
/**
|
||||
* The "close" method is called when the class loader is no longer needed and we should close any open resources.
|
||||
* In particular this method will close the jar files associated with this class loader.
|
||||
*/
|
||||
public void close() {
|
||||
synchronized (loaders) {
|
||||
if (closed)
|
||||
return;
|
||||
for (Iterator iterator = loaders.iterator(); iterator.hasNext();) {
|
||||
CloseableJarFileLoader loader = (CloseableJarFileLoader) iterator.next();
|
||||
loader.close();
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.net.URLClassLoader#addURL(java.net.URL)
|
||||
*/
|
||||
protected void addURL(URL url) {
|
||||
synchronized (loaders) {
|
||||
if (isFileJarURL(url)) {
|
||||
if (closed)
|
||||
throw new IllegalStateException("Cannot add url. CloseableURLClassLoader is closed."); //$NON-NLS-1$
|
||||
loaderURLs.add(url);
|
||||
safeAddLoader(url);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.addURL(url);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.net.URLClassLoader#getURLs()
|
||||
*/
|
||||
public URL[] getURLs() {
|
||||
List result = new ArrayList();
|
||||
synchronized (loaders) {
|
||||
result.addAll(loaderURLs);
|
||||
}
|
||||
result.addAll(Arrays.asList(super.getURLs()));
|
||||
return (URL[]) result.toArray(new URL[result.size()]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue