EMMA Coverage Report (generated Sat Oct 08 11:41:37 CEST 2011)
[all classes][net.sf.jomic.tools]

COVERAGE SUMMARY FOR SOURCE FILE [ConsoleTools.java]

nameclass, %method, %block, %line, %
ConsoleTools.java100% (1/1)71%  (5/7)88%  (237/270)89%  (48.9/55)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ConsoleTools100% (1/1)71%  (5/7)88%  (237/270)89%  (48.9/55)
getVersion (String): float 0%   (0/1)0%   (0/17)0%   (0/3)
run (String [], File, int): List 0%   (0/1)0%   (0/7)0%   (0/1)
ConsoleTools (): void 100% (1/1)93%  (13/14)98%  (2.9/3)
run (String [], File, int, ConsoleOutputListener): List 100% (1/1)95%  (139/146)96%  (24/25)
getVersion (List): float 100% (1/1)99%  (71/72)95%  (18/19)
asVersionNumber (float): String 100% (1/1)100% (6/6)100% (1/1)
instance (): ConsoleTools 100% (1/1)100% (8/8)100% (3/3)

1// Jomic - a viewer for comic book archives.
2// Copyright (C) 2004-2011 Thomas Aglassinger
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16package net.sf.jomic.tools;
17 
18import java.io.File;
19import java.io.IOException;
20import java.text.NumberFormat;
21import java.util.Iterator;
22import java.util.LinkedList;
23import java.util.List;
24import java.util.Locale;
25import java.util.regex.Pattern;
26 
27import org.apache.commons.logging.Log;
28import org.apache.commons.logging.LogFactory;
29 
30/**
31 *  Utility methods to interact with command line interface.
32 *
33 * @author    Thomas Aglassinger
34 */
35public final class ConsoleTools
36{
37    /**
38     * Pseudo exit code indicating that exit code does not matter.
39     */
40    public static final int NO_RESULT = Integer.MIN_VALUE;
41 
42    private static final float NO_VERSION = -1f;
43 
44    private static /*@ spec_public nullable @*/ ConsoleTools instance;
45 
46    private Log logger;
47 
48    private ConsoleTools() {
49        logger = LogFactory.getLog(ConsoleTools.class);
50    }
51 
52    /**
53     *  Get accessor to unique instance.
54     */
55    //@ ensures instance != null;
56    public static synchronized ConsoleTools instance() {
57        if (instance == null) {
58            instance = new ConsoleTools();
59        }
60        return instance;
61    }
62 
63    /**
64     *  Render version as a version number. Unlike <code>Float.toString()</code>, always use a "."
65     *  and never a "," independant of the current locale.
66     */
67    public String asVersionNumber(float version) {
68        return NumberFormat.getNumberInstance(Locale.US).format(version);
69    }
70 
71    /**
72     *  Extract version from <code>outLines</code>, which are the lines written by a command line
73     *  utility supposed to contain the version number of the tool.
74     *
75     * @return    the version number or a value < 0 in case no number could be found.
76     */
77    float getVersion(List outLines) {
78        float result = NO_VERSION;
79        boolean versionFound = false;
80        Pattern versionNumberPattern = Pattern.compile("\\d+\\.\\d+");
81        Iterator rider = outLines.iterator();
82        NumberFormat englishNumberFormat = NumberFormat.getInstance(Locale.ENGLISH);
83 
84        while (!versionFound && rider.hasNext()) {
85            String line = (String) rider.next();
86            String[] words = versionNumberPattern.split(line, 2);
87 
88            if (words.length == 2) {
89                int startIndex = words[0].length();
90                int endIndex = line.length() - words[1].length();
91                String token = line.substring(startIndex, endIndex);
92 
93                try {
94                    result = englishNumberFormat.parse(token).floatValue();
95                    versionFound = true;
96                    logger.info("found unrar version " + result);
97                } catch (java.text.ParseException error) {
98                    // Ignore error and try with next word.
99                }
100            }
101        }
102        return result;
103    }
104 
105    public float getVersion(String commandPath)
106    throws IOException, InterruptedException {
107    float result;
108    List outLines = run(new String[]{commandPath}, null, NO_RESULT);
109 
110    result = getVersion(outLines);
111    return result;
112}
113 
114   /**
115     *  Runs the specified (shell) command.
116     *
117     * @return                        the lines written to <code>System.out</code> and <code>System.err</code>
118     *      by the command
119     * @throws  IOException           if the exit code is not expectedResult
120     * @throws  InterruptedException
121     * @param  arguments              arguments[0] is the actual command, all other entries are the
122     *      arguments passed to it
123     * @param  path                   the current directory in which the command is to be executed;
124     *      if null, use property "user.dir" (the current working directory)
125     * @param  expectedResult         the expected exit code; typically 0 to indicate a successful
126     *      run
127     */
128    //@ requires arguments.length >= 1;
129    //@ requires \nonnullelements(arguments);
130    public List run(String[] arguments, /*@ nullable @*/ File path, int expectedResult)
131        throws IOException, InterruptedException {
132        return run(arguments, path, expectedResult, null);
133    }
134 
135    /**
136     *  Runs the specified (shell) command.
137     *
138     * @return                        the lines written to <code>System.out</code> and <code>System.err</code>
139     *      by the command
140     * @throws  IOException           if the exit code is not expectedResult
141     * @throws  InterruptedException
142     * @param  arguments              arguments[0] is the actual command, all other entries are the
143     *      arguments passed to it
144     * @param  path                   the current directory in which the command is to be executed;
145     *      if null, use the current working directory (as specified by <code>System.getProperty("user.dir")</code>
146     *      )
147     * @param  expectedResult         the expected exit code; typically 0 to indicate a successful
148     *      run. NO_RESULT means that the exit code should be ignored.
149     * @param  listener               to be informed about every line written to <code>System.out</code>
150     *      or <code>Syst.err</code>
151     */
152    //@ requires arguments.length >= 1;
153    //@ requires \nonnullelements(arguments);
154    public List run(
155            String[] arguments,
156            /*@ nullable @*/ File path,
157            int expectedResult,
158            /*@ nullable @*/ ConsoleOutputListener listener)
159        throws IOException, InterruptedException {
160        File workingDir;
161 
162        if (path == null) {
163            workingDir = new File(System.getProperty("user.dir"));
164        } else {
165            workingDir = path;
166        }
167 
168        List result = new LinkedList();
169 
170        if (logger.isInfoEnabled()) {
171            logger.info("run command: " + arguments[0]);
172            logger.info("  in path \"" + workingDir + "\"");
173            logger.info("  using arguments:");
174            for (int i = 1; i < arguments.length; i += 1) {
175                logger.info("    \"" + arguments[i] + "\"");
176            }
177        }
178        Process process = Runtime.getRuntime().exec(arguments, null, workingDir);
179        ProcessOutputThread errThread =
180                new ProcessOutputThread(
181                process,
182                process.getErrorStream(),
183                result,
184                true,
185                this,
186                listener,
187                ConsoleOutputListener.STREAM_TYPE_ERR);
188 
189        errThread.start();
190 
191        Thread outThread =
192                new ProcessOutputThread(
193                process,
194                process.getInputStream(),
195                result,
196                false,
197                this,
198                listener,
199                ConsoleOutputListener.STREAM_TYPE_OUT);
200 
201        outThread.start();
202 
203        // Wait until the thread to copy the output are done.
204        if (logger.isDebugEnabled()) {
205            logger.debug("wait for notify from err");
206        }
207        errThread.join();
208        if (logger.isDebugEnabled()) {
209            logger.debug("wait for notify from out");
210        }
211        outThread.join();
212 
213        // Check the exit code.
214        int exitCode = process.waitFor();
215 
216        if ((expectedResult != NO_RESULT) && (expectedResult != exitCode)) {
217            throw new ConsoleIOException(arguments, expectedResult, exitCode,
218                    errThread.getLastLineWritten());
219        }
220 
221        return result;
222    }
223}

[all classes][net.sf.jomic.tools]
EMMA 2.0.4217 (C) Vladimir Roubtsov