1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.applications.parameter;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15
16 import org.astrogrid.applications.CeaException;
17 import org.astrogrid.applications.beans.v1.parameters.ParameterValue;
18 import org.astrogrid.applications.description.ParameterDescription;
19 import org.astrogrid.applications.parameter.protocol.ExternalValue;
20 import org.astrogrid.io.Piper;
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.io.OutputStream;
26 import java.io.OutputStreamWriter;
27 import java.io.PrintWriter;
28 import java.io.Reader;
29 import java.io.StringWriter;
30
31
32 /*** The default implementation of {@link org.astrogrid.applications.parameter.ParameterAdapter}
33 * <p/>
34 * Handles both direct and indirect parameters, returing them as an in-memory string.
35 * @see org.astrogrid.applications.parameter.protocol.ProtocolLibrary#getExternalValue(ParameterValue)
36 * @author Noel Winstanley (nw@jb.man.ac.uk)
37 * @author Paul Harrison (pah@jb.man.ac.uk)
38 * @todo should really do different things according to what the type of the parameter is.
39 * @todo check whether it is really appropriate use Readers and Writers to access the indirect parameters
40 */
41 public class DefaultParameterAdapter extends AbstractParameterAdapter {
42 /***
43 * Constructor.
44 * @param val
45 * @param description
46 * @param externalVal
47 */
48 public DefaultParameterAdapter(ParameterValue val, ParameterDescription description, ExternalValue externalVal) {
49 super(val, description, externalVal);
50
51 }
52
53 /***
54 * Commons Logger for this class
55 */
56 private static final Log logger = LogFactory
57 .getLog(DefaultParameterAdapter.class);
58
59 /***
60 * retreives the value for this paramter
61 * if the parameter is direct, just return the value of the parameter value itself,
62 * if indirect, retreive the value from the {@link #externalVal}
63 * @return always returns the string value of this parameter
64 * */
65 public Object process() throws CeaException {
66 if (externalVal == null) {
67 return val.getValue();
68 } else {
69 Reader r = null;
70 StringWriter sw = null;
71 try {
72 sw = new StringWriter();
73 r = new InputStreamReader(externalVal.read());
74 Piper.pipe(r, sw);
75
76 return sw.toString();
77 }
78 catch (IOException e) {
79 throw new CeaException("Could not process parameter " + val.getName());
80 } finally {
81 if (r != null) {
82 try {
83 r.close();
84 } catch (IOException e) {
85 logger.warn("could not close reader",e);
86 }
87 }
88 if (sw != null) {
89 try {
90 sw.close();
91 } catch (IOException e) {
92 logger.warn("could not close writer",e);
93 }
94 }
95 }
96
97 }
98 }
99
100 /***
101 * Writes the value of an output parameter back to the parameter storage.
102 * That storage may be an internal buffer (a "direct" parameter) or
103 * an external location (an "indirect" parameter).
104 * Various forms of the value are supported: null object reference;
105 * byte array; InputStream; any other object. Binary values, such
106 * as the contents of FITS files, should be given as byte arrays or
107 * streams. Other values can be given as any object for which the
108 * toString() method produces a valid copy of the value. Note that
109 * the bit pattern of binary values is only sure to be preserved
110 * for an indirect parameter. In a direct parameter, the value is
111 * forced into a String object and may be corrupted in the process.
112 */
113 public void writeBack(Object o) throws CeaException {
114 if (this.externalVal == null) {
115 this.writeBackToParameterValue(o);
116 }
117 else {
118 this.writeBackToExternalValue(o);
119 }
120 }
121
122 /***
123 * Writes a parameter value to a local ParameterValue object. The value
124 * is always sent as a String, since ParameterValue requires this.
125 * Binary values (e.g. FITS files) are expected to arrive as byte arrays;
126 * these don't have an effective toString() method and are treated specially.
127 *
128 * @param o The object to be written out.
129 */
130 private void writeBackToParameterValue(Object o) throws CeaException {
131 try {
132 if (o == null) {
133 this.val.setValue("<null>");
134 }
135 else if (o instanceof byte[]) {
136 this.val.setValue(new String((byte[])o));
137 }
138 else if (o instanceof InputStream) {
139 InputStream is = (InputStream)o;
140 ByteArrayOutputStream os = new ByteArrayOutputStream();
141 this.pipe(is, os);
142 this.val.setValue(new String(os.toByteArray()));
143 }
144 else {
145 this.val.setValue(o.toString());
146 }
147 }
148 catch (Exception e) {
149 throw new CeaException("Failed to write back a value to a direct parameter.", e);
150 }
151 }
152
153 /***
154 * Writes a parameter value to an ExternalValue object.
155 *
156 * @param o The object to be written out.
157 */
158 private void writeBackToExternalValue(Object o) throws CeaException {
159 try {
160 if (o == null) {
161 PrintWriter pw = new PrintWriter(new OutputStreamWriter(externalVal.write()));
162 pw.println("<null>");
163 pw.close();
164 }
165 else if (o instanceof byte[]) {
166 OutputStream os = this.externalVal.write();
167 os.write((byte[])o);
168 os.close();
169 }
170 else if (o instanceof InputStream) {
171 InputStream is = (InputStream)o;
172 OutputStream os = this.externalVal.write();
173 this.pipe(is, os);
174 os.close();
175 }
176 else {
177 PrintWriter pw = new PrintWriter(new OutputStreamWriter(externalVal.write()));
178 pw.print(o);
179 pw.close();
180 }
181 }
182 catch (Exception e) {
183 throw new CeaException("Failed to write back a value to an indirect parameter.", e);
184 }
185
186 }
187
188 /***
189 * Copies an input stream onto an output stream.
190 */
191 private void pipe(InputStream is, OutputStream os) throws IOException {
192 byte[] block = new byte[65536];
193 int read = is.read(block);
194 while (read > -1) {
195 os.write(block, 0, read);
196 read = is.read(block);
197 }
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261