KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > oyster > mail > ContentAnalyzer


1 /**
2  * Title: Oyster Project
3  * Description: Creating S/MIME email transport capabilities.
4  * Copyright: Copyright (c) 2001
5  * @Author Vladimir Radisic
6  * @Version 2.1.5
7  */

8 package org.enhydra.oyster.mail;
9
10 import java.io.InputStream JavaDoc;
11 import java.io.FileInputStream JavaDoc;
12 import java.io.BufferedInputStream JavaDoc;
13 import java.io.IOException JavaDoc;
14 import java.io.File JavaDoc;
15 import org.enhydra.oyster.exception.SMIMEException;
16
17 /**
18  * Analyzes content which will be placed in MimeBodyPart and suggests which
19  * Content-Transfer-Encoding header parameter should be used (7bit,
20  * quoted-printable or base64). ContentAnalyzer makes the following checks, and
21  * according to them decisions about which Content-Transfer-Encoding to suggest:<BR>
22  * <BR>
23  * 7bit: if all checked characters (or bytes) are in group of ASCII characters
24  * which are less than 127 (7F hexadecimal) and higher than 31 (1F hexadecimal).
25  * Characters: HT (Horizontal Tab) 9 (09 hexadecimal), and combinaton of CR
26  * (Carriage Return) 13 (0D hexadecimal) and LF (Line Feed) 11 (0A hexadecimal)
27  * are also allowed. Single usage of CR or LF characters or it's combination
28  * LFCR are not permitted for this type Content-Transfer-Encoding. Also, acording
29  * to RFC822, no line should be longer than 1000 characters with included trailing
30  * CRLF charachters.<BR>
31  * <BR>
32  * quoted-printable: if at least one character does not satisfy previous condition,
33  * and if number of those characters do not exceed 30 percent of all characters.<BR>
34  * <BR>
35  * base64: if number of those characters which do not satisfy 7bit condition
36  * exceed 30 percent of all characters.<BR>
37  */

38 public class ContentAnalyzer
39 {
40
41   /**
42    * Number of bytes for processed content data.
43    */

44   private int numberOfBytes = 0;
45
46   /**
47    * Number of bytes which could not be represented as 7bit for processed
48    * content data.
49    */

50   private int numberOfNon7bitBytes = 0;
51
52   /**
53    * This variable is used for counting line lenght. It shouldn't be higher
54    * than 1000.
55    */

56   private int lineLenght = 0;
57
58   /**
59    * Indicates that line lenght at least once exceeded 1000 characters.
60    */

61   private boolean errorInLineLenght = false;
62
63   /**
64    * Indicates that the previous character was CR (Carriage Return).
65    */

66   private boolean CRCharIndcator = false;
67
68   /**
69    * Simple constructor.
70    */

71   public ContentAnalyzer() {
72
73   }
74
75   /**
76    * Method checks one charachter passed as integer, if it passes condition for
77    * implementation of 7bit Content-Transfer-Encoding. For checking content
78    * data which is constructed from more than one byte, this method must be called
79    * in loop for every byte that belongs to examined content data.
80    * @param dataToCheck integer represetation of passed byte for check
81    */

82   public void isCharFor7BitEncoding(int dataToCheck) {
83     lineLenght++;
84     numberOfBytes++;
85     if(lineLenght > 1000)
86       errorInLineLenght = true;
87     if(dataToCheck < 0x7F && dataToCheck > 0x1F) {
88       return;
89     }
90     if(dataToCheck == 0x09)
91       return;
92     if(dataToCheck == 0x0D) {
93       if(CRCharIndcator) {
94         numberOfNon7bitBytes++;
95         return;
96       }
97       else {
98         CRCharIndcator = true;
99         return;
100       }
101     }
102     if(dataToCheck == 0x0A) {
103       if(CRCharIndcator) {
104         CRCharIndcator = false;
105         lineLenght = 0; // CRLF resets line lenght to 0
106
return;
107       }
108       else {
109         numberOfNon7bitBytes++;
110         return;
111       }
112     }
113     numberOfNon7bitBytes++;
114   }
115
116   /**
117    * Method checks data passed as InputStream which will be used later in the
118    * process of creation of content in MimeBodyPart, if it passes condition for
119    * implementation of 7bit Content-Transfer-Encoding.
120    * @param dataToCheck content data which has to be checked represented as
121    * InputStream
122    * @exception SMIMEException caused by non SMIMEException which is IOException
123    */

124   public void isFor7BitEncoding(InputStream JavaDoc dataToCheck) throws SMIMEException {
125     BufferedInputStream JavaDoc buf = new BufferedInputStream JavaDoc(dataToCheck, 1000);
126     try {
127       int available = buf.available();
128       int markPoint = 0;
129       while(markPoint < available) {
130         buf.mark(markPoint);
131         buf.reset();
132         int byteVal = buf.read();
133         while(byteVal != -1) {
134           this.isCharFor7BitEncoding(byteVal);
135           byteVal = buf.read();
136         }
137         markPoint+=1000;
138       }
139       buf.close();
140     }
141     catch(IOException JavaDoc e) {
142             throw SMIMEException.getInstance(this, e, "isFor7BitEncoding");
143     }
144   }
145
146   /**
147    * Method checks data passed from File which will be used later in the process
148    * of creation of content in MimeBodyPart, if it passes condition for
149    * implementation of 7bit Content-Transfer-Encoding.
150    * @param fileToCheck pointer to file which data has to be checked.
151    * @exception SMIMEException caused by non SMIMEException which is IOException
152    */

153   public void isFor7BitEncoding(File JavaDoc fileToCheck) throws SMIMEException {
154     try {
155       FileInputStream JavaDoc fi = new FileInputStream JavaDoc(fileToCheck);
156       this.isFor7BitEncoding(fi);
157     }
158     catch(IOException JavaDoc e) {
159     throw SMIMEException.getInstance(this, e, "isFor7BitEncoding"); }
160   }
161
162   /**
163    * Performs analyze of content data and accoding to that decides which
164    * Content-Transfer-Encoding to suggesst.
165    */

166   public void analyse() {
167
168   }
169
170   /**
171    * Returns suggested encoding, after finished analyze.
172    * @return the name of Content-Transfer-Encoding header parameter which can
173    * take values: 7bit, quoted-printable, base64 or null in case of error.
174    */

175   public String JavaDoc getPreferedEncoding() {
176     if(numberOfBytes == 0)
177       return "7bit";
178     if( numberOfNon7bitBytes == 0 && !errorInLineLenght)
179       return "7bit";
180     if( numberOfNon7bitBytes == 0 && errorInLineLenght)
181       return "quoted-printable";
182     if( numberOfNon7bitBytes != 0) {
183       int percentage = 100 * numberOfNon7bitBytes / numberOfBytes;
184       if(percentage > 30)
185         return "base64";
186       else
187         return "quoted-printable";
188     }
189     return null;
190   }
191
192   /**
193    * Resets all storaged values in ContentAnalyzer object to default values and
194    * prepares object for new use.
195    */

196   public void reset() {
197     numberOfBytes = 0;
198     numberOfNon7bitBytes = 0;
199     lineLenght = 0;
200     errorInLineLenght = false;
201     CRCharIndcator = false;
202   }
203 }
Popular Tags