001 /*
002 * Cobertura - http://cobertura.sourceforge.net/
003 *
004 * Copyright (C) 2005 Grzegorz Lukasik
005 *
006 * Note: This file is dual licensed under the GPL and the Apache
007 * Source License (so that it can be used from both the main
008 * Cobertura classes and the ant tasks).
009 *
010 * Cobertura is free software; you can redistribute it and/or modify
011 * it under the terms of the GNU General Public License as published
012 * by the Free Software Foundation; either version 2 of the License,
013 * or (at your option) any later version.
014 *
015 * Cobertura is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of
017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018 * General Public License for more details.
019 *
020 * You should have received a copy of the GNU General Public License
021 * along with Cobertura; if not, write to the Free Software
022 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
023 * USA
024 */
025
026 package net.sourceforge.cobertura.util;
027
028 import java.io.BufferedReader;
029 import java.io.File;
030 import java.io.FileReader;
031 import java.io.FileWriter;
032 import java.io.IOException;
033 import java.util.ArrayList;
034 import java.util.List;
035
036 import org.apache.log4j.Logger;
037
038 /**
039 * Helper class for storing long command lines inside temporary file.
040 * <p>
041 * Typical usage:
042 *
043 * <pre>
044 * builder = new CommandLineBuilder();
045 * builder.addArg("--someoption");
046 * builder.addArg("optionValue");
047 * ...
048 * builder.saveArgs();
049 * doSomething(builder.getCommandLineFile());
050 * builder.dispose();
051 * </pre>
052 *
053 * It will save options in <code>builder.getCommandLineFile()</code>. Options
054 * will be stored one in a line. To retrieve options from file helper method can
055 * be used (see documentation):
056 *
057 * <pre>
058 * String[] args = CommandLineBuilder.preprocessCommandLineArguments(args);
059 * </pre>
060 *
061 * </p>
062 *
063 * <p>
064 * NOTICE: No protection against line separators in arguments, should be OK for
065 * Cobertura needs.
066 * </p>
067 * <p>
068 * NOTICE: This class depends on local machine settings (line separator, default
069 * encoding). If arguments are saved on different machine than they are loaded,
070 * results are unspecified. No problem in Cobertura.
071 * </p>
072 *
073 * @author Grzegorz Lukasik
074 */
075 public class CommandLineBuilder {
076 private static final Logger logger = Logger
077 .getLogger(CommandLineBuilder.class);
078
079 private static final String LINESEP = System.getProperty("line.separator");
080
081 // File that will be used to store arguments
082 private File commandLineFile = null;
083
084 // Writer that will be used to write arguments to the file
085 private FileWriter commandLineWriter = null;
086
087 /**
088 * Creates a new instance of the builder. Instances of this class should not
089 * be reused to create many command lines.
090 *
091 * @throws IOException
092 * if problems with creating temporary file for storing command
093 * line occur
094 */
095 public CommandLineBuilder() throws IOException {
096 commandLineFile = File.createTempFile("cobertura.", ".cmdline");
097 commandLineFile.deleteOnExit();
098 commandLineWriter = new FileWriter(commandLineFile);
099 }
100
101 /**
102 * Adds command line argument. Each argument can be thought as a single cell
103 * in array passed to main method. This method should not be used after
104 * arguments were saved.
105 *
106 * @param arg command line argument to save
107 * @throws IOException
108 * if problems with temporary file occur
109 * @throws NullPointerException
110 * if <code>arg</code> is <code>null</code>
111 */
112 public void addArg(String arg) throws IOException {
113 if( arg==null)
114 throw new NullPointerException();
115 commandLineWriter.write(arg + LINESEP);
116 }
117
118
119 /**
120 * Adds two command line arguments. Convienience function, calls
121 * {@link #addArg(String)} two times.
122 *
123 * @param arg1 first command line argument to save
124 * @param arg2 second command line argument to save
125 * @throws IOException
126 * if problems with temporary file occur
127 * @throws NullPointerException
128 * if any <code>arg</code> is <code>null</code>
129 */
130 public void addArg(String arg1, String arg2) throws IOException {
131 addArg(arg1);
132 addArg(arg2);
133 }
134
135
136 /**
137 * Saves options and made file available to use. Use method
138 * {@link #getCommandLineFile} to get the file the arguments are saved in.
139 *
140 * @throws IOException
141 * if problems with temporary file occur
142 */
143 public void saveArgs() throws IOException {
144 commandLineWriter.flush();
145 commandLineWriter.close();
146 }
147
148 /**
149 * Gets absolute path to the file with saved arguments. Notice, that however
150 * this method can be used as soon as an instance of this class is created,
151 * arguments should be read from the file after a call to
152 * {@link #saveArgs} method.
153 *
154 * @return absolute path to the file with arguments
155 */
156 public String getCommandLineFile() {
157 return commandLineFile.getAbsolutePath();
158 }
159
160 /**
161 * Explicity frees all resources associated with this instance. Result of
162 * any other method call after disposing an instance of this class is
163 * unspecified.
164 */
165 public void dispose() {
166 commandLineFile.delete();
167 }
168
169 /**
170 * Loads arguments from file if <code>--commandsfile</code> option is used. Checks
171 * if passed array contains <code>--commandsfile</code> String, and if
172 * so arguments from file specified in the very next array cell are read. If
173 * there are more then one <code>--commandsfile</code> the result is unspecified.
174 *
175 * @return The list of arguments read from commandsfile, or
176 * <code>args</code> if commandsfile option was not specified
177 * or the file cannot be read.
178 * @throws NullPointerException if args is null, or any argument is null
179 * @throws IllegalArgumentException if --commandsfile is specified as last option
180 * @throws IOException if I/O related error with temporary command line file occur
181 */
182 public static String[] preprocessCommandLineArguments(String[] args) throws IOException {
183 boolean hasCommandsFile = false;
184 String commandsFileName = null;
185 for (int i = 0; i < args.length; i++) {
186 if ( args[i].equals( "--commandsfile")) {
187 if( i==args.length-1) {
188 throw new IllegalArgumentException("'--commandsfile' specified as last option.");
189 }
190 hasCommandsFile = true;
191 commandsFileName = args[++i];
192 }
193 }
194
195 if (hasCommandsFile) {
196 List arglist = new ArrayList();
197 BufferedReader bufferedReader = null;
198
199 try {
200 bufferedReader = new BufferedReader(new FileReader(
201 commandsFileName));
202 String line;
203
204 while ((line = bufferedReader.readLine()) != null)
205 arglist.add(line);
206
207 } catch (IOException e) {
208 logger.info( "I/O error when reading temporary commands file", e);
209 throw new IOException( "Unable to read temporary commands file "
210 + commandsFileName + ".");
211 } finally {
212 if (bufferedReader != null) {
213 try {
214 bufferedReader.close();
215 } catch (IOException e) {
216 }
217 }
218 }
219
220 args = (String[]) arglist.toArray(new String[arglist.size()]);
221 }
222 return args;
223 }
224 }