|
From: <fd...@us...> - 2009-08-15 09:25:03
|
Revision: 5642
http://jnode.svn.sourceforge.net/jnode/?rev=5642&view=rev
Author: fduminy
Date: 2009-08-15 09:24:53 +0000 (Sat, 15 Aug 2009)
Log Message:
-----------
committed patch from zephyr (http://www.jnode.org/user/9083) for the 'tee' command (http://www.jnode.org/node/3061)
Modified Paths:
--------------
trunk/cli/descriptors/org.jnode.command.file.xml
trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
Added Paths:
-----------
trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java
trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml
Modified: trunk/cli/descriptors/org.jnode.command.file.xml
===================================================================
--- trunk/cli/descriptors/org.jnode.command.file.xml 2009-08-14 16:59:45 UTC (rev 5641)
+++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-08-15 09:24:53 UTC (rev 5642)
@@ -44,6 +44,7 @@
<alias name="rm" class="org.jnode.command.file.DeleteCommand"/>
<alias name="sort" class="org.jnode.command.file.SortCommand"/>
<alias name="tail" class="org.jnode.command.file.TailCommand"/>
+ <alias name="tee" class="org.jnode.command.file.TeeCommand"/>
<alias name="touch" class="org.jnode.command.file.TouchCommand"/>
<alias name="wc" class="org.jnode.command.file.WcCommand"/>
</extension>
@@ -351,6 +352,16 @@
</repeat>
</sequence>
</syntax>
+ <syntax alias="tee">
+ <sequence>
+ <optionSet label="globals">
+ <option argLabel="append" shortName="a" longName="append"/>
+ </optionSet>
+ <repeat>
+ <argument argLabel="files"/>
+ </repeat>
+ </sequence>
+ </syntax>
<syntax alias="touch">
<argument argLabel="file" description="touch the given file"/>
</syntax>
Added: trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java
===================================================================
--- trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java (rev 0)
+++ trunk/cli/src/commands/org/jnode/command/file/TeeCommand.java 2009-08-15 09:24:53 UTC (rev 5642)
@@ -0,0 +1,170 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.command.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.jnode.command.util.IOUtils;
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.FlagArgument;
+
+/**
+ * Copy standard input to standard output, making a copy in zero or more files.<br>
+ * Implementation based on:
+ * http://www.opengroup.org/onlinepubs/9699919799/utilities/tee.html.
+ */
+public class TeeCommand extends AbstractCommand {
+
+ /** Help text for the parameter. */
+ private static final String HELP_FILE = "One or more files that will receive the \"tee-d\" output";
+
+ /** Help text for the append switch. */
+ private static final String HELP_APPEND = "Append to the given FILEs, do not overwrite";
+
+ /** Help text for the command. */
+ private static final String HELP_SUPER = "Copy standard input to each FILE, and also to standard outputd";
+
+ /** The file argument. */
+ private final FileArgument argFile;
+
+ /** The append switch. */
+ private final FlagArgument argAppend;
+
+ /** The standard input. */
+ private InputStream stdin;
+
+ /** The standard output. */
+ private OutputStream stdout;
+
+ /** The files that will receive the output. */
+ private File[] files;
+
+ /** The return code of the command. */
+ private int returnCode = 0;
+
+ /** Flag to indicate if the files should be appended. */
+ private boolean appendFiles;
+
+ /**
+ * In the documentation it is stated that a minimum of 13 files must be
+ * supported. Limit the command to only accept a maximum of 13 files to
+ * limit resource usage.
+ */
+ private static final int MAX_NUMBER_OF_FILES = 13;
+
+ /** Buffer used in stream copies. */
+ private static final int BUFFER_SIZE = 8192;
+
+ /**
+ * Default constructor.
+ */
+ public TeeCommand() {
+ super(HELP_SUPER);
+ int fileFlags = Argument.MULTIPLE;
+ argFile = new FileArgument("files", fileFlags, HELP_FILE);
+ argAppend = new FlagArgument("append", 0, HELP_APPEND);
+ registerArguments(argFile, argAppend);
+ }
+
+ /**
+ * Used to run this command independently.
+ *
+ * @param args the arguments passed to the command
+ * @throws Exception if an error occurs
+ */
+ public static void main(String[] args) throws Exception {
+ new TeeCommand().execute(args);
+ }
+
+ @Override
+ public void execute() throws IOException {
+ OutputStream out = null;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ stdin = getInput().getInputStream();
+ stdout = getOutput().getOutputStream();
+
+ // Parse the command arguments
+ files = argFile.getValues();
+
+ if (files == null || files.length == 0) {
+ // The command is simply ignored if there are no files
+ // Just copy the input to the output and return
+ IOUtils.copyStream(stdin, stdout, buffer);
+ exit(returnCode);
+ }
+
+ if (argAppend.isSet()) {
+ appendFiles = true;
+ }
+
+ // A maximum of MAX_NUMBER_OF_FILES will be used
+ int numberOfFiles = files.length > MAX_NUMBER_OF_FILES ? MAX_NUMBER_OF_FILES : files.length;
+
+ int successfullOpenFiles = 0;
+
+ // Create an array to hold all output files
+ OutputStream[] outFiles = new OutputStream[numberOfFiles];
+
+ try {
+ // Open all output files
+ for (int i = 0; i < numberOfFiles; i++) {
+ if ((out = IOUtils.openOutputstream(files[i], appendFiles)) != null) {
+ outFiles[successfullOpenFiles++] = out;
+ }
+ }
+
+ int count = 0;
+ do {
+ count = stdin.read(buffer);
+ for (int i = 0; i < successfullOpenFiles; i++) {
+ try {
+ outFiles[i].write(buffer, 0, count);
+ } catch (IOException e) {
+ // Only the return code is updated
+ returnCode++;
+ }
+
+ }
+ stdout.write(buffer, 0, count);
+ } while (!(count < BUFFER_SIZE));
+
+ } finally {
+ // Close all open output files
+ for (int i = 0; i < successfullOpenFiles; i++) {
+ try {
+ outFiles[i].close();
+ } catch (IOException e) {
+ // Nothing to do in this case
+ // Just continue closing the files
+ }
+ }
+ }
+
+ // Returns the code
+ exit(returnCode);
+ }
+}
Modified: trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-08-14 16:59:45 UTC (rev 5641)
+++ trunk/cli/src/test/org/jnode/test/command/file/all-file-tests.xml 2009-08-15 09:24:53 UTC (rev 5642)
@@ -6,5 +6,6 @@
<include setName="paste-command-tests.xml"/>
<include setName="sort-command-tests.xml"/>
<include setName="tail-command-tests.xml"/>
+ <include setName="tee-command-tests.xml"/>
<include setName="wc-command-tests.xml"/>
</testSet>
Added: trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml
===================================================================
--- trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml (rev 0)
+++ trunk/cli/src/test/org/jnode/test/command/file/tee-command-tests.xml 2009-08-15 09:24:53 UTC (rev 5642)
@@ -0,0 +1,255 @@
+<testSet title="tee command tests">
+ <plugin id="org.jnode.command.file"/>
+ <plugin id="org.jnode.shell.bjorne" class="org.jnode.test.shell.bjorne.BjornePseudoPlugin"/>
+ <testSpec title="no file" command="tee" runMode="AS_ALIAS" rc="0">
+ <input>1234
+</input>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="single-file" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee @TEMP_DIR@/out
+ </script>
+ <file name="out" input="false">1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12
+ </script>
+ <file name="out" input="false">1234
+</file>
+ <file name="out_1" input="false">1234
+</file>
+ <file name="out_2" input="false">1234
+</file>
+ <file name="out_3" input="false">1234
+</file>
+ <file name="out_4" input="false">1234
+</file>
+ <file name="out_5" input="false">1234
+</file>
+ <file name="out_6" input="false">1234
+</file>
+ <file name="out_7" input="false">1234
+</file>
+ <file name="out_8" input="false">1234
+</file>
+ <file name="out_9" input="false">1234
+</file>
+ <file name="out_10" input="false">1234
+</file>
+ <file name="out_11" input="false">1234
+</file>
+ <file name="out_12" input="false">1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="more-then-max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12 @TEMP_DIR@/out_13
+ </script>
+ <file name="out" input="false">1234
+</file>
+ <file name="out_1" input="false">1234
+</file>
+ <file name="out_2" input="false">1234
+</file>
+ <file name="out_3" input="false">1234
+</file>
+ <file name="out_4" input="false">1234
+</file>
+ <file name="out_5" input="false">1234
+</file>
+ <file name="out_6" input="false">1234
+</file>
+ <file name="out_7" input="false">1234
+</file>
+ <file name="out_8" input="false">1234
+</file>
+ <file name="out_9" input="false">1234
+</file>
+ <file name="out_10" input="false">1234
+</file>
+ <file name="out_11" input="false">1234
+</file>
+ <file name="out_12" input="false">1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+
+
+ <testSpec title="append-single-file" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee -a @TEMP_DIR@/out
+ </script>
+ <file name="out" input="true">Already in File out
+</file>
+ <file name="out" input="false">Already in File out
+1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="append-max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee -a @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12
+ </script>
+
+ <!-- Exiting files -->
+ <file name="out" input="true">Already in File out
+</file>
+ <file name="out_1" input="true">Already in File out_1
+</file>
+ <file name="out_2" input="true">Already in File out_2
+</file>
+ <file name="out_3" input="true">Already in File out_3
+</file>
+ <file name="out_4" input="true">Already in File out_4
+</file>
+ <file name="out_5" input="true">Already in File out_5
+</file>
+ <file name="out_6" input="true">Already in File out_6
+</file>
+ <file name="out_7" input="true">Already in File out_7
+</file>
+ <file name="out_8" input="true">Already in File out_8
+</file>
+ <file name="out_9" input="true">Already in File out_9
+</file>
+ <file name="out_10" input="true">Already in File out_10
+</file>
+ <file name="out_11" input="true">Already in File out_11
+</file>
+ <file name="out_12" input="true">Already in File out_12
+</file>
+
+ <!-- Output files -->
+ <file name="out" input="false">Already in File out
+1234
+</file>
+ <file name="out_1" input="false">Already in File out_1
+1234
+</file>
+ <file name="out_2" input="false">Already in File out_2
+1234
+</file>
+ <file name="out_3" input="false">Already in File out_3
+1234
+</file>
+ <file name="out_4" input="false">Already in File out_4
+1234
+</file>
+ <file name="out_5" input="false">Already in File out_5
+1234
+</file>
+ <file name="out_6" input="false">Already in File out_6
+1234
+</file>
+ <file name="out_7" input="false">Already in File out_7
+1234
+</file>
+ <file name="out_8" input="false">Already in File out_8
+1234
+</file>
+ <file name="out_9" input="false">Already in File out_9
+1234
+</file>
+ <file name="out_10" input="false">Already in File out_10
+1234
+</file>
+ <file name="out_11" input="false">Already in File out_11
+1234
+</file>
+ <file name="out_12" input="false">Already in File out_12
+1234
+</file>
+ <output>1234
+</output>
+ </testSpec>
+ <testSpec title="append-more-than-max-files" command="run" runMode="AS_SCRIPT" rc="0">
+ <script>#!bjorne
+ echo 1234 | tee -a @TEMP_DIR@/out @TEMP_DIR@/out_1 @TEMP_DIR@/out_2 @TEMP_DIR@/out_3 @TEMP_DIR@/out_4 @TEMP_DIR@/out_5 @TEMP_DIR@/out_6 @TEMP_DIR@/out_7 @TEMP_DIR@/out_8 @TEMP_DIR@/out_9 @TEMP_DIR@/out_10 @TEMP_DIR@/out_11 @TEMP_DIR@/out_12 @TEMP_DIR@/out_13
+ </script>
+
+ <!-- Exiting files -->
+ <file name="out" input="true">Already in File out
+</file>
+ <file name="out_1" input="true">Already in File out_1
+</file>
+ <file name="out_2" input="true">Already in File out_2
+</file>
+ <file name="out_3" input="true">Already in File out_3
+</file>
+ <file name="out_4" input="true">Already in File out_4
+</file>
+ <file name="out_5" input="true">Already in File out_5
+</file>
+ <file name="out_6" input="true">Already in File out_6
+</file>
+ <file name="out_7" input="true">Already in File out_7
+</file>
+ <file name="out_8" input="true">Already in File out_8
+</file>
+ <file name="out_9" input="true">Already in File out_9
+</file>
+ <file name="out_10" input="true">Already in File out_10
+</file>
+ <file name="out_11" input="true">Already in File out_11
+</file>
+ <file name="out_12" input="true">Already in File out_12
+</file>
+ <file name="out_13" input="true">Already in File out_13
+</file>
+
+ <!-- Output files -->
+ <file name="out" input="false">Already in File out
+1234
+</file>
+ <file name="out_1" input="false">Already in File out_1
+1234
+</file>
+ <file name="out_2" input="false">Already in File out_2
+1234
+</file>
+ <file name="out_3" input="false">Already in File out_3
+1234
+</file>
+ <file name="out_4" input="false">Already in File out_4
+1234
+</file>
+ <file name="out_5" input="false">Already in File out_5
+1234
+</file>
+ <file name="out_6" input="false">Already in File out_6
+1234
+</file>
+ <file name="out_7" input="false">Already in File out_7
+1234
+</file>
+ <file name="out_8" input="false">Already in File out_8
+1234
+</file>
+ <file name="out_9" input="false">Already in File out_9
+1234
+</file>
+ <file name="out_10" input="false">Already in File out_10
+1234
+</file>
+ <file name="out_11" input="false">Already in File out_11
+1234
+</file>
+ <file name="out_12" input="false">Already in File out_12
+1234
+</file>
+ <file name="out_13" input="false">Already in File out_13
+</file>
+ <output>1234
+</output>
+ </testSpec>
+</testSet>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|