View Javadoc
1   /*
2    * Copyright 2008, 2009 Ange Optimization ApS
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  package eu.simuline.octave.exec;
17  
18  import java.io.IOException;
19  import java.io.Writer;
20  import java.util.concurrent.Callable;
21  
22  import eu.simuline.octave.exception.OctaveIOException;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  /**
28   * {@link Callable} that writes scripts to the octave process. 
29   * Used in {@link OctaveExec#evalRW(WriteFunctor, ReadFunctor)} only. 
30   * This is complementary to {@link OctaveReaderCallable}. 
31   */
32  final class OctaveWriterCallable implements Callable<Void> {
33  
34      private static final Log LOG = LogFactory
35  	.getLog(OctaveWriterCallable.class);
36  
37      static final String MSG_IOE_WRITE =
38  	"IOException from WriteFunctor";
39  
40      static final String MSG_IOE_SPACER =
41  	"IOException when writing spacer";
42  
43      /**
44       * The writer for scripts passed to octave. 
45       * This is nothing but {@link OctaveExec#processWriter}. 
46       */
47      private final Writer processWriter;
48  
49      /**
50       * The functor the writing task is delegated to. 
51       */
52      private final WriteFunctor writeFunctor;
53  
54      /**
55       * A string essentially consisting of a unique hashvalue. 
56       * It is printed to {@link #processWriter} 
57       * after having applied {@link #writeFunctor}. 
58       * That way the according {@link OctaveReaderCallable} 
59       * detects the end of the read sequence from the octave process.   
60       */
61      private final String spacer;
62  
63      // TBC: strictly speaking,
64      // this goes wrong with a small but positive probability. 
65      /**
66       * Creates a new OctaveWriterCallable with method {@link #call()} 
67       * delegating writing 
68       * 
69       * @param processWriter
70       *    the writer used for writing. 
71       * @param writeFunctor
72       *    the functor the writing process is delegated to. 
73       * @param spacer
74       *    a string essentially consisting of a unique hashvalue 
75       *    printed after applying the write functor.  
76       *    This indicates the end of the sunbsequent according reading process 
77       *    in {@link OctaveExec#evalRW(WriteFunctor, ReadFunctor)}.
78       */
79      OctaveWriterCallable(final Writer processWriter, 
80  			 final WriteFunctor writeFunctor, 
81  			 final String spacer) {
82          this.processWriter = processWriter;
83          this.writeFunctor  = writeFunctor;
84          this.spacer        = spacer;
85      }
86  
87      /**
88       * Calling writes to {@link #processWriter} 
89       * representing the octave process: 
90       * first according to {@link #writeFunctor}, 
91       * i.e. delegates to {@link WriteFunctor#doWrites(Writer)},
92       * then writes <code>printf</code> of {@link #spacer} and then flush. 
93       * That way, {@link OctaveReaderCallable#call()} knows, that reading is completed, 
94       * as soon as the spacer is detected. 
95       * Exceptions are logged on {@link #LOG}. 
96       * 
97       * @throws OctaveIOException 
98       *    if the underlying {@link #writeFunctor} or {@link #processWriter} 
99       *    throws an {@link IOException}. 
100      */
101     @Override
102     public Void call() {
103         // Write to process
104         try {
105 	    this.writeFunctor.doWrites(this.processWriter);
106         } catch (final IOException e) {
107             LOG.debug(MSG_IOE_WRITE, e);
108             throw new OctaveIOException(MSG_IOE_WRITE, e);
109         }
110         try {
111 	    this.processWriter.write("\nprintf(\"\\n%s\\n\", \"" + 
112 				     this.spacer + "\");\n");
113             this.processWriter.flush();
114         } catch (final IOException e) {
115             LOG.debug(MSG_IOE_SPACER, e);
116             throw new OctaveIOException(MSG_IOE_SPACER, e);
117         }
118         LOG.debug("Has written all");
119         return null;
120     }
121 
122 }