Repository: cxf
Updated Branches:
  refs/heads/master e8a038340 -> f5d2a0332


[CXF-5311] Actually making JWS out streaming work, more refactoring will follow


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/f5d2a033
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/f5d2a033
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/f5d2a033

Branch: refs/heads/master
Commit: f5d2a0332c7a40d7b528fb1d32d10fe9ebb74fc2
Parents: e8a0383
Author: Sergey Beryozkin <sberyoz...@talend.com>
Authored: Thu Jul 10 22:00:01 2014 +0100
Committer: Sergey Beryozkin <sberyoz...@talend.com>
Committed: Thu Jul 10 22:00:01 2014 +0100

----------------------------------------------------------------------
 .../cxf/common/util/Base64OutputStream.java     | 90 ++++++++++++++++++++
 .../jws/AbstractJwsSignatureProvider.java       | 12 +--
 .../rs/security/oauth2/jws/JwsOutputStream.java | 40 +--------
 .../oauth2/jwt/jaxrs/JwsWriterInterceptor.java  |  9 +-
 .../oauth2/utils/Base64UrlOutputStream.java     | 31 +++++++
 .../jaxrs/security/jwt/JAXRSJweJwsTest.java     |  4 +-
 6 files changed, 140 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/f5d2a033/core/src/main/java/org/apache/cxf/common/util/Base64OutputStream.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/cxf/common/util/Base64OutputStream.java 
b/core/src/main/java/org/apache/cxf/common/util/Base64OutputStream.java
new file mode 100644
index 0000000..6ba8e95
--- /dev/null
+++ b/core/src/main/java/org/apache/cxf/common/util/Base64OutputStream.java
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.common.util;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class Base64OutputStream extends FilterOutputStream {
+    private byte[] lastChunk;
+    private boolean flushed;
+    private boolean urlSafe;
+    public Base64OutputStream(OutputStream out, boolean urlSafe) {
+        super(out);
+        this.urlSafe = urlSafe;
+    }
+
+    @Override
+    public void write(int value) throws IOException {
+        byte[] bytes = ByteBuffer.allocate(Integer.SIZE / 
8).putInt(value).array();
+        write(bytes, 0, bytes.length);
+    }
+    
+    @Override
+    public void write(byte b[], int off, int len) throws IOException {
+        encodeAndWrite(b, off, len, false);
+    }
+    
+    private void encodeAndWrite(byte[] b, int off, int len, boolean 
finalWrite) throws IOException {
+        byte[] theChunk = lastChunk;
+        int lenToEncode = len;
+        if (theChunk != null) {
+            theChunk = newArray(theChunk, 0, theChunk.length, b, off, len);
+            lenToEncode = theChunk.length;
+            off = 0;
+        } else {
+            theChunk = b;
+        }
+        int rem = finalWrite ? 0 : lenToEncode % 3; 
+        Base64Utility.encodeAndStream(theChunk, off, lenToEncode - rem, 
urlSafe, out);
+        
+        if (rem > 0) {
+            lastChunk = newArray(theChunk, lenToEncode - rem, rem);
+        } else {
+            lastChunk = null;
+        }
+    }
+    
+    @Override
+    public void flush() throws IOException {
+        if (flushed) {
+            return;
+        }
+        try {
+            Base64Utility.encodeAndStream(lastChunk, 0, lastChunk.length, 
urlSafe, out);
+            lastChunk = null;
+        } catch (Exception ex) {
+            throw new SecurityException();
+        }
+        flushed = true;
+    }
+    private byte[] newArray(byte[] src, int srcPos, int srcLen) {
+        byte[] buf = new byte[srcLen];
+        System.arraycopy(src, srcPos, buf, 0, srcLen);
+        return buf;
+    }
+    private byte[] newArray(byte[] src, int srcPos, int srcLen, byte[] src2, 
int srcPos2, int srcLen2) {
+        byte[] buf = new byte[srcLen + srcLen2];
+        System.arraycopy(src, srcPos, buf, 0, srcLen);
+        System.arraycopy(src2, srcPos2, buf, srcLen, srcLen2);
+        return buf;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/f5d2a033/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
index dc63a1e..b78c63b 100644
--- 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
@@ -21,9 +21,9 @@ package org.apache.cxf.rs.security.oauth2.jws;
 import java.io.OutputStream;
 import java.util.Set;
 
-import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtTokenReaderWriter;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
 
 public abstract class AbstractJwsSignatureProvider implements 
JwsSignatureProvider {
     private Set<String> supportedAlgorithms;
@@ -48,20 +48,20 @@ public abstract class AbstractJwsSignatureProvider 
implements JwsSignatureProvid
     
     @Override
     public JwsOutputStream createJwsStream(OutputStream os, String 
contentType) {
-        JwtHeaders headers = new JwtHeaders();
+        JwtHeaders headers = prepareHeaders(null);
         if (contentType != null) {
             headers.setContentType(contentType);
         }
-        headers = prepareHeaders(headers);
         JwsSignatureProviderWorker worker = createJwsSignatureWorker(headers);
+        JwsOutputStream jwsStream = new JwsOutputStream(os, worker);
         try {
             byte[] headerBytes = new 
JwtTokenReaderWriter().headersToJson(headers).getBytes("UTF-8");
-            Base64Utility.encodeAndStream(headerBytes, 0, headerBytes.length, 
os);
-            os.write(new byte[]{'.'});
+            Base64UrlUtility.encodeAndStream(headerBytes, 0, 
headerBytes.length, jwsStream);
+            jwsStream.write(new byte[]{'.'});
         } catch (Exception ex) {
             throw new SecurityException(ex);
         }
-        return new JwsOutputStream(os, worker);
+        return jwsStream;
     }
     
     protected abstract JwsSignatureProviderWorker 
createJwsSignatureWorker(JwtHeaders headers);

http://git-wip-us.apache.org/repos/asf/cxf/blob/f5d2a033/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
index 8c7734d..26268d1 100644
--- 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
@@ -26,7 +26,6 @@ import java.nio.ByteBuffer;
 import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
 
 public class JwsOutputStream extends FilterOutputStream {
-    private byte[] lastNonEncodedDataChunk;
     private boolean flushed;
     private JwsSignatureProviderWorker signature;
     public JwsOutputStream(OutputStream out, JwsSignatureProviderWorker 
signature) {
@@ -47,29 +46,8 @@ public class JwsOutputStream extends FilterOutputStream {
         } catch (Throwable ex) {
             throw new SecurityException();
         }
-        encodeAndWrite(b, off, len, false);
+        out.write(b, off, len);
     }
-    
-    private void encodeAndWrite(byte[] encryptedChunk, int off, int len, 
boolean finalWrite) throws IOException {
-        byte[] theChunk = lastNonEncodedDataChunk;
-        int lenToEncode = len;
-        if (theChunk != null) {
-            theChunk = newArray(theChunk, 0, theChunk.length, encryptedChunk, 
off, len);
-            lenToEncode = theChunk.length;
-            off = 0;
-        } else {
-            theChunk = encryptedChunk;
-        }
-        int rem = finalWrite ? 0 : lenToEncode % 3; 
-        Base64UrlUtility.encodeAndStream(theChunk, off, lenToEncode - rem, 
out);
-        
-        if (rem > 0) {
-            lastNonEncodedDataChunk = newArray(theChunk, lenToEncode - rem, 
rem);
-        } else {
-            lastNonEncodedDataChunk = null;
-        }
-    }
-    
     @Override
     public void flush() throws IOException {
         if (flushed) {
@@ -77,22 +55,12 @@ public class JwsOutputStream extends FilterOutputStream {
         }
         try {
             byte[] finalBytes = signature.sign();
-            out.write('.');
-            encodeAndWrite(finalBytes, 0, finalBytes.length, true);
+            out.write(new byte[]{'.'});
+            Base64UrlUtility.encodeAndStream(finalBytes, 0, finalBytes.length, 
out);
         } catch (Exception ex) {
             throw new SecurityException();
         }
         flushed = true;
     }
-    private byte[] newArray(byte[] src, int srcPos, int srcLen) {
-        byte[] buf = new byte[srcLen];
-        System.arraycopy(src, srcPos, buf, 0, srcLen);
-        return buf;
-    }
-    private byte[] newArray(byte[] src, int srcPos, int srcLen, byte[] src2, 
int srcPos2, int srcLen2) {
-        byte[] buf = new byte[srcLen + srcLen2];
-        System.arraycopy(src, srcPos, buf, 0, srcLen);
-        System.arraycopy(src2, srcPos2, buf, srcLen, srcLen2);
-        return buf;
-    }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/f5d2a033/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
index c672e29..e44dec7 100644
--- 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
@@ -32,6 +32,7 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.rs.security.oauth2.jws.JwsCompactProducer;
 import org.apache.cxf.rs.security.oauth2.jws.JwsOutputStream;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlOutputStream;
 
 @Priority(Priorities.JWS_WRITE_PRIORITY)
 public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements 
WriterInterceptor {
@@ -48,10 +49,12 @@ public class JwsWriterInterceptor extends 
AbstractJwsWriterProvider implements W
             }
         }
         if (useJwsOutputStream) {
-            JwsOutputStream cos = 
getInitializedSigProvider().createJwsStream(actualOs, ctString);
-            ctx.setOutputStream(cos);
+            JwsOutputStream jwsStream = 
getInitializedSigProvider().createJwsStream(actualOs, ctString);
+            Base64UrlOutputStream base64Stream = new 
Base64UrlOutputStream(jwsStream);
+            ctx.setOutputStream(base64Stream);
             ctx.proceed();
-            cos.flush();
+            base64Stream.flush();
+            jwsStream.flush();
         } else {
             CachedOutputStream cos = new CachedOutputStream(); 
             ctx.setOutputStream(cos);

http://git-wip-us.apache.org/repos/asf/cxf/blob/f5d2a033/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlOutputStream.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlOutputStream.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlOutputStream.java
new file mode 100644
index 0000000..549b062
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlOutputStream.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.oauth2.utils;
+
+import java.io.OutputStream;
+
+import org.apache.cxf.common.util.Base64OutputStream;
+
+public class Base64UrlOutputStream extends Base64OutputStream {
+
+    public Base64UrlOutputStream(OutputStream out) {
+        super(out, true);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/f5d2a033/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java
 
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java
index 15f40dd..e9bbc3b 100644
--- 
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java
+++ 
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java
@@ -86,7 +86,9 @@ public class JAXRSJweJwsTest extends 
AbstractBusClientServerTestBase {
         jweWriter.setUseJweOutputStream(true);
         providers.add(jweWriter);
         providers.add(new JweClientResponseFilter());
-        providers.add(new JwsWriterInterceptor());
+        JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor();
+        jwsWriter.setUseJwsOutputStream(true);
+        providers.add(jwsWriter);
         providers.add(new JwsClientResponseFilter());
         bean.setProviders(providers);
         bean.getProperties(true).put("rs.security.encryption.out.properties", 
SERVER_JWEJWS_PROPERTIES);

Reply via email to