View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.jdkim.impl;
21  
22  import java.io.OutputStream;
23  import java.security.MessageDigest;
24  import java.security.NoSuchAlgorithmException;
25  
26  import org.apache.james.jdkim.api.BodyHasher;
27  import org.apache.james.jdkim.api.SignatureRecord;
28  import org.apache.james.jdkim.canon.DebugOutputStream;
29  import org.apache.james.jdkim.canon.DigestOutputStream;
30  import org.apache.james.jdkim.canon.LimitedOutputStream;
31  import org.apache.james.jdkim.canon.RelaxedBodyCanonicalizer;
32  import org.apache.james.jdkim.canon.SimpleBodyCanonicalizer;
33  import org.apache.james.jdkim.exceptions.PermFailException;
34  
35  public class BodyHasherImpl implements BodyHasher {
36  
37      private static final boolean DEEP_DEBUG = false;
38      private SignatureRecord sign;
39      private DigestOutputStream digesterOS;
40      private OutputStream out;
41  
42      public BodyHasherImpl(SignatureRecord sign) throws PermFailException {
43          MessageDigest md;
44          try {
45              md = MessageDigest.getInstance(sign.getHashAlgo().toString());
46          } catch (NoSuchAlgorithmException e) {
47              throw new PermFailException("Unsupported algorythm: "
48                      + sign.getHashAlgo(), e);
49          }
50  
51          int limit = sign.getBodyHashLimit();
52  
53          // TODO enhance this to use a lookup service.
54          boolean relaxedBody = SignatureRecord.RELAXED.equals(sign
55                  .getBodyCanonicalisationMethod());
56  
57          if (!relaxedBody
58                  && !SignatureRecord.SIMPLE.equals(sign
59                          .getBodyCanonicalisationMethod())) {
60              throw new PermFailException(
61                      "Unsupported body canonicalization method: "
62                              + sign.getBodyCanonicalisationMethod());
63          }
64  
65          DigestOutputStream dout = new DigestOutputStream(md);
66  
67          OutputStream out = dout;
68          if (DEEP_DEBUG)
69              out = new DebugOutputStream(out);
70          out = prepareCanonicalizerOutputStream(limit, relaxedBody, out);
71  
72          setSignatureRecord(sign);
73          setDigestOutputStream(dout);
74          setOutputStream(out);
75      }
76  
77      static OutputStream prepareCanonicalizerOutputStream(int limit,
78              boolean relaxedBody, OutputStream dout) {
79          OutputStream out = dout;
80          if (limit != -1)
81              out = new LimitedOutputStream(out, limit);
82          if (relaxedBody)
83              out = new RelaxedBodyCanonicalizer(out);
84          else
85              out = new SimpleBodyCanonicalizer(out);
86          return out;
87      }
88  
89      /**
90       * @see org.apache.james.jdkim.api.BodyHasher#getOutputStream()
91       */
92      public OutputStream getOutputStream() {
93          return out;
94      }
95  
96      /**
97       * @see org.apache.james.jdkim.api.BodyHasher#getSignatureRecord()
98       */
99      public SignatureRecord getSignatureRecord() {
100         return sign;
101     }
102 
103     private DigestOutputStream getDigesterOutputStream() {
104         return digesterOS;
105     }
106 
107     /**
108      * @see org.apache.james.jdkim.api.BodyHasher#getDigest()
109      */
110     public byte[] getDigest() {
111         return getDigesterOutputStream().getDigest();
112     }
113 
114     public void setSignatureRecord(SignatureRecord sign) {
115         this.sign = sign;
116     }
117 
118     public void setDigestOutputStream(DigestOutputStream dout) {
119         this.digesterOS = dout;
120     }
121 
122     public void setOutputStream(OutputStream out) {
123         this.out = out;
124     }
125 
126 }