You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@abdera.apache.org by jm...@apache.org on 2008/02/01 03:34:10 UTC
svn commit: r617333 - in /incubator/abdera/java/trunk/security: ./
src/main/java/org/apache/abdera/security/util/filters/
src/main/java/org/apache/abdera/security/util/servlet/
src/test/java/org/apache/abdera/test/security/filter/
Author: jmsnell
Date: Thu Jan 31 18:34:07 2008
New Revision: 617333
URL: http://svn.apache.org/viewvc?rev=617333&view=rev
Log:
Convert the security filters over to the new Abdera Filter api... this decouples them from the Servlet API and simplifies their implementation in some respects. Add a test case for signed responses. Will fill in test cases for the rest later
Added:
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/
- copied from r617258, incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/
incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/
incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/CustomProvider.java
incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/JettyServer.java
incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SecurityFilterTest.java
incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SimpleAdapter.java
Removed:
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SecurityFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/
Modified:
incubator/abdera/java/trunk/security/pom.xml
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AESEncryptedResponseFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedRequestFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedResponseFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedRequestFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedResponseFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedRequestFilter.java
incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedResponseFilter.java
Modified: incubator/abdera/java/trunk/security/pom.xml
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/pom.xml?rev=617333&r1=617332&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/pom.xml (original)
+++ incubator/abdera/java/trunk/security/pom.xml Thu Jan 31 18:34:07 2008
@@ -84,6 +84,12 @@
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.1.5</version>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>bouncycastle</groupId>
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AESEncryptedResponseFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AESEncryptedResponseFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AESEncryptedResponseFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AESEncryptedResponseFilter.java Thu Jan 31 18:34:07 2008
@@ -15,16 +15,15 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
+package org.apache.abdera.security.util.filters;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.RequestContext.Scope;
import org.apache.abdera.security.Encryption;
import org.apache.abdera.security.EncryptionOptions;
import org.apache.abdera.security.util.KeyHelper;
@@ -47,35 +46,35 @@
public static final String PUBLICKEY = "X-PublicKey";
- protected X509Certificate[] getCerts(ServletRequest request) {
+ protected X509Certificate[] getCerts(RequestContext request) {
return (X509Certificate[]) request.getAttribute(
+ Scope.REQUEST,
"javax.servlet.request.X509Certificate");
}
- protected PublicKey getPublicKey(ServletRequest request) {
- HttpServletRequest servletrequest = (HttpServletRequest) request;
- String header = servletrequest.getHeader(PUBLICKEY);
+ protected PublicKey getPublicKey(RequestContext request) {
+ String header = request.getHeader(PUBLICKEY);
PublicKey pkey = KeyHelper.generatePublicKey(header);
if (pkey == null) pkey = retrievePublicKey(request);
return pkey;
}
- protected boolean doEncryption(ServletRequest request, Object arg) {
+ protected boolean doEncryption(RequestContext request, Object arg) {
return arg != null && arg instanceof RSAPublicKey;
}
- protected Object initArg(ServletRequest request) {
+ protected Object initArg(RequestContext request) {
return getPublicKey(request);
}
- protected PublicKey retrievePublicKey(ServletRequest request) {
+ protected PublicKey retrievePublicKey(RequestContext request) {
X509Certificate[] cert = getCerts(request);
return cert != null ? cert[0].getPublicKey() : null;
}
protected EncryptionOptions initEncryptionOptions(
- ServletRequest request,
- ServletResponse response,
+ RequestContext request,
+ ResponseContext response,
Encryption enc,
Object arg) {
try {
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedRequestFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedRequestFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedRequestFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedRequestFilter.java Thu Jan 31 18:34:07 2008
@@ -15,31 +15,30 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
+package org.apache.abdera.security.util.filters;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
+import org.apache.abdera.parser.ParseException;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.parser.ParserOptions;
+import org.apache.abdera.protocol.server.Filter;
+import org.apache.abdera.protocol.server.FilterChain;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.context.RequestContextWrapper;
+import org.apache.abdera.security.AbderaSecurity;
import org.apache.abdera.security.Encryption;
import org.apache.abdera.security.EncryptionOptions;
-import org.apache.abdera.security.SecurityException;
public abstract class AbstractEncryptedRequestFilter
- extends SecurityFilter {
+ implements Filter {
// The methods that allow encrypted bodies
protected final List<String> methods = new ArrayList<String>();
@@ -50,6 +49,7 @@
protected AbstractEncryptedRequestFilter(String... methods) {
for (String method: methods) this.methods.add(method);
+ initProvider();
}
protected void initProvider() {}
@@ -59,69 +59,53 @@
Security.addProvider(provider);
}
- @Override
- public void init(FilterConfig config) throws ServletException {
- super.init(config);
- initProvider();
- String s = config.getInitParameter("methods");
- if (s != null && s.length() > 0) {
- this.methods.clear();
- String[] methods = s.split("\\s*,\\s*");
- for (String method : methods) this.methods.add(method);
- }
+ public ResponseContext filter(
+ RequestContext request,
+ FilterChain chain) {
+ bootstrap(request);
+ String method = request.getMethod();
+ if (methods.contains(method.toUpperCase())) {
+ return chain.next(new DecryptingRequestContextWrapper(request));
+ } else
+ return chain.next(request);
}
+
+ protected abstract void bootstrap(RequestContext request);
- @SuppressWarnings("unchecked")
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain chain)
- throws IOException,
- ServletException {
-
- bootstrap(request,response);
- HttpServletRequest req = (HttpServletRequest) request;
- String method = req.getMethod();
- if (methods.contains(method.toUpperCase())) {
- BufferedRequestWrapper wrapper =
- new BufferedRequestWrapper((HttpServletRequest) request);
+ protected abstract Object initArg(RequestContext request);
+
+ protected abstract EncryptionOptions initEncryptionOptions(
+ RequestContext request,
+ Encryption encryption,
+ Object arg);
+
+ private class DecryptingRequestContextWrapper
+ extends RequestContextWrapper {
+
+ public DecryptingRequestContextWrapper(
+ RequestContext request) {
+ super(request);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Element> Document<T> getDocument(
+ Parser parser,
+ ParserOptions options)
+ throws ParseException,
+ IOException {
+ Document<Element> doc = super.getDocument();
try {
- Document<Element> doc = getDocument(wrapper);
if (doc != null) {
+ AbderaSecurity security = new AbderaSecurity(getAbdera());
Encryption enc = security.getEncryption();
if (enc.isEncrypted(doc)) {
Object arg = initArg(request);
- EncryptionOptions options = initEncryptionOptions(request,response,enc,arg);
- doDecryption(doc, options, enc, wrapper);
+ EncryptionOptions encoptions = initEncryptionOptions(request,enc,arg);
+ doc = enc.decrypt(doc, encoptions);
}
}
- } catch (Exception e) {
- } finally {wrapper.reset();}
- request = wrapper;
+ } catch (Exception e) {}
+ return (Document<T>) doc;
}
- chain.doFilter(request, response);
}
-
- protected void doDecryption(
- Document doc,
- EncryptionOptions options,
- Encryption enc,
- BufferedRequestWrapper wrapper)
- throws SecurityException, IOException {
- doc = enc.decrypt(doc, options);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- doc.writeTo(out);
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- wrapper.setInputStream(in);
- }
-
- protected abstract void bootstrap(ServletRequest request, ServletResponse response);
-
- protected abstract Object initArg(ServletRequest request);
-
- protected abstract EncryptionOptions initEncryptionOptions(
- ServletRequest request,
- ServletResponse response,
- Encryption encryption,
- Object arg);
}
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedResponseFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedResponseFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedResponseFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/AbstractEncryptedResponseFilter.java Thu Jan 31 18:34:07 2008
@@ -15,31 +15,33 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
+package org.apache.abdera.security.util.filters;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.security.Provider;
import java.security.Security;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-
+import org.apache.abdera.Abdera;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
+import org.apache.abdera.protocol.server.Filter;
+import org.apache.abdera.protocol.server.FilterChain;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.context.ResponseContextWrapper;
+import org.apache.abdera.security.AbderaSecurity;
import org.apache.abdera.security.Encryption;
import org.apache.abdera.security.EncryptionOptions;
+import org.apache.abdera.writer.Writer;
+@SuppressWarnings("unchecked")
public abstract class AbstractEncryptedResponseFilter
- extends SecurityFilter {
-
- public void init(
- FilterConfig config)
- throws ServletException {
- super.init(config);
+ implements Filter {
+
+ public AbstractEncryptedResponseFilter() {
initProvider();
}
@@ -50,40 +52,92 @@
Security.addProvider(provider);
}
- @SuppressWarnings("unchecked")
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain chain)
- throws IOException,
- ServletException {
- try {
+ public ResponseContext filter(
+ RequestContext request,
+ FilterChain chain) {
Object arg = initArg(request);
if (doEncryption(request, arg)) {
- BufferingResponseWrapper wrapper =
- new BufferingResponseWrapper(
- (HttpServletResponse)response);
- chain.doFilter(request, wrapper);
- Document<Element> doc = getDocument(wrapper);
- if (doc != null) {
- Encryption enc = security.getEncryption();
- EncryptionOptions options = initEncryptionOptions(request,response,enc,arg);
- Document<Element> enc_doc = enc.encrypt(doc, options);
- enc_doc.writeTo(response.getOutputStream());
- }
+ return new EncryptingResponseContext(
+ request.getAbdera(),
+ request,
+ chain.next(request),
+ arg);
} else {
- chain.doFilter(request, response);
+ return chain.next(request);
}
- } catch (Exception e) {}
}
- protected abstract boolean doEncryption(ServletRequest request, Object arg);
+ protected abstract boolean doEncryption(RequestContext request, Object arg);
protected abstract EncryptionOptions initEncryptionOptions(
- ServletRequest request,
- ServletResponse response,
+ RequestContext request,
+ ResponseContext response,
Encryption enc,
Object arg);
- protected abstract Object initArg(ServletRequest request);
+ protected abstract Object initArg(RequestContext request);
+
+ private class EncryptingResponseContext
+ extends ResponseContextWrapper {
+
+ private final RequestContext request;
+ private final AbderaSecurity security;
+ private final Abdera abdera;
+ private final Object arg;
+
+ public EncryptingResponseContext(
+ Abdera abdera,
+ RequestContext request,
+ ResponseContext response,
+ Object arg) {
+ super(response);
+ this.abdera = abdera;
+ this.request = request;
+ this.security = new AbderaSecurity(abdera);
+ this.arg = arg;
+ }
+
+ public void writeTo(
+ OutputStream out,
+ Writer writer)
+ throws IOException {
+ try {
+ encrypt(out,null);
+ } catch (Exception se) {
+ throw new RuntimeException(se);
+ }
+ }
+
+ public void writeTo(OutputStream out)
+ throws IOException {
+ try {
+ encrypt(out,null);
+ } catch (Exception se) {
+ throw new RuntimeException(se);
+ }
+ }
+
+ private void encrypt(OutputStream aout, Writer writer) throws Exception {
+ Document<Element> doc = null;
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (writer == null)
+ super.writeTo(out);
+ else
+ super.writeTo(out,writer);
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ doc = abdera.getParser().parse(in);
+ } catch (Exception e) {}
+ if (doc != null) {
+ Encryption enc = security.getEncryption();
+ EncryptionOptions options = initEncryptionOptions(request,response,enc,arg);
+ doc = enc.encrypt(doc, options);
+ }
+ if (doc != null)
+ doc.writeTo(aout);
+ else
+ throw new RuntimeException(
+ "There was an error encrypting the response");
+ }
+ }
}
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedRequestFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedRequestFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedRequestFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedRequestFilter.java Thu Jan 31 18:34:07 2008
@@ -15,15 +15,12 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
-
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+package org.apache.abdera.security.util.filters;
+import org.apache.abdera.protocol.server.FilterChain;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.RequestContext.Scope;
import org.apache.abdera.security.Encryption;
import org.apache.abdera.security.EncryptionOptions;
import org.apache.abdera.security.util.Constants;
@@ -40,51 +37,59 @@
public class DHEncryptedRequestFilter
extends AbstractEncryptedRequestFilter {
- @Override
- public void init(FilterConfig config) throws ServletException {
- super.init(config);
+ public DHEncryptedRequestFilter() {
+ super();
+ }
+
+ public DHEncryptedRequestFilter(String... methods) {
+ super(methods);
}
- @Override
public void bootstrap(
- ServletRequest request,
- ServletResponse response ) {
- String method = ((HttpServletRequest)request).getMethod();
- // include a Accept-Encryption header in the response to GET, HEAD and OPTIONS requests
- // the header will specify all the information the client needs to construct
- // it's own DH context and encrypt the request
- if ("GET".equalsIgnoreCase(method) ||
- "HEAD".equalsIgnoreCase(method) ||
- "OPTIONS".equalsIgnoreCase(method)) {
- DHContext context = new DHContext();
- ((HttpServletResponse)response).setHeader(
- Constants.ACCEPT_ENCRYPTION,
- context.getRequestString());
- ((HttpServletRequest) request).getSession(true).setAttribute(
- "dhcontext", context);
- }
+ RequestContext request) {}
+
+ public ResponseContext filter(
+ RequestContext request,
+ FilterChain chain) {
+ ResponseContext response = super.filter(request, chain);
+ String method = request.getMethod();
+ // include a Accept-Encryption header in the response to GET, HEAD and OPTIONS requests
+ // the header will specify all the information the client needs to construct
+ // it's own DH context and encrypt the request
+ if ("GET".equalsIgnoreCase(method) ||
+ "HEAD".equalsIgnoreCase(method) ||
+ "OPTIONS".equalsIgnoreCase(method)) {
+ DHContext context =
+ (DHContext) request.getAttribute(
+ Scope.SESSION,
+ "dhcontext");
+ if (context == null) {
+ context = new DHContext();
+ request.setAttribute(Scope.SESSION, "dhcontext", context);
+ }
+ response.setHeader(
+ Constants.ACCEPT_ENCRYPTION,
+ context.getRequestString());
+ }
+ return response;
}
- @Override
- protected Object initArg(ServletRequest request) {
+ protected Object initArg(RequestContext request) {
DHContext context =
- (DHContext) ((HttpServletRequest)request).
- getSession(true).getAttribute("dhcontext");
- String dh = ((HttpServletRequest)request).getHeader(Constants.CONTENT_ENCRYPTED);
+ (DHContext) request.getAttribute(
+ Scope.SESSION,
+ "dhcontext");
+ String dh = request.getHeader(Constants.CONTENT_ENCRYPTED);
if (context != null && dh != null && dh.length() > 0) {
try {
context.setPublicKey(dh);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ } catch (Exception e) {}
}
return context;
}
- @Override
protected EncryptionOptions initEncryptionOptions(
- ServletRequest request,
- ServletResponse response,
+ RequestContext request,
Encryption encryption,
Object arg) {
EncryptionOptions options = null;
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedResponseFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedResponseFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedResponseFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/DHEncryptedResponseFilter.java Thu Jan 31 18:34:07 2008
@@ -15,13 +15,11 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+package org.apache.abdera.security.util.filters;
+import org.apache.abdera.protocol.server.FilterChain;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
import org.apache.abdera.security.Encryption;
import org.apache.abdera.security.EncryptionOptions;
import org.apache.abdera.security.util.Constants;
@@ -71,34 +69,47 @@
public class DHEncryptedResponseFilter
extends AbstractEncryptedResponseFilter {
- protected boolean doEncryption(ServletRequest request, Object arg) {
- return arg != null;
+ protected boolean doEncryption(
+ RequestContext request,
+ Object arg) {
+ return arg != null;
}
- protected Object initArg(ServletRequest request) {
- return getDHContext((HttpServletRequest)request);
+ protected Object initArg(RequestContext request) {
+ return getDHContext(request);
}
protected EncryptionOptions initEncryptionOptions(
- ServletRequest request,
- ServletResponse response,
+ RequestContext request,
+ ResponseContext response,
Encryption enc,
Object arg) {
EncryptionOptions options = null;
try {
DHContext context = (DHContext) arg;
options = context.getEncryptionOptions(enc);
- returnPublicKey((HttpServletResponse)response,context);
+ returnPublicKey(response,context);
} catch (Exception e) {}
return options;
}
- private void returnPublicKey(HttpServletResponse response, DHContext context) {
+ public ResponseContext filter(
+ RequestContext request,
+ FilterChain chain) {
+ ResponseContext response = super.filter(request,chain);
+ DHContext context = getDHContext(request);
+ response.setHeader(
+ Constants.CONTENT_ENCRYPTED,
+ context.getResponseString());
+ return response;
+ }
+
+ private void returnPublicKey(ResponseContext response, DHContext context) {
response.setHeader(Constants.CONTENT_ENCRYPTED,context.getResponseString());
}
- private DHContext getDHContext(HttpServletRequest request) {
+ private DHContext getDHContext(RequestContext request) {
try {
String dh_req = request.getHeader(Constants.ACCEPT_ENCRYPTION);
if (dh_req == null || dh_req.length() == 0) return null;
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedRequestFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedRequestFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedRequestFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedRequestFilter.java Thu Jan 31 18:34:07 2008
@@ -15,21 +15,16 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
+package org.apache.abdera.security.util.filters;
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.abdera.Abdera;
import org.apache.abdera.i18n.text.Localizer;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
+import org.apache.abdera.protocol.server.Filter;
+import org.apache.abdera.protocol.server.FilterChain;
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
import org.apache.abdera.security.AbderaSecurity;
import org.apache.abdera.security.Signature;
@@ -38,43 +33,31 @@
* via PUT or POST contains a valid XML Digital Signature.
*/
public class SignedRequestFilter
- extends SecurityFilter {
+ implements Filter {
public static final String VALID = "org.apache.abdera.security.util.servlet.SignedRequestFilter.valid";
public static final String CERTS = "org.apache.abdera.security.util.servlet.SignedRequestFilter.certs";
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain filter)
- throws IOException, ServletException {
-
- HttpServletRequest req = (HttpServletRequest) request;
- String method = req.getMethod();
+ public ResponseContext filter(
+ RequestContext request,
+ FilterChain chain) {
+
+ AbderaSecurity security = new AbderaSecurity(request.getAbdera());
+ Signature sig = security.getSignature();
+ String method = request.getMethod();
if (method.equals("POST") || method.equals("PUT")) {
- BufferedRequestWrapper wrapper =
- new BufferedRequestWrapper((HttpServletRequest) request);
try {
- Abdera abdera = new Abdera();
- AbderaSecurity absec = new AbderaSecurity(abdera);
- Signature sig = absec.getSignature();
- Document<Element> doc = abdera.getParser().parse(wrapper.getInputStream());
+ Document<Element> doc = request.getDocument();
boolean valid = sig.verify(doc.getRoot(), null);
- if (!valid) {
- ((HttpServletResponse)response).sendError(
- 400, Localizer.get("VALID.SIGNATURE.REQUIRED"));
- return;
- }
- wrapper.setAttribute(VALID, Boolean.valueOf(valid));
- wrapper.setAttribute(CERTS, sig.getValidSignatureCertificates(doc.getRoot(), null));
- } catch (Exception e) {
- e.printStackTrace();
- }
- wrapper.reset();
- filter.doFilter(wrapper, response);
- } else {
- filter.doFilter(request, response);
+ if (!valid)
+ return ProviderHelper.badrequest(
+ request,
+ Localizer.get("VALID.SIGNATURE.REQUIRED"));
+ request.setAttribute(VALID, valid);
+ request.setAttribute(CERTS,sig.getValidSignatureCertificates(doc.getRoot(), null));
+ } catch (Exception e) {}
}
+ return chain.next(request);
}
}
Modified: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedResponseFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedResponseFilter.java?rev=617333&r1=617258&r2=617333&view=diff
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedResponseFilter.java (original)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/filters/SignedResponseFilter.java Thu Jan 31 18:34:07 2008
@@ -15,25 +15,30 @@
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
-package org.apache.abdera.security.util.servlet;
+package org.apache.abdera.security.util.filters;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-
+import org.apache.abdera.Abdera;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
+import org.apache.abdera.protocol.server.Filter;
+import org.apache.abdera.protocol.server.FilterChain;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.context.ResponseContextWrapper;
+import org.apache.abdera.security.AbderaSecurity;
import org.apache.abdera.security.SecurityException;
import org.apache.abdera.security.Signature;
import org.apache.abdera.security.SignatureOptions;
+import org.apache.abdera.writer.Writer;
/**
* <p>This HTTP Servlet Filter will add an XML Digital Signature to Abdera documents</p>
@@ -73,15 +78,8 @@
* </pre>
*/
public class SignedResponseFilter
- extends SecurityFilter {
-
- private static final String KEYSTORE = "org.apache.abdera.security.util.servlet.Keystore";
- private static final String STOREPASS = "org.apache.abdera.security.util.servlet.KeystorePassword";
- private static final String KEY = "org.apache.abdera.security.util.servlet.PrivateKeyAlias";
- private static final String KEYPASS = "org.apache.abdera.security.util.servlet.PrivateKeyPassword";
- private static final String CERT = "org.apache.abdera.security.util.servlet.CertificateAlias";
- private static final String ALGO = "org.apache.abdera.security.util.servlet.SigningAlgorithm";
-
+ implements Filter {
+
private static final String keystoreType = "JKS";
private String keystoreFile = null;
@@ -93,65 +91,178 @@
private PrivateKey signingKey = null;
private X509Certificate cert = null;
- public void init(
- FilterConfig config)
- throws ServletException {
- keystoreFile = config.getInitParameter(KEYSTORE);
- keystorePass = config.getInitParameter(STOREPASS);
- privateKeyAlias = config.getInitParameter(KEY);
- privateKeyPass = config.getInitParameter(KEYPASS);
- certificateAlias = config.getInitParameter(CERT);
- algorithm = config.getInitParameter(ALGO);
-
- try {
- KeyStore ks = KeyStore.getInstance(keystoreType);
- //InputStream in = SignedResponseFilter.class.getResourceAsStream(keystoreFile);
- java.io.FileInputStream fin = new java.io.FileInputStream(keystoreFile);
- ks.load(fin, keystorePass.toCharArray());
- signingKey =
- (PrivateKey) ks.getKey(
- privateKeyAlias,
- privateKeyPass.toCharArray());
- cert =
- (X509Certificate) ks.getCertificate(
- certificateAlias);
- } catch (Exception e) {}
+ public SignedResponseFilter(
+ String keystoreFile,
+ String keystorePass,
+ String privateKeyAlias,
+ String privateKeyPass,
+ String certificateAlias,
+ String algorithm) {
+ this.keystoreFile = keystoreFile;
+ this.keystorePass = keystorePass;
+ this.privateKeyAlias = privateKeyAlias;
+ this.privateKeyPass = privateKeyPass;
+ this.certificateAlias = certificateAlias;
+ this.algorithm = algorithm;
+ try {
+ KeyStore ks = KeyStore.getInstance(keystoreType);
+ InputStream in = SignedResponseFilter.class.getResourceAsStream(keystoreFile);
+ ks.load(in, keystorePass.toCharArray());
+ signingKey =
+ (PrivateKey) ks.getKey(
+ privateKeyAlias,
+ privateKeyPass.toCharArray());
+ cert =
+ (X509Certificate) ks.getCertificate(
+ certificateAlias);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain chain)
- throws IOException,
- ServletException {
-
- BufferingResponseWrapper wrapper =
- new BufferingResponseWrapper(
- (HttpServletResponse)response);
-
- chain.doFilter(request, wrapper);
-
- try {
- Document<Element> doc = getDocument(wrapper);
- if (doc != null) {
- doc = sign(doc);
- doc.writeTo(response.getOutputStream());
- }
- } catch (Exception e) {
- throw new ServletException(e);
- }
+ public ResponseContext filter(
+ RequestContext request,
+ FilterChain chain) {
+ return new SigningResponseContextWrapper(
+ request.getAbdera(),
+ chain.next(request));
}
- private Document<Element> sign(Document<Element> doc) throws SecurityException {
+ private Document<Element> signDocument(
+ Abdera abdera,
+ Document<Element> doc)
+ throws SecurityException {
+ AbderaSecurity security = new AbderaSecurity(abdera);
if (signingKey == null || cert == null) return doc; // pass through
Signature sig = security.getSignature();
SignatureOptions options = sig.getDefaultSignatureOptions();
options.setCertificate(cert);
options.setSigningKey(signingKey);
- options.setSigningAlgorithm(algorithm);
+ if (algorithm != null)
+ options.setSigningAlgorithm(algorithm);
Element element = doc.getRoot();
element = sig.sign(element, options);
return element.getDocument();
}
-
+
+ private class SigningResponseContextWrapper
+ extends ResponseContextWrapper {
+
+ private final Abdera abdera;
+
+ public SigningResponseContextWrapper(
+ Abdera abdera,
+ ResponseContext response) {
+ super(response);
+ this.abdera = abdera;
+ }
+
+ public void writeTo(
+ OutputStream out,
+ Writer writer)
+ throws IOException {
+ try {
+ sign(out,null);
+ } catch (Exception se) {
+ throw new RuntimeException(se);
+ }
+ }
+
+ public void writeTo(OutputStream out)
+ throws IOException {
+ try {
+ sign(out,null);
+ } catch (Exception se) {
+ throw new RuntimeException(se);
+ }
+ }
+
+ private void sign(OutputStream aout, Writer writer) throws Exception {
+ Document<Element> doc = null;
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (writer == null)
+ super.writeTo(out);
+ else
+ super.writeTo(out,writer);
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ doc = abdera.getParser().parse(in);
+ } catch (Exception e) {}
+ if (doc != null) {
+ doc = signDocument(abdera,doc);
+ doc.writeTo(aout);
+ }
+ else
+ throw new RuntimeException(
+ "There was an error signing the response");
+ }
+ }
+
+ public String getKeystoreFile() {
+ return keystoreFile;
+ }
+
+ public void setKeystoreFile(String keystoreFile) {
+ this.keystoreFile = keystoreFile;
+ }
+
+ public String getKeystorePass() {
+ return keystorePass;
+ }
+
+ public void setKeystorePass(String keystorePass) {
+ this.keystorePass = keystorePass;
+ }
+
+ public String getPrivateKeyAlias() {
+ return privateKeyAlias;
+ }
+
+ public void setPrivateKeyAlias(String privateKeyAlias) {
+ this.privateKeyAlias = privateKeyAlias;
+ }
+
+ public String getPrivateKeyPass() {
+ return privateKeyPass;
+ }
+
+ public void setPrivateKeyPass(String privateKeyPass) {
+ this.privateKeyPass = privateKeyPass;
+ }
+
+ public String getCertificateAlias() {
+ return certificateAlias;
+ }
+
+ public void setCertificateAlias(String certificateAlias) {
+ this.certificateAlias = certificateAlias;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public void setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public PrivateKey getSigningKey() {
+ return signingKey;
+ }
+
+ public void setSigningKey(PrivateKey signingKey) {
+ this.signingKey = signingKey;
+ }
+
+ public X509Certificate getCert() {
+ return cert;
+ }
+
+ public void setCert(X509Certificate cert) {
+ this.cert = cert;
+ }
+
+ public static String getKeystoreType() {
+ return keystoreType;
+ }
}
Added: incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/CustomProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/CustomProvider.java?rev=617333&view=auto
==============================================================================
--- incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/CustomProvider.java (added)
+++ incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/CustomProvider.java Thu Jan 31 18:34:07 2008
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.abdera.test.security.filter;
+
+import org.apache.abdera.protocol.server.CollectionAdapter;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.TargetType;
+import org.apache.abdera.protocol.server.impl.AbstractWorkspaceProvider;
+import org.apache.abdera.protocol.server.impl.RouteManager;
+import org.apache.abdera.protocol.server.impl.SimpleWorkspaceInfo;
+import org.apache.abdera.security.util.filters.SignedResponseFilter;
+
+public class CustomProvider
+ extends AbstractWorkspaceProvider {
+
+ private final SimpleAdapter adapter;
+
+ private static final String keystoreFile = "/key.jks";
+ private static final String keystorePass = "testing";
+ private static final String privateKeyAlias = "James";
+ private static final String privateKeyPass = "testing";
+ private static final String certificateAlias = "James";
+
+ public CustomProvider() {
+
+ this.adapter = new SimpleAdapter();
+
+ RouteManager rm =
+ new RouteManager()
+ .addRoute("service", "/", TargetType.TYPE_SERVICE)
+ .addRoute("collection", "/:collection", TargetType.TYPE_COLLECTION)
+ .addRoute("entry","/:collection/:entry", TargetType.TYPE_ENTRY);
+
+ setTargetBuilder(rm);
+ setTargetResolver(rm);
+
+ SimpleWorkspaceInfo workspace = new SimpleWorkspaceInfo();
+ workspace.setTitle("A Simple Workspace");
+ workspace.addCollection(adapter);
+ addWorkspace(workspace);
+
+ addFilter(
+ new SignedResponseFilter(
+ keystoreFile,
+ keystorePass,
+ privateKeyAlias,
+ privateKeyPass,
+ certificateAlias, null
+ )
+ );
+ }
+
+ public CollectionAdapter getCollectionAdapter(
+ RequestContext request) {
+ return adapter;
+ }
+
+}
Added: incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/JettyServer.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/JettyServer.java?rev=617333&view=auto
==============================================================================
--- incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/JettyServer.java (added)
+++ incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/JettyServer.java Thu Jan 31 18:34:07 2008
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.test.security.filter;
+
+import org.apache.abdera.protocol.server.Provider;
+import org.apache.abdera.protocol.server.ServiceManager;
+import org.apache.abdera.protocol.server.servlet.AbderaServlet;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+public class JettyServer {
+
+ public static final int DEFAULT_PORT = 9002;
+
+ private final int port;
+ private Server server;
+
+ public JettyServer() {
+ this(DEFAULT_PORT);
+ }
+
+ public JettyServer(int port) {
+ this.port = port;
+ }
+
+ public void start(Class<? extends Provider> _class) throws Exception {
+ server = new Server(port);
+ Context context = new Context(server, "/", Context.SESSIONS);
+ ServletHolder servletHolder = new ServletHolder(new AbderaServlet());
+ servletHolder.setInitParameter(ServiceManager.PROVIDER, _class.getName());
+ context.addServlet(servletHolder, "/*");
+ server.start();
+ }
+
+ public void stop() throws Exception {
+ server.stop();
+ }
+
+ public void join() throws Exception {
+ server.join();
+ }
+
+}
Added: incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SecurityFilterTest.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SecurityFilterTest.java?rev=617333&view=auto
==============================================================================
--- incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SecurityFilterTest.java (added)
+++ incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SecurityFilterTest.java Thu Jan 31 18:34:07 2008
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.abdera.test.security.filter;
+
+import junit.framework.Assert;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.protocol.client.AbderaClient;
+import org.apache.abdera.protocol.client.ClientResponse;
+import org.apache.abdera.security.AbderaSecurity;
+import org.apache.abdera.security.Signature;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SecurityFilterTest
+ extends Assert {
+
+ private static JettyServer server;
+ private static Abdera abdera = Abdera.getInstance();
+ private static AbderaClient client = new AbderaClient();
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ try {
+ server = new JettyServer();
+ server.start(CustomProvider.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ server.stop();
+ }
+
+ @Test
+ public void testSignedResponseFilter() throws Exception {
+ ClientResponse resp = client.get("http://localhost:9002/");
+ Document<Element> doc = resp.getDocument();
+ Element root = doc.getRoot();
+ AbderaSecurity security = new AbderaSecurity(abdera);
+ Signature sig = security.getSignature();
+ assertTrue(sig.isSigned(root));
+ assertTrue(sig.verify(root, sig.getDefaultSignatureOptions()));
+ }
+
+}
Added: incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SimpleAdapter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SimpleAdapter.java?rev=617333&view=auto
==============================================================================
--- incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SimpleAdapter.java (added)
+++ incubator/abdera/java/trunk/security/src/test/java/org/apache/abdera/test/security/filter/SimpleAdapter.java Thu Jan 31 18:34:07 2008
@@ -0,0 +1,268 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.test.security.filter;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.i18n.text.UrlEncoding;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.parser.ParseException;
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.TargetType;
+import org.apache.abdera.protocol.server.RequestContext.Scope;
+import org.apache.abdera.protocol.server.context.BaseResponseContext;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.abdera.protocol.server.context.StreamWriterResponseContext;
+import org.apache.abdera.protocol.server.impl.AbstractCollectionAdapter;
+import org.apache.abdera.util.Constants;
+import org.apache.abdera.writer.StreamWriter;
+
+@SuppressWarnings("unchecked")
+public class SimpleAdapter
+ extends AbstractCollectionAdapter {
+
+ @Override
+ public String getAuthor() throws ResponseContextException {
+ return "Simple McGee";
+ }
+
+ @Override
+ public String getId(RequestContext request) {
+ return "tag:example.org,2008:feed";
+ }
+
+ public String getHref(RequestContext request) {
+ Map<String,Object> params = new HashMap<String,Object>();
+ params.put("collection","feed");
+ return request.urlFor(TargetType.TYPE_COLLECTION, params);
+ }
+
+ public String getTitle(RequestContext request) {
+ return "A simple feed";
+ }
+
+ public ResponseContext extensionRequest(RequestContext request) {
+ return ProviderHelper.notallowed(
+ request,
+ "Method Not Allowed",
+ ProviderHelper.getDefaultMethods(request));
+ }
+
+ private Document<Feed> getFeedDocument(RequestContext context) throws ResponseContextException {
+ Feed feed = (Feed)context.getAttribute(Scope.SESSION, "feed");
+ if (feed == null) {
+ feed = createFeedBase(context);
+ feed.setBaseUri(getHref(context));
+ context.setAttribute(Scope.SESSION, "feed", feed);
+ }
+ return feed.getDocument();
+ }
+
+ public ResponseContext getFeed(
+ RequestContext request) {
+ Document<Feed> feed;
+ try {
+ feed = getFeedDocument(request);
+ } catch (ResponseContextException e) {
+ return e.getResponseContext();
+ }
+
+ return ProviderHelper.returnBase(
+ feed,
+ 200,
+ feed.getRoot().getUpdated())
+ .setEntityTag(
+ ProviderHelper.calculateEntityTag(
+ feed.getRoot()));
+ }
+
+
+ public ResponseContext deleteEntry(
+ RequestContext request) {
+ Entry entry = getAbderaEntry(request);
+ if (entry != null)
+ entry.discard();
+ return ProviderHelper.nocontent();
+ }
+
+ public ResponseContext getEntry(
+ RequestContext request) {
+ Entry entry = (Entry) getAbderaEntry(request);
+ if (entry != null) {
+ Feed feed = entry.getParentElement();
+ entry = (Entry) entry.clone();
+ entry.setSource(feed.getAsSource());
+ Document<Entry> entry_doc = entry.getDocument();
+ return
+ ProviderHelper.returnBase(
+ entry_doc,
+ 200,
+ entry.getEdited())
+ .setEntityTag(
+ ProviderHelper.calculateEntityTag(
+ entry));
+ } else {
+ return ProviderHelper.notfound(request);
+ }
+ }
+
+ public ResponseContext postEntry(
+ RequestContext request) {
+ Abdera abdera = request.getAbdera();
+ try {
+ Document<Entry> entry_doc =
+ (Document<Entry>) request.getDocument(
+ abdera.getParser()).clone();
+ if (entry_doc != null) {
+ Entry entry = entry_doc.getRoot();
+ if (!ProviderHelper.isValidEntry(entry))
+ return ProviderHelper.badrequest(request);
+ setEntryDetails(
+ request,
+ entry,
+ abdera.getFactory().newUuidUri());
+ Feed feed = getFeedDocument(request).getRoot();
+ feed.insertEntry(entry);
+ feed.setUpdated(new Date());
+ BaseResponseContext rc =
+ (BaseResponseContext) ProviderHelper.returnBase(
+ entry_doc, 201, entry.getEdited());
+ return
+ rc.setLocation(
+ ProviderHelper.resolveBase(request).resolve(
+ entry.getEditLinkResolvedHref()).toString())
+ .setContentLocation(rc.getLocation().toString())
+ .setEntityTag(ProviderHelper.calculateEntityTag(entry));
+ } else {
+ return ProviderHelper.badrequest(request);
+ }
+ } catch (ParseException pe) {
+ return ProviderHelper.notsupported(request);
+ } catch (ClassCastException cce) {
+ return ProviderHelper.notsupported(request);
+ } catch (Exception e) {
+ return ProviderHelper.badrequest(request);
+ }
+ }
+
+ private void setEntryDetails(
+ RequestContext request,
+ Entry entry,
+ String id) {
+ entry.setUpdated(new Date());
+ entry.setEdited(entry.getUpdated());
+ entry.getIdElement().setValue(id);
+ entry.addLink(
+ getEntryLink(request,entry.getId().toASCIIString()),
+ "edit");
+ }
+
+ private String getEntryLink(RequestContext request, String entryid) {
+ Map<String,String> params = new HashMap<String,String>();
+ params.put("collection", request.getTarget().getParameter("collection"));
+ params.put("entry", entryid);
+ return request.urlFor(TargetType.TYPE_ENTRY, params);
+ }
+
+ public ResponseContext putEntry(
+ RequestContext request) {
+ Abdera abdera = request.getAbdera();
+ Entry orig_entry = getAbderaEntry(request);
+ if (orig_entry != null) {
+ try {
+ Document<Entry> entry_doc =
+ (Document<Entry>) request.getDocument(
+ abdera.getParser()).clone();
+ if (entry_doc != null) {
+ Entry entry = entry_doc.getRoot();
+ if (!entry.getId().equals(orig_entry.getId()))
+ return ProviderHelper.conflict(request);
+ if (!ProviderHelper.isValidEntry(entry))
+ return ProviderHelper.badrequest(request);
+ setEntryDetails(
+ request,
+ entry,
+ orig_entry.getId().toString());
+ orig_entry.discard();
+ Feed feed = getFeedDocument(request).getRoot();
+ feed.insertEntry(entry);
+ feed.setUpdated(new Date());
+ return ProviderHelper.nocontent();
+ } else {
+ return ProviderHelper.badrequest(request);
+ }
+ } catch (ParseException pe) {
+ return ProviderHelper.notsupported(request);
+ } catch (ClassCastException cce) {
+ return ProviderHelper.notsupported(request);
+ } catch (Exception e) {
+ return ProviderHelper.badrequest(request);
+ }
+ } else {
+ return ProviderHelper.notfound(request);
+ }
+ }
+
+ private Entry getAbderaEntry(
+ RequestContext request) {
+ try {
+ return getFeedDocument(
+ request)
+ .getRoot()
+ .getEntry(
+ getEntryID(request));
+ } catch (Exception e) {}
+ return null;
+ }
+
+ public String getEntryID(
+ RequestContext request) {
+ if (request.getTarget().getType() != TargetType.TYPE_ENTRY)
+ return null;
+ String[] segments = request.getUri().toString().split("/");
+ return UrlEncoding.decode(segments[segments.length-1]);
+ }
+
+ public ResponseContext getCategories(
+ RequestContext request) {
+ return
+ new StreamWriterResponseContext(request.getAbdera()) {
+ protected void writeTo(
+ StreamWriter sw)
+ throws IOException {
+ sw.startDocument()
+ .startCategories(false)
+ .writeCategory("foo")
+ .writeCategory("bar")
+ .writeCategory("baz")
+ .endCategories()
+ .endDocument();
+ }
+ }
+ .setStatus(200)
+ .setContentType(Constants.CAT_MEDIA_TYPE);
+ }
+}
\ No newline at end of file