001    /*
002     * Copyright 1999-2001,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */ 
016    
017    package org.apache.commons.workflow.io;
018    
019    import java.io.BufferedOutputStream;
020    import java.io.File;
021    import java.io.FileOutputStream;
022    import java.io.IOException;
023    import java.io.OutputStreamWriter;
024    import java.util.EmptyStackException;
025    import org.apache.commons.workflow.Context;
026    import org.apache.commons.workflow.StepException;
027    import org.apache.commons.workflow.base.BaseStep;
028    
029    
030    /**
031     * <p>Pop the top value from the evaluation stack, and write its contents
032     * as a string to the specified file in the filesystem (replacing any
033     * previous contents in that file).</p>
034     *
035     * <p>Supported Attributes:</p>
036     * <ul>
037     * <li><strong>encoding</strong> - Character encoding in which to write
038     *     the characters to the specified file, or omitted for the platform
039     *     default encoding.</li>
040     * <li><strong>file</strong> - Relative or absolute operating system pathname
041     *     whose contents are to be written.</li>
042     * </ul>
043     *
044     * <strong>DESIGN QUESTION - What about binary content?</strong>
045     *
046     * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
047     * @author Craig R. McClanahan
048     */
049    
050    public class WriteStep extends BaseStep {
051    
052    
053        // ----------------------------------------------------------= Constructors
054    
055    
056        /**
057         * Construct a default instance of this Step.
058         */
059        public WriteStep() {
060    
061            super();
062    
063        }
064    
065    
066        /**
067         * Construct an instance of this Step with the specified identifier.
068         *
069         * @param id Step identifier
070         */
071        public WriteStep(String id) {
072    
073            super();
074            setId(id);
075    
076        }
077    
078    
079        /**
080         * Construct a fully configured instance of this Step.
081         *
082         * @param id Step identifier
083         * @param encoding Character encoding to use
084         * @param file Relative or absolute pathname
085         */
086        public WriteStep(String id, String encoding, String file) {
087    
088            super();
089            setId(id);
090            setEncoding(encoding);
091            setFile(file);
092    
093        }
094    
095    
096        // ------------------------------------------------------------- Properties
097    
098    
099        /**
100         * The character encoding used to write the contents of this file.
101         */
102        protected String encoding = null;
103    
104        public String getEncoding() {
105            return (this.encoding);
106        }
107    
108        public void setEncoding(String encoding) {
109            this.encoding = encoding;
110        }
111    
112    
113        /**
114         * The relative or absolute pathname of the operating system file.
115         */
116        protected String file = null;
117    
118        public String getFile() {
119            return (this.file);
120        }
121    
122        public void setFile(String file) {
123            this.file = file;
124        }
125    
126    
127        // --------------------------------------------------------- Public Methods
128    
129    
130        /**
131         * Perform the executable actions related to this Step, in the context of
132         * the specified Context.
133         *
134         * @param context The Context that is tracking our execution state
135         *
136         * @exception StepException if a processing error has occurred
137         */
138        public void execute(Context context) throws StepException {
139    
140            // Pop the top value from the evaluation stack
141            Object value = null;
142            try {
143                value = context.pop();
144            } catch (EmptyStackException e) {
145                throw new StepException("Evaluation stack is empty", e, this);
146            }
147            String string = null;
148            if (value instanceof String)
149                string = (String) value;
150            else
151                string = value.toString();
152    
153            // Define variables we will need later
154            FileOutputStream fos = null;
155            BufferedOutputStream bos = null;
156            OutputStreamWriter osw = null;
157            StepException se = null;
158    
159            try {
160    
161                // Construct a suitable OutputStreamWriter
162                fos = new FileOutputStream(file);
163                bos = new BufferedOutputStream(fos, 2048);
164                if (encoding == null)
165                    osw = new OutputStreamWriter(bos);
166                else
167                    osw = new OutputStreamWriter(bos, encoding);
168    
169                // Copy all characters to this file
170                osw.write(string, 0, string.length());
171    
172                // Close the output file
173                osw.flush();
174                osw.close();
175                osw = null;
176                bos = null;
177                fos = null;
178    
179            } catch (IOException e) {
180    
181                se = new StepException("IOException processing '" + file + "'",
182                                       e, this);
183    
184            } finally {
185    
186                if (osw != null) {
187                    try {
188                        osw.close();
189                    } catch (Throwable t) {
190                        ;
191                    }
192                } else if (bos != null) {
193                    try {
194                        bos.close();
195                    } catch (Throwable t) {
196                        ;
197                    }
198                } else if (fos != null) {
199                    try {
200                        fos.close();
201                    } catch (Throwable t) {
202                        ;
203                    }
204                }
205    
206                if (se != null)
207                    (new File(file)).delete();
208    
209            }
210    
211        }
212    
213    
214    }