1+ package javaxt .exchange ;
2+ import java .io .IOException ;
3+
4+ //******************************************************************************
5+ //** Attachment Class
6+ //******************************************************************************
7+ /**
8+ * Used to represent an attachment associated with a FolderItem.
9+ *
10+ ******************************************************************************/
11+
12+ public class Attachment {
13+
14+ private String id ;
15+ private String name ;
16+ private String contentType ;
17+
18+ public Attachment (org .w3c .dom .Node node ){
19+ org .w3c .dom .NodeList childNodes = node .getChildNodes ();
20+ for (int j =0 ; j <childNodes .getLength (); j ++){
21+ org .w3c .dom .Node childNode = childNodes .item (j );
22+ if (childNode .getNodeType ()==1 ){
23+ String nodeName = childNode .getNodeName ();
24+ if (nodeName .contains (":" )) nodeName = nodeName .substring (nodeName .indexOf (":" )+1 );
25+
26+ if (nodeName .equalsIgnoreCase ("AttachmentId" )){
27+ id = javaxt .xml .DOM .getAttributeValue (childNode , "Id" );
28+ }
29+ else if (nodeName .equalsIgnoreCase ("Name" )){
30+ name = javaxt .xml .DOM .getNodeValue (childNode );
31+ }
32+ else if (nodeName .equalsIgnoreCase ("ContentType" )){
33+ contentType = javaxt .xml .DOM .getNodeValue (childNode );
34+ }
35+ }
36+ }
37+ }
38+
39+ public String getID (){
40+ return id ;
41+ }
42+
43+ public String getName (){
44+ return name ;
45+ }
46+
47+ public String getContentType (){
48+ return contentType ;
49+ }
50+
51+ public String toString (){
52+ return name ;
53+ }
54+
55+ public int hashCode (){
56+ return id .hashCode ();
57+ }
58+
59+ public boolean equals (Object obj ){
60+ if (obj ==null ) return false ;
61+ if (obj instanceof Attachment ){
62+ return ((Attachment ) obj ).id .equals (id );
63+ }
64+ return false ;
65+ }
66+
67+
68+ //**************************************************************************
69+ //** download
70+ //**************************************************************************
71+ /** Used to download the attachment. Returns an input stream with the
72+ * attachment.
73+ */
74+ public java .io .InputStream download (Connection conn ) throws ExchangeException {
75+
76+ String msg =
77+ "<?xml version=\" 1.0\" encoding=\" utf-8\" ?>"
78+ + "<soap:Envelope xmlns:soap=\" http://schemas.xmlsoap.org/soap/envelope/\" xmlns:t=\" http://schemas.microsoft.com/exchange/services/2006/types\" >"
79+ + "<soap:Body>"
80+ + "<GetAttachment xmlns=\" http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\" http://schemas.microsoft.com/exchange/services/2006/types\" >"
81+ + "<AttachmentShape/>"
82+ + "<AttachmentIds><t:AttachmentId Id=\" " + id + "\" /></AttachmentIds>"
83+ + "</GetAttachment>"
84+ + "</soap:Body>"
85+ + "</soap:Envelope>" ;
86+
87+ javaxt .http .Response response = (javaxt .http .Response ) conn .execute (msg , false );
88+ try {
89+ java .io .InputStream inputStream = response .getInputStream ();
90+ java .io .InputStream is = parseResponse (inputStream );
91+ inputStream .close ();
92+ return is ;
93+ }
94+ catch (java .io .IOException e ){
95+ throw new ExchangeException (e .getLocalizedMessage ());
96+ }
97+ }
98+
99+
100+ //**************************************************************************
101+ //** parseResponse
102+ //**************************************************************************
103+ /** Used to parse the "GetAttachmentResponse" response message. Instead of
104+ * using a DOM parser, this method parses the response XML as a stream.
105+ * This is important in order to minimize memory usage when downloading
106+ * large attachments.
107+ */
108+ public static java .io .InputStream parseResponse (java .io .InputStream inputStream )
109+ throws ExchangeException , java .io .IOException {
110+
111+ boolean concat = true ;
112+ StringBuffer tag = new StringBuffer ();
113+ int x =0 ;
114+ while ( (x = inputStream .read ()) != -1 ) {
115+
116+ char c = (char ) x ;
117+
118+ if (c == '<' ){
119+ concat = true ;
120+ }
121+
122+
123+ if (concat ==true ){
124+ tag .append (c );
125+ }
126+
127+
128+ if (c ==('>' ) && concat ==true ){
129+ concat = false ;
130+
131+ if (tag .indexOf ("</" )==-1 ){
132+ String node = tag .toString ().trim ();
133+ String nodeName = node .substring (1 ).trim ();
134+ if (nodeName .endsWith ("/>" )) nodeName = nodeName .substring (0 , nodeName .length ()-2 ).trim ();
135+ else nodeName = nodeName .substring (0 , nodeName .length ()-1 ).trim ();
136+ if (nodeName .contains (" " )) nodeName = nodeName .substring (0 , nodeName .indexOf (" " ));
137+ if (nodeName .contains (":" )) nodeName = nodeName .substring (nodeName .indexOf (":" )+1 );
138+
139+
140+ if (nodeName .toLowerCase ().endsWith ("responsemessage" )){
141+ if (node .toLowerCase ().contains ("error" )){
142+ if (!node .endsWith ("/>" )) node = node .substring (0 , node .length ()-1 ) + "/>" ;
143+ org .w3c .dom .Document XMLDoc = javaxt .xml .DOM .createDocument (node );
144+ String responseClass = javaxt .xml .DOM .getAttributeValue (XMLDoc .getFirstChild (), "ResponseClass" );
145+ if (responseClass .equalsIgnoreCase ("Error" )){
146+ inputStream .close ();
147+ throw new ExchangeException ("Failed to download attachment." );
148+ }
149+ }
150+ }
151+ else if (nodeName .equalsIgnoreCase ("Content" )){
152+ return new javaxt .utils .Base64 .InputStream (new ContentInputStream (inputStream ));
153+ }
154+ }
155+
156+
157+ tag = new StringBuffer ();
158+ }
159+ }
160+ return null ;
161+ }
162+
163+
164+ //**************************************************************************
165+ //** ContentInputStream
166+ //**************************************************************************
167+ /** Provides an input stream for reading the "Content" tag found in a
168+ * "GetAttachmentResponse" message.
169+ */
170+ public static class ContentInputStream extends java .io .InputStream {
171+
172+ private java .io .InputStream inputStream ;
173+
174+ protected ContentInputStream (java .io .InputStream inputStream ){
175+ this .inputStream = inputStream ;
176+ }
177+
178+
179+ /** Returns false. This stream does not support the mark and reset
180+ * methods.
181+ */
182+ public boolean markSupported (){
183+ return false ;
184+ }
185+
186+
187+ /** Reads the next byte of data from the "Content" tag. The byte is
188+ * returned as a positive integer. Returns a value of -1 if there is
189+ * no more data to read (e.g. found whitespace, start of new xml tag,
190+ * or end of stream).
191+ */
192+ public int read () throws IOException {
193+
194+ int x = inputStream .read ();
195+ if (x ==-1 ) return -1 ;
196+ else {
197+ char c = (char ) x ;
198+ if (c == '<' ){
199+ return -1 ;
200+ }
201+ else if (c ==' ' ){
202+ while ( (x = inputStream .read ()) != -1 ) {
203+ c = (char ) x ;
204+ if (c == '<' ) return -1 ;
205+ if (c != ' ' ) return x ;
206+ }
207+ return -1 ;
208+ }
209+ else return x ;
210+ }
211+ }
212+ }
213+
214+ }
0 commit comments