You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ro...@apache.org on 2003/11/03 22:33:36 UTC

cvs commit: jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli2 SourceDestArgument.java

roxspring    2003/11/03 13:33:36

  Added:       cli/src/test/org/apache/commons/cli2/apps CpTest.java
               cli/src/java/org/apache/commons/cli2 SourceDestArgument.java
  Log:
  Added application test for the unix "cp" command.
  Also added example SourceDestArgument implementation.
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/cli/src/test/org/apache/commons/cli2/apps/CpTest.java
  
  Index: CpTest.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/test/org/apache/commons/cli2/apps/CpTest.java,v 1.1 2003/11/03 21:33:36 roxspring Exp $
   * $Revision: 1.1 $
   * $Date: 2003/11/03 21:33:36 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache GroupImpl.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.cli2.apps;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.io.StringReader;
  import java.io.StringWriter;
  
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  
  import org.apache.commons.cli2.Argument;
  import org.apache.commons.cli2.ArgumentBuilder;
  import org.apache.commons.cli2.ArgumentImpl;
  import org.apache.commons.cli2.CommandLine;
  import org.apache.commons.cli2.CommandLineParser;
  import org.apache.commons.cli2.DefaultOptionBuilder;
  import org.apache.commons.cli2.Group;
  import org.apache.commons.cli2.GroupBuilder;
  import org.apache.commons.cli2.HelpFormatter;
  import org.apache.commons.cli2.MissingValueException;
  import org.apache.commons.cli2.Option;
  import org.apache.commons.cli2.OptionException;
  import org.apache.commons.cli2.SourceDestArgument;
  
  /**
   * <p>
   * Test the <code>cp</code> command.  Duplicated Option types
   * are not tested e.g. -a and -d are the same Option type.
   * </p>
   * 
   * <p>
   * The following is the man output for 'cp'.  See http://www.rt.com/man/cp.1.html.
   * </p>
   * 
   * <pre>
   * CP(1)                          FSF                          CP(1)
   * 
   * NAME
   *        cp - copy files and directories
   * 
   * SYNOPSIS
   *        cp [OPTION]... SOURCE DEST
   *        cp [OPTION]... SOURCE... DIRECTORY
   * 
   * DESCRIPTION
   *        Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
   * 
   *        -a, --archive
   *               same as -dpR
   * 
   *        -b, --backup
   *               make backup before removal
   * 
   *        -d, --no-dereference
   *               preserve links
   * 
   *        -f, --force
   *               remove existing destinations, never prompt
   * 
   *        -i, --interactive
   *               prompt before overwrite
   * 
   *        -l, --link
   *               link files instead of copying
   * 
   *        -p, --preserve
   *               preserve file attributes if possible
   * 
   *        -P, --parents
   *               append source path to DIRECTORY
   * 
   *        -r     copy recursively, non-directories as files
   * 
   *        --sparse=WHEN
   *               control creation of sparse files
   * 
   *        -R, --recursive
   *               copy directories recursively
   * 
   *        -s, --symbolic-link
   *               make symbolic links instead of copying
   * 
   *        -S, --suffix=SUFFIX
   *               override the usual backup suffix
   * 
   *        -u, --update
   *               copy  only  when  the SOURCE file is newer than the
   *               destination file or when the  destination  file  is
   *               missing
   * 
   *        -v, --verbose
   *               explain what is being done
   * 
   *        -V, --version-control=WORD
   *               override the usual version control
   * 
   *        -x, --one-file-system
   *               stay on this file system
   * 
   *        --help display this help and exit
   * 
   *        --version
   *               output version information and exit
   * 
   *        By  default,  sparse  SOURCE files are detected by a crude
   *        heuristic and the corresponding DEST file is  made  sparse
   *        as  well.  That is the behavior selected by --sparse=auto.
   *        Specify --sparse=always to create a sparse DEST file when-
   *        ever  the  SOURCE  file contains a long enough sequence of
   *        zero bytes.  Use --sparse=never  to  inhibit  creation  of
   *        sparse files.
   * 
   *        The backup suffix is ~, unless set with SIMPLE_BACKUP_SUF-
   *        FIX.  The version control may be set with VERSION_CONTROL,
   *        values are:
   * 
   *        t, numbered
   *               make numbered backups
   * 
   *        nil, existing
   *               numbered  if  numbered backups exist, simple other-
   *               wise
   * 
   *        never, simple
   *               always make simple backups
   * 
   *        As a special case, cp makes a backup of  SOURCE  when  the
   *        force and backup options are given and SOURCE and DEST are
   *        the same name for an existing, regular file. * </pre>
   * </pre>
   * 
   * @author Rob Oxspring
   * @author John Keyes
   */
  public class CpTest extends TestCase
  {
  
      /** Option Builder */
      private static final DefaultOptionBuilder oBuilder =
          new DefaultOptionBuilder();
  
      /** Argument Builder */
      private static final ArgumentBuilder aBuilder = new ArgumentBuilder();
  
      /** Group Builder */
      private static final GroupBuilder gBuilder = new GroupBuilder();
  
      private Group options;
  
      public static Test suite()
      {
          return new TestSuite(CpTest.class);
      }
  
      private ArgumentImpl source;
      private ArgumentImpl dest;
      private Argument targets;
  
      private Option archive;
      private Option backup;
      private Option noDereference;
      private Option force;
      private Option interactive;
      private Option link;
      private Option preserve;
      private Option parents;
      private Option recursive1;
      private Option sparse;
      private Option recursive2;
      private Option symbolicLink;
      private Option suffix;
      private Option update;
      private Option verbose;
      private Option versionControl;
      private Option oneFileSystem;
      private Option help;
      private Option version;
  
      public void setUp() throws OptionException
      {
          source =
              (ArgumentImpl)aBuilder.withName("SOURCE").withMinimum(1).create();
          dest =
              (ArgumentImpl)aBuilder
                  .withName("DEST")
                  .withMinimum(1)
                  .withMaximum(1)
                  .create();
          targets = new SourceDestArgument(source, dest);
  
          archive =
              oBuilder
                  .withShortName("a")
                  .withLongName("archive")
                  .withDescription("same as -dpR")
                  .create();
  
          backup =
              oBuilder
                  .withShortName("b")
                  .withLongName("backup")
                  .withDescription("make backup before removal")
                  .create();
  
          noDereference =
              oBuilder
                  .withShortName("d")
                  .withLongName("no-dereference")
                  .withDescription("preserve links")
                  .create();
  
          force =
              oBuilder
                  .withShortName("f")
                  .withLongName("force")
                  .withDescription("remove existing destinations, never prompt")
                  .create();
  
          interactive =
              oBuilder
                  .withShortName("i")
                  .withLongName("interactive")
                  .withDescription("prompt before overwrite")
                  .create();
  
          link =
              oBuilder
                  .withShortName("l")
                  .withLongName("link")
                  .withDescription("link files instead of copying")
                  .create();
  
          preserve =
              oBuilder
                  .withShortName("p")
                  .withLongName("preserve")
                  .withDescription("preserve file attributes if possible")
                  .create();
  
          parents =
              oBuilder
                  .withShortName("P")
                  .withLongName("parents")
                  .withDescription("append source path to DIRECTORY")
                  .create();
  
          recursive1 =
              oBuilder
                  .withShortName("r")
                  .withDescription("copy recursively, non-directories as files")
                  .create();
  
          sparse =
              oBuilder
                  .withLongName("sparse")
                  .withDescription("control creation of sparse files")
                  .withArgument(
                      aBuilder
                          .withName("WHEN")
                          .withMinimum(1)
                          .withMaximum(1)
                          .withInitialSeparator('=')
                          .create())
                  .create();
  
          recursive2 =
              oBuilder
                  .withShortName("R")
                  .withLongName("recursive")
                  .withDescription("copy directories recursively")
                  .create();
  
          symbolicLink =
              oBuilder
                  .withShortName("s")
                  .withLongName("symbolic-link")
                  .withDescription("make symbolic links instead of copying")
                  .create();
  
          suffix =
              oBuilder
                  .withShortName("S")
                  .withLongName("suffix")
                  .withDescription("override the usual backup suffix")
                  .withArgument(
                      aBuilder
                          .withName("SUFFIX")
                          .withMinimum(1)
                          .withMaximum(1)
                          .create())
                  .create();
  
          update =
              oBuilder
                  .withShortName("u")
                  .withLongName("update")
                  .withDescription("copy only when the SOURCE file is newer than the destination file or when the destination file is missing")
                  .create();
  
          verbose =
              oBuilder
                  .withShortName("v")
                  .withLongName("verbose")
                  .withDescription("explain what is being done")
                  .create();
  
          versionControl =
              oBuilder
                  .withShortName("V")
                  .withLongName("version-contol")
                  .withDescription("explain what is being done")
                  .withArgument(
                      aBuilder
                          .withName("WORD")
                          .withInitialSeparator('=')
                          .withMinimum(1)
                          .withMaximum(1)
                          .create())
                  .create();
  
          oneFileSystem =
              oBuilder
                  .withShortName("x")
                  .withLongName("one-file-system")
                  .withDescription("stay on this file system")
                  .create();
  
          help =
              oBuilder
                  .withLongName("help")
                  .withDescription("display this help and exit")
                  .create();
  
          version =
              oBuilder
                  .withLongName("version")
                  .withDescription("output version information and exit")
                  .create();
  
          options =
              gBuilder
                  .withOption(archive)
                  .withOption(backup)
                  .withOption(noDereference)
                  .withOption(force)
                  .withOption(interactive)
                  .withOption(link)
                  .withOption(preserve)
                  .withOption(parents)
                  .withOption(recursive1)
                  .withOption(sparse)
                  .withOption(recursive2)
                  .withOption(symbolicLink)
                  .withOption(suffix)
                  .withOption(update)
                  .withOption(verbose)
                  .withOption(versionControl)
                  .withOption(oneFileSystem)
                  .withOption(help)
                  .withOption(version)
                  .withOption(targets)
                  .withName("OPTIONS")
                  .create();
      }
  
      public void testNoSource() throws OptionException
      {
          CommandLineParser parser = new CommandLineParser();
          parser.setGroup(options);
          try
          {
              parser.parse(new String[0]);
          } catch (MissingValueException mve)
          {
              assertEquals(
                  "Missing value(s) SOURCE [SOURCE ...]",
                  mve.getMessage());
          }
      }
  
      public void testOneSource() throws OptionException, IOException
      {
          final String[] args = new String[] { "source1", "dest1" };
          final CommandLineParser parser = new CommandLineParser();
          parser.setGroup(options);
          final CommandLine commandLine = parser.parse(args);
  
          assertTrue(commandLine.getValues(source).contains("source1"));
          assertEquals(1, commandLine.getValues(source).size());
          assertTrue(commandLine.getValues(dest).contains("dest1"));
          assertEquals(1, commandLine.getValues(dest).size());
      }
  
      public void testMultiSource() throws OptionException
      {
          final String[] args =
              new String[] { "source1", "source2", "source3", "dest1" };
          final CommandLineParser parser = new CommandLineParser();
          parser.setGroup(options);
          final CommandLine commandLine = parser.parse(args);
  
          assertTrue(commandLine.getValues(source).contains("source1"));
          assertTrue(commandLine.getValues(source).contains("source2"));
          assertTrue(commandLine.getValues(source).contains("source3"));
          assertEquals(3, commandLine.getValues(source).size());
  
          assertTrue(commandLine.getValues(dest).contains("dest1"));
          assertEquals(1, commandLine.getValues(dest).size());
      }
  
      public void testHelp() throws OptionException, IOException {
          final StringWriter out = new StringWriter();
          final HelpFormatter helpFormatter = new HelpFormatter();
          helpFormatter.setGroup(options);
          helpFormatter.setPrintWriter(new PrintWriter(out));
          helpFormatter.print();
  
          final BufferedReader in = new BufferedReader(new StringReader(out.toString()));
          assertEquals("Usage:                                                                          ",in.readLine());
          assertEquals(" [-a -b -d -f -i -l -p -P -r --sparse <WHEN> -R -s -S <SUFFIX> -u -v -V <WORD>  ",in.readLine());
          assertEquals("-x --help --version] <SOURCE1> [<SOURCE2> ...] <DEST>                           ",in.readLine());
          assertEquals("OPTIONS                                                                         ",in.readLine());
          assertEquals("  -a (--archive)            same as -dpR                                        ",in.readLine());
          assertEquals("  -b (--backup)             make backup before removal                          ",in.readLine());
          assertEquals("  -d (--no-dereference)     preserve links                                      ",in.readLine());
          assertEquals("  -f (--force)              remove existing destinations, never prompt          ",in.readLine());
          assertEquals("  -i (--interactive)        prompt before overwrite                             ",in.readLine());
          assertEquals("  -l (--link)               link files instead of copying                       ",in.readLine());
          assertEquals("  -p (--preserve)           preserve file attributes if possible                ",in.readLine());
          assertEquals("  -P (--parents)            append source path to DIRECTORY                     ",in.readLine());
          assertEquals("  -r                        copy recursively, non-directories as files          ",in.readLine());
          assertEquals("  --sparse                  control creation of sparse files                    ",in.readLine());
          assertEquals("  -R (--recursive)          copy directories recursively                        ",in.readLine());
          assertEquals("  -s (--symbolic-link)      make symbolic links instead of copying              ",in.readLine());
          assertEquals("  -S (--suffix)             override the usual backup suffix                    ",in.readLine());
          assertEquals("  -u (--update)             copy only when the SOURCE file is newer than the    ",in.readLine());
          assertEquals("                            destination file or when the destination file is    ",in.readLine());
          assertEquals("                            missing                                             ",in.readLine());
          assertEquals("  -v (--verbose)            explain what is being done                          ",in.readLine());
          assertEquals("  -V (--version-contol)     explain what is being done                          ",in.readLine());
          assertEquals("  -x (--one-file-system)    stay on this file system                            ",in.readLine());
          assertEquals("  --help                    display this help and exit                          ",in.readLine());
          assertEquals("  --version                 output version information and exit                 ",in.readLine());
          assertEquals("  SOURCE [SOURCE ...]                                                           ",in.readLine());
          assertEquals("  DEST                                                                          ",in.readLine());
          assertNull(in.readLine());
      }
  }
  
  
  1.1                  jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli2/SourceDestArgument.java
  
  Index: SourceDestArgument.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli2/SourceDestArgument.java,v 1.1 2003/11/03 21:33:36 roxspring Exp $
   * $Revision: 1.1 $
   * $Date: 2003/11/03 21:33:36 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache GroupImpl.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.cli2;
  
  import java.util.ArrayList;
  import java.util.Comparator;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  
  /**
   * @author Rob Oxspring
   *
   * To change the template for this generated type comment go to
   * Window - Preferences - Java - Code Generation - Code and Comments
   */
  public class SourceDestArgument extends ArgumentImpl
  {
      private static int sum(final int a, final int b)
      {
          return Math.max(a, Math.max(b, a + b));
      }
  
      private final ArgumentImpl source;
      private final ArgumentImpl dest;
  
      public SourceDestArgument(final ArgumentImpl source, final ArgumentImpl dest)
      {
          this(
              source,
              dest,
              DEFAULT_INITIAL_SEPARATOR,
              DEFAULT_SUBSEQUENT_SEPARATOR,
              DEFAULT_CONSUME_REMAINING,
              null);
      }
  
      public SourceDestArgument(
          final ArgumentImpl source,
          final ArgumentImpl dest,
          final char initialSeparator,
          final char subsequentSeparator,
          final String consumeRemaining,
          final List defaultValues)
      {
          super(
              "SourceDestArgument",
              null,
              sum(source.getMinimum(), dest.getMinimum()),
              sum(source.getMaximum(), dest.getMaximum()),
              initialSeparator,
              subsequentSeparator,
              null,
              consumeRemaining,
              defaultValues,
              0);
  
          this.source = source;
          this.dest = dest;
  
          if (dest.getMinimum() != dest.getMaximum())
          {
              throw new IllegalArgumentException("The dest argument must enforce a fixed number of values");
          }
      }
  
      /* (non-Javadoc)
       * @see org.apache.commons.cli2.Option#appendUsage(java.lang.StringBuffer, java.util.Set, java.util.Comparator)
       */
      public void appendUsage(
          final StringBuffer buffer,
          final Set helpSettings,
          final Comparator comp)
      {
  
          final int length = buffer.length();
  
          source.appendUsage(buffer, helpSettings, comp);
  
          if (buffer.length() != length)
          {
              buffer.append(' ');
          }
  
          dest.appendUsage(buffer, helpSettings, comp);
      }
  
      /* (non-Javadoc)
       * @see org.apache.commons.cli2.Option#helpLines(int, java.util.Set, java.util.Comparator)
       */
      public List helpLines(int depth, Set helpSettings, Comparator comp)
      {
          final List helpLines = new ArrayList();
          helpLines.addAll(source.helpLines(depth, helpSettings, comp));
          helpLines.addAll(dest.helpLines(depth, helpSettings, comp));
          return helpLines;
      }
  
      /* (non-Javadoc)
       * @see org.apache.commons.cli2.Argument#validate(org.apache.commons.cli2.CommandLine, org.apache.commons.cli2.Option)
       */
      public void validate(CommandLine commandLine, Option option)
          throws OptionException
      {
  
          final List values = commandLine.getValues(option);
  
          final int limit = values.size() - dest.getMinimum();
          int count = 0;
  
          final Iterator i = values.iterator();
          while (count++ < limit)
          {
              commandLine.addValue(source, i.next());
          }
          while (i.hasNext())
          {
              commandLine.addValue(dest, i.next());
          }
  
          source.validate(commandLine, source);
          dest.validate(commandLine, dest);
      }
      
      /* (non-Javadoc)
       * @see org.apache.commons.cli2.Option#canProcess(java.lang.String)
       */
      public boolean canProcess(final String arg) {
          return source.canProcess(arg) || dest.canProcess(arg);
      }
  
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org