Source code: org/apache/axis/attachments/MultiPartDimeInputStream.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis.attachments;
18
19
20 import org.apache.axis.Part;
21 import org.apache.axis.components.logger.LogFactory;
22 import org.apache.axis.transport.http.HTTPConstants;
23 import org.apache.axis.utils.Messages;
24 import org.apache.commons.logging.Log;
25
26 import javax.activation.DataHandler;
27
28
29 /**
30 * This simulates the multipart stream.
31 *
32 * @author Rick Rineholt
33 */
34 public class MultiPartDimeInputStream extends MultiPartInputStream {
35 protected static Log log =
36 LogFactory.getLog(MultiPartDimeInputStream.class.getName());
37
38 protected java.util.HashMap parts = new java.util.HashMap();
39 protected java.util.LinkedList orderedParts = new java.util.LinkedList();
40 protected int rootPartLength = 0;
41 protected boolean closed = false; //If true the stream has been closed.
42 protected boolean eos = false; //This is set once the SOAP packet has reached the end of stream.
43 //This stream controls and manages the boundary.
44 protected DimeDelimitedInputStream dimeDelimitedStream = null;
45 protected java.io.InputStream soapStream = null; //Set the soap stream once found.
46 protected byte[] boundary = null;
47 protected java.io.ByteArrayInputStream cachedSOAPEnvelope = null; //Caches the soap stream if it is
48 //Still open and a reference to read data in a later attachment occurs.
49 protected String contentId = null;
50
51 /**
52 * Create a new Multipart stream from an input stream.
53 *
54 * @param is the true input stream that is read from
55 * @throws java.io.IOException if it was not possible to build the Multipart
56 */
57 public MultiPartDimeInputStream (java.io.InputStream is)
58 throws java.io.IOException {
59 super(null); //don't cache this stream.
60 soapStream = dimeDelimitedStream = new DimeDelimitedInputStream(is); //The Soap stream must always be first
61 contentId = dimeDelimitedStream.getContentId();
62 }
63
64 public Part getAttachmentByReference(final String[] id)
65 throws org.apache.axis.AxisFault {
66 //First see if we have read it in yet.
67 Part ret = null;
68
69 try {
70 for (int i = id.length - 1; ret == null && i > -1; --i) {
71 ret = (AttachmentPart) parts.get(id[i]);
72 }
73
74 if (null == ret) {
75 ret = readTillFound(id);
76 }
77 log.debug(Messages.getMessage("return02",
78 "getAttachmentByReference(\"" + id + "\"",
79 (ret == null ? "null" : ret.toString())));
80 } catch (java.io.IOException e) {
81 throw new org.apache.axis.AxisFault(e.getClass().getName()
82 + e.getMessage());
83 }
84 return ret;
85 }
86
87 protected void addPart(String contentId, String locationId,
88 AttachmentPart ap) {
89 //For DIME streams Content-Location is ignored.
90 if (contentId != null && contentId.trim().length() != 0)
91 parts.put(contentId, ap);
92 orderedParts.add(ap);
93 }
94
95 //Shouldn't never match
96 protected static final String[] READ_ALL = { " * \0 ".intern()};
97
98 protected void readAll() throws org.apache.axis.AxisFault {
99 try {
100 readTillFound(READ_ALL);
101 } catch (Exception e) {
102 throw org.apache.axis.AxisFault.makeFault(e);
103 }
104 }
105
106 public java.util.Collection getAttachments()
107 throws org.apache.axis.AxisFault {
108 readAll();
109 return new java.util.LinkedList(orderedParts);
110 }
111
112 /**
113 * This will read streams in till the one that is needed is found.
114 *
115 * @param id is the stream being sought
116 * @return a <code>Part</code> matching the ids
117 */
118 protected Part readTillFound(final String[] id)
119 throws java.io.IOException {
120 if (dimeDelimitedStream == null) {
121 //The whole stream has been consumed already
122 return null;
123 }
124 Part ret = null;
125
126 try {
127
128 if (soapStream != null) { //Still on the SOAP stream.
129 if (!eos) { //The SOAP packet has not been fully read yet. Need to store it away.
130
131 java.io.ByteArrayOutputStream soapdata =
132 new java.io.ByteArrayOutputStream(1024 * 8);
133
134 byte[] buf = new byte[1024 * 16];
135 int byteread = 0;
136
137 do {
138 byteread = soapStream.read(buf);
139 if (byteread > 0) {
140 soapdata.write(buf, 0, byteread);
141 }
142
143 } while (byteread > -1);
144 soapdata.close();
145 soapStream.close();
146 soapStream = new java.io.ByteArrayInputStream(
147 soapdata.toByteArray());
148 }
149 dimeDelimitedStream = dimeDelimitedStream.getNextStream();
150 }
151 //Now start searching for the data.
152
153 if (null != dimeDelimitedStream) {
154 do {
155 String contentId = dimeDelimitedStream.getContentId();
156 String type = dimeDelimitedStream.getType();
157
158 if (type != null && !dimeDelimitedStream.getDimeTypeNameFormat().equals(DimeTypeNameFormat.MIME)) {
159 type = "application/uri; uri=\"" + type + "\"";
160 }
161
162
163 ManagedMemoryDataSource source = new ManagedMemoryDataSource(dimeDelimitedStream,
164 ManagedMemoryDataSource.MAX_MEMORY_DISK_CACHED, type, true);
165 DataHandler dh = new DataHandler(source);
166
167 AttachmentPart ap = new AttachmentPart(dh);
168 if (contentId != null) {
169 ap.setMimeHeader(HTTPConstants.HEADER_CONTENT_ID, contentId);
170 }
171
172 addPart(contentId, "", ap);
173
174 for (int i = id.length - 1; ret == null && i > -1; --i) {
175 if (contentId != null && id[i].equals(contentId)) { //This is the part being sought
176 ret = ap;
177 }
178 }
179
180 dimeDelimitedStream =
181 dimeDelimitedStream.getNextStream();
182
183 }
184 while (null == ret && null != dimeDelimitedStream);
185 }
186 } catch (Exception e) {
187 throw org.apache.axis.AxisFault.makeFault(e);
188 }
189
190 return ret;
191 }
192
193 /**
194 * Return the content location.
195 * @return the Content-Location of the stream.
196 * Null if no content-location specified.
197 */
198 public String getContentLocation() {
199 return null;
200 }
201
202 /**
203 * Return the content id of the stream.
204 *
205 * @return the Content-Location of the stream.
206 * Null if no content-location specified.
207 */
208 public String getContentId() {
209 return contentId;
210 }
211
212 public int read(byte[] b, int off, int len)
213 throws java.io.IOException {
214 if (closed) {
215 throw new java.io.IOException(Messages.getMessage(
216 "streamClosed"));
217 }
218 if (eos) {
219 return -1;
220 }
221 int read = soapStream.read(b, off, len);
222
223 if (read < 0) {
224 eos = true;
225 }
226 return read;
227 }
228
229 public int read(byte[] b) throws java.io.IOException {
230 return read(b, 0, b.length);
231 }
232
233 public int read() throws java.io.IOException {
234 if (closed) {
235 throw new java.io.IOException(Messages.getMessage(
236 "streamClosed"));
237 }
238 if (eos) {
239 return -1;
240 }
241 int ret = soapStream.read();
242
243 if (ret < 0) {
244 eos = true;
245 }
246 return ret;
247 }
248
249 public void close() throws java.io.IOException {
250 closed = true;
251 soapStream.close();
252 }
253 }