1 /*
2 * Copyright 1999-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.commons.workflow.io;
18
19
20 import java.io.BufferedInputStream;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.io.IOException;
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.net.URLConnection;
27 import java.util.EmptyStackException;
28 import org.apache.commons.workflow.Context;
29 import org.apache.commons.workflow.StepException;
30 import org.apache.commons.workflow.base.BaseStep;
31 import org.apache.commons.workflow.util.WorkflowUtils;
32
33
34 /**
35 * <p>Retrieve the contents of a specified URL resource, and push the
36 * contents as a String object onto the evaluation stack.</p>
37 *
38 * <p>Supported Attributes:</p>
39 * <ul>
40 * <li><strong>url</strong> - URL of the resource to be retrieved, or
41 * omitted to pop a computed String value from the top of the
42 * evaluation stack.</li>
43 * </ul>
44 *
45 * <strong>DESIGN QUESTION - What about binary content?</strong>
46 *
47 * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
48 * @author Craig R. McClanahan
49 */
50
51 public class GetStep extends BaseStep {
52
53
54 // ----------------------------------------------------------= Constructors
55
56
57 /**
58 * Construct a default instance of this Step.
59 */
60 public GetStep() {
61
62 super();
63
64 }
65
66
67 /**
68 * Construct an instance of this Step with the specified identifier.
69 *
70 * @param id Step identifier
71 */
72 public GetStep(String id) {
73
74 super();
75 setId(id);
76
77 }
78
79
80 /**
81 * Construct a fully configured instance of this Step.
82 *
83 * @param id Step identifier
84 * @param url Resource url
85 */
86 public GetStep(String id, String url) {
87
88 super();
89 setId(id);
90 setUrl(url);
91
92 }
93
94
95 // ------------------------------------------------------------- Properties
96
97
98 /**
99 * The URL of the resource to be retrieved.
100 */
101 protected String url = null;
102
103 public String getUrl() {
104 return (this.url);
105 }
106
107 public void setUrl(String url) {
108 this.url = url;
109 }
110
111
112 // --------------------------------------------------------- Public Methods
113
114
115 /**
116 * Perform the executable actions related to this Step, in the context of
117 * the specified Context.
118 *
119 * @param context The Context that is tracking our execution state
120 *
121 * @exception StepException if a processing error has occurred
122 */
123 public void execute(Context context) throws StepException {
124
125 // Get the remote URL we will be contacting
126 Object remote = this.url;
127 URL remoteURL = null;
128 if (remote == null) {
129 try {
130 remote = (String) context.pop();
131 } catch (EmptyStackException e) {
132 throw new StepException("Evaluation stack is empty", this);
133 }
134 }
135 if (remote instanceof URL) {
136 remoteURL = (URL) remote;
137 } else if (remote instanceof String) {
138 try {
139 remoteURL = new URL((String) remote);
140 } catch (MalformedURLException e) {
141 throw new StepException("Invalid URL '" + remote + "'",
142 e, this);
143 }
144 } else {
145 try {
146 remoteURL = new URL(remote.toString());
147 } catch (MalformedURLException e) {
148 throw new StepException("Invalid URL '" + remote + "'",
149 e, this);
150 }
151 }
152
153 // Define variables we will need later
154 URLConnection conn = null;
155 InputStream is = null;
156 BufferedInputStream bis = null;
157 InputStreamReader isr = null;
158 StringBuffer sb = null;
159 StepException se = null;
160
161 try {
162
163 // Open a connection to the specified URL
164 conn = remoteURL.openConnection();
165 conn.setDoInput(true);
166 conn.setDoOutput(false);
167 conn.connect();
168 int contentLength = conn.getContentLength();
169 if (contentLength < 2048)
170 contentLength = 2048;
171 sb = new StringBuffer(contentLength);
172
173 // Parse the character encoding to be used
174 String contentType = conn.getContentType();
175 String encoding =
176 WorkflowUtils.parseCharacterEncoding(contentType);
177
178 // Construct a suitable InputStreamReader
179 is = conn.getInputStream();
180 bis = new BufferedInputStream(is, 2048);
181 if (encoding == null)
182 isr = new InputStreamReader(bis);
183 else
184 isr = new InputStreamReader(bis, encoding);
185
186 // Copy all characters from this resource
187 while (true) {
188 int ch = isr.read();
189 if (ch < 0)
190 break;
191 sb.append((char) ch);
192 }
193
194 // Close the input file
195 isr.close();
196 isr = null;
197 bis = null;
198 is = null;
199
200 } catch (IOException e) {
201
202 se = new StepException("IOException processing '" + remoteURL +
203 "'", e, this);
204
205 } finally {
206
207 if (isr != null) {
208 try {
209 isr.close();
210 } catch (Throwable t) {
211 ;
212 }
213 } else if (bis != null) {
214 try {
215 bis.close();
216 } catch (Throwable t) {
217 ;
218 }
219 } else if (is != null) {
220 try {
221 is.close();
222 } catch (Throwable t) {
223 ;
224 }
225 }
226
227 }
228
229 // Push results or throw exception as appropriate
230 if (se != null)
231 throw se;
232 context.push(sb.toString());
233
234 }
235
236
237 }