1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.ksb.security;
17
18 import java.io.BufferedOutputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.security.GeneralSecurityException;
23
24 import javax.servlet.ServletOutputStream;
25
26
27
28
29
30
31
32
33
34 public class SignatureSigningOutputStream extends ServletOutputStream {
35
36 private boolean delayWrite;
37 private DigitalSigner signer;
38 private BufferedOutputStream bufferedDataHoldingStream;
39 private ByteArrayOutputStream dataHoldingStream;
40 private OutputStream wrappedOutputStream;
41
42
43
44
45
46
47
48 public SignatureSigningOutputStream(DigitalSigner signer, OutputStream wrappedOutputStream, boolean delayWrite) {
49 super();
50 this.delayWrite = delayWrite;
51 if (delayWrite) {
52 this.dataHoldingStream = new ByteArrayOutputStream();
53 this.bufferedDataHoldingStream = new BufferedOutputStream(this.dataHoldingStream);
54 }
55 this.wrappedOutputStream = wrappedOutputStream;
56 this.signer = signer;
57 }
58
59 public void write(int data) throws IOException {
60 if (this.delayWrite) {
61 this.bufferedDataHoldingStream.write(data);
62 } else {
63 this.wrappedOutputStream.write(data);
64 }
65 try {
66 this.signer.getSignature().update((byte)data);
67 } catch (GeneralSecurityException e) {
68 IOException exception = new IOException("Error updating signature.");
69 exception.initCause(e);
70 throw exception;
71 }
72 }
73
74 @Override
75 public void close() throws IOException {
76
77 try {
78 this.signer.sign();
79 if (this.delayWrite) {
80 this.bufferedDataHoldingStream.close();
81 byte[] data = this.dataHoldingStream.toByteArray();
82 for (int index = 0; index < data.length; index++) {
83 this.wrappedOutputStream.write(data[index]);
84 }
85 }
86 this.wrappedOutputStream.close();
87 } catch (Exception e) {
88 IOException exception = new IOException("Error attaching digital signature to outbound response.");
89 exception.initCause(e);
90 throw exception;
91 } finally {
92 super.close();
93 }
94 }
95
96 }