You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2020/05/29 22:06:32 UTC

[maven-shared-utils] branch MSHARED-297 updated (bb6b6a4 -> dd89556)

This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a change to branch MSHARED-297
in repository https://gitbox.apache.org/repos/asf/maven-shared-utils.git.


    omit bb6b6a4  [MSHARED-297] - Minor code cleanup
    omit 2735fac  [MSHARED-297] - BourneShell unconditionally single quotes executable and arguments
    omit 3b069da  [MSHARED-431] Escape arguments including hash-signs
     add c2ec379  [MSHARED-893] deprecate more file methods we don't need in Java 7+ (#36)
     add 5b7ecec  [MSHARED-894] deprecate close methods since we require Java 7+ (#38)
     add 9530c54  no need of this we are svn free now
     add 1d4471a  no need of this we are svn free now
     add da69ad6  [MSHARED-893] deprecate more methods and clean up api doc and tests (#37)
     add cb239ef  [MSHARED-894] deprecate many easily replaced methods (#39)
     add d1042e0  -a (#43)
     add 660fd80  [MSHARED-860] deprecate constants that are now available in Java 7+ (#42)
     add a51b3eb  [MSHARED-860] deprecate PropertyUtils constructor and clean up docs (#41)
     add 7768b89  docs: correct API docs for clean and trim (#44)
     add 0760867  [MSHARED-898]  prefer JDK classes to DirectoryScanner (#45)
     add a2ce78c  [MSHARED-431] Escape arguments including hash-signs
     new 5e963e7  [MSHARED-297] - BourneShell unconditionally single quotes executable and arguments
     new dd89556  [MSHARED-297] - Minor code cleanup

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (bb6b6a4)
            \
             N -- N -- N   refs/heads/MSHARED-297 (dd89556)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 pom.xml                                            |   1 -
 .../java/org/apache/maven/shared/utils/Os.java     |   1 -
 .../org/apache/maven/shared/utils/PathTool.java    |  11 +
 .../apache/maven/shared/utils/PropertyUtils.java   |  62 ++--
 .../apache/maven/shared/utils/ReaderFactory.java   |  81 +++--
 .../org/apache/maven/shared/utils/StringUtils.java |  23 +-
 .../apache/maven/shared/utils/WriterFactory.java   |  79 +++--
 .../shared/utils/cli/CommandLineException.java     |   1 -
 .../utils/cli/CommandLineTimeOutException.java     |   1 -
 .../maven/shared/utils/cli/CommandLineUtils.java   |   1 -
 .../maven/shared/utils/cli/DefaultConsumer.java    |   1 -
 .../maven/shared/utils/cli/StreamFeeder.java       |   1 -
 .../shared/utils/cli/WriterStreamConsumer.java     |   2 +-
 .../utils/cli/javatool/JavaToolException.java      |   2 +-
 .../maven/shared/utils/introspection/ClassMap.java |   2 +-
 .../shared/utils/introspection/MethodMap.java      |   2 +-
 .../introspection/ReflectionValueExtractor.java    |   2 +-
 .../maven/shared/utils/io/DirectoryScanResult.java |   3 +
 .../maven/shared/utils/io/DirectoryScanner.java    |   8 +-
 .../shared/utils/io/DirectoryWalkListener.java     |  13 +-
 .../maven/shared/utils/io/DirectoryWalker.java     | 337 -------------------
 .../apache/maven/shared/utils/io/FileUtils.java    | 184 ++++++----
 .../org/apache/maven/shared/utils/io/IOUtil.java   | 374 +++++++++++++--------
 .../apache/maven/shared/utils/io/MatchPattern.java |   4 +-
 .../maven/shared/utils/io/MatchPatterns.java       |   2 +
 .../maven/shared/utils/io/ScanConductor.java       |   3 +
 .../maven/shared/utils/io/SelectorUtils.java       |   2 +
 .../maven/shared/utils/io/WalkCollector.java       |   5 +-
 .../maven/shared/utils/xml/XmlWriterUtil.java      |   2 +-
 .../maven/shared/utils/PropertyUtilsTest.java      |  39 +--
 .../ReflectionValueExtractorTest.java              |   2 +-
 .../shared/utils/io/DirectoryScannerTest.java      |   4 +-
 .../maven/shared/utils/io/DirectoryWalkerTest.java |  50 ---
 .../maven/shared/utils/io/FileUtilsTest.java       |  43 +--
 .../apache/maven/shared/utils/io/IOUtilTest.java   |   1 +
 .../shared/utils/testhelpers/FileTestHelper.java   |  11 +-
 .../shared/utils/xml/PrettyPrintXmlWriterTest.java |   2 +-
 .../maven/shared/utils/xml/XmlWriterUtilTest.java  |   2 +-
 38 files changed, 546 insertions(+), 818 deletions(-)
 delete mode 100644 src/main/java/org/apache/maven/shared/utils/io/DirectoryWalker.java
 delete mode 100644 src/test/java/org/apache/maven/shared/utils/io/DirectoryWalkerTest.java


[maven-shared-utils] 02/02: [MSHARED-297] - Minor code cleanup

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch MSHARED-297
in repository https://gitbox.apache.org/repos/asf/maven-shared-utils.git

commit dd895564aa960348c4e1e0fa853f51d81763c136
Author: Rob Oxspring <ro...@imapmail.org>
AuthorDate: Thu May 28 23:50:09 2020 +0100

    [MSHARED-297] - Minor code cleanup
---
 .../maven/shared/utils/cli/shell/BourneShell.java  | 13 ++-----------
 .../apache/maven/shared/utils/cli/shell/Shell.java |  8 ++++----
 .../shared/utils/cli/CommandLineUtilsTest.java     |  5 ++---
 .../shared/utils/cli/shell/BourneShellTest.java    | 22 +++++++---------------
 4 files changed, 15 insertions(+), 33 deletions(-)

diff --git a/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java b/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
index 3317788..e3af665 100644
--- a/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
+++ b/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
@@ -105,13 +105,8 @@ public class BourneShell
         }
 
         String dir = getWorkingDirectoryAsString();
-        StringBuilder sb = new StringBuilder();
-        sb.append( "cd " );
 
-        sb.append( quoteOneItem( dir, false ) );
-        sb.append( " && " );
-
-        return sb.toString();
+        return "cd " + quoteOneItem( dir, false ) + " && ";
     }
 
     /**
@@ -138,10 +133,6 @@ public class BourneShell
             return null;
         }
 
-        StringBuilder sb = new StringBuilder();
-        sb.append( "'" );
-        sb.append( path.replace( "'", "'\"'\"'" ) );
-        sb.append( "'" );
-        return sb.toString();
+        return "'" + path.replace( "'", "'\"'\"'" ) + "'";
     }
 }
diff --git a/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java b/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
index 5ef0d04..0268108 100644
--- a/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
+++ b/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
@@ -104,13 +104,13 @@ public class Shell
      */
     String[] getShellArgs()
     {
-        if ( ( shellArgs == null ) || shellArgs.isEmpty() )
+        if ( shellArgs.isEmpty() )
         {
             return null;
         }
         else
         {
-            return shellArgs.toArray( new String[shellArgs.size()] );
+            return shellArgs.toArray( new String[0] );
         }
     }
 
@@ -146,7 +146,7 @@ public class Shell
      */
     List<String> getRawCommandLine( String executableParameter, String... argumentsParameter )
     {
-        List<String> commandLine = new ArrayList<String>();
+        List<String> commandLine = new ArrayList<>();
         StringBuilder sb = new StringBuilder();
 
         if ( executableParameter != null )
@@ -280,7 +280,7 @@ public class Shell
     public List<String> getShellCommandLine( String... arguments )
     {
 
-        List<String> commandLine = new ArrayList<String>();
+        List<String> commandLine = new ArrayList<>();
 
         if ( getShellCommand() != null )
         {
diff --git a/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java b/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java
index 50d9336..079d0d1 100644
--- a/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java
+++ b/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java
@@ -148,8 +148,8 @@ public class CommandLineUtilsTest
     public void givenAnEscapedSingleQuoteMarkInArgument_whenTranslatingToCmdLineArgs_thenTheQuotationMarkRemainsEscaped()
         throws Exception
     {
-        final String command = "echo \"let\\\'s go\"";
-        final String[] expected = new String[] { "echo", "let\\\'s go" };
+        final String command = "echo \"let\\'s go\"";
+        final String[] expected = new String[] { "echo", "let\\'s go"};
         assertCmdLineArgs( expected, command );
     }
 
@@ -168,5 +168,4 @@ public class CommandLineUtilsTest
         assertEquals( expected.length, actual.length );
         assertEquals( Arrays.asList( expected ), Arrays.asList( actual ) );
     }
-
 }
diff --git a/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java b/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
index 4fbcf84..199f36e 100644
--- a/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
+++ b/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
@@ -42,7 +42,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "/usr/local/bin" );
         sh.setExecutable( "chmod" );
 
-        String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
+        String executable = StringUtils.join( sh.getShellCommandLine().iterator(), " " );
 
         assertEquals( "/bin/sh -c cd '/usr/local/bin' && 'chmod'", executable );
     }
@@ -54,7 +54,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "/usr/local/'something else'" );
         sh.setExecutable( "chmod" );
 
-        String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
+        String executable = StringUtils.join( sh.getShellCommandLine().iterator(), " " );
 
         assertEquals( "/bin/sh -c cd '/usr/local/'\"'\"'something else'\"'\"'' && 'chmod'", executable );
     }
@@ -66,7 +66,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "\\usr\\local\\'something else'" );
         sh.setExecutable( "chmod" );
 
-        String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
+        String executable = StringUtils.join( sh.getShellCommandLine().iterator(), " " );
 
         assertEquals( "/bin/sh -c cd '\\usr\\local\\'\"'\"'something else'\"'\"'' && 'chmod'", executable );
     }
@@ -78,9 +78,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "/usr/bin" );
         sh.setExecutable( "chmod" );
 
-        final String[] args = { "\"some arg with spaces\"" };
-
-        List<String> shellCommandLine = sh.getShellCommandLine( args );
+        List<String> shellCommandLine = sh.getShellCommandLine("\"some arg with spaces\"");
 
         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
@@ -94,9 +92,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "/usr/bin" );
         sh.setExecutable( "chmod" );
 
-        String[] args = { "some arg with spaces" };
-
-        List<String> shellCommandLine = sh.getShellCommandLine( args );
+        List<String> shellCommandLine = sh.getShellCommandLine("some arg with spaces");
 
         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
@@ -110,9 +106,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "/usr/bin" );
         sh.setExecutable( "chmod" );
 
-        String[] args = { "arg'withquote" };
-
-        List<String> shellCommandLine = sh.getShellCommandLine( args );
+        List<String> shellCommandLine = sh.getShellCommandLine("arg'withquote");
 
         assertEquals("cd '/usr/bin' && 'chmod' 'arg'\"'\"'withquote'", shellCommandLine.get(shellCommandLine.size() - 1));
     }
@@ -127,9 +121,7 @@ public class BourneShellTest
         sh.setWorkingDirectory( "/usr/bin" );
         sh.setExecutable( "chmod" );
 
-        String[] args = { ";some&argwithunix$chars" };
-
-        List<String> shellCommandLine = sh.getShellCommandLine( args );
+        List<String> shellCommandLine = sh.getShellCommandLine(";some&argwithunix$chars");
 
         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );


[maven-shared-utils] 01/02: [MSHARED-297] - BourneShell unconditionally single quotes executable and arguments

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch MSHARED-297
in repository https://gitbox.apache.org/repos/asf/maven-shared-utils.git

commit 5e963e7f4d482bc33d125c77e546959efd867e69
Author: Rob Oxspring <ro...@imapmail.org>
AuthorDate: Thu May 28 23:29:05 2020 +0100

    [MSHARED-297] - BourneShell unconditionally single quotes executable and arguments
---
 .../maven/shared/utils/cli/shell/BourneShell.java  | 49 +++++++++-------------
 .../apache/maven/shared/utils/cli/shell/Shell.java | 39 ++++++++++++-----
 .../shared/utils/cli/shell/BourneShellTest.java    | 32 ++++++++++----
 3 files changed, 70 insertions(+), 50 deletions(-)

diff --git a/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java b/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
index 02586af..3317788 100644
--- a/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
+++ b/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
@@ -23,7 +23,6 @@ package org.apache.maven.shared.utils.cli.shell;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.maven.shared.utils.Os;
-import org.apache.maven.shared.utils.StringUtils;
 
 /**
  * @author Jason van Zyl
@@ -31,19 +30,16 @@ import org.apache.maven.shared.utils.StringUtils;
 public class BourneShell
     extends Shell
 {
-    private static final char DOUBLE_QUOTATION = '"';
-
-    private static final char[] BASH_QUOTING_TRIGGER_CHARS =
-        { ' ', '$', ';', '&', '|', '<', '>', '*', '?', '(', ')', '[', ']', '{', '}', '`', '#' };
 
     /**
      * Create instance of BourneShell.
      */
     public BourneShell()
     {
+        setUnconditionalQuoting( true );
         setShellCommand( "/bin/sh" );
-        setArgumentQuoteDelimiter( DOUBLE_QUOTATION );
-        setExecutableQuoteDelimiter( DOUBLE_QUOTATION );
+        setArgumentQuoteDelimiter( '\'' );
+        setExecutableQuoteDelimiter( '\'' );
         setSingleQuotedArgumentEscaped( true );
         setSingleQuotedExecutableEscaped( false );
         setQuotedExecutableEnabled( true );
@@ -59,7 +55,7 @@ public class BourneShell
             return super.getExecutable();
         }
 
-        return unifyQuotes( super.getExecutable() );
+        return quoteOneItem( super.getExecutable(), true );
     }
 
     /** {@inheritDoc} */
@@ -112,47 +108,40 @@ public class BourneShell
         StringBuilder sb = new StringBuilder();
         sb.append( "cd " );
 
-        sb.append( unifyQuotes( dir ) );
+        sb.append( quoteOneItem( dir, false ) );
         sb.append( " && " );
 
         return sb.toString();
     }
 
-    /** {@inheritDoc} */
-    protected char[] getQuotingTriggerChars()
-    {
-        return BASH_QUOTING_TRIGGER_CHARS;
-    }
-
     /**
      * <p>Unify quotes in a path for the Bourne Shell.</p>
      * <p/>
      * <pre>
-     * BourneShell.unifyQuotes(null)                       = null
-     * BourneShell.unifyQuotes("")                         = (empty)
-     * BourneShell.unifyQuotes("/test/quotedpath'abc")     = /test/quotedpath\'abc
-     * BourneShell.unifyQuotes("/test/quoted path'abc")    = "/test/quoted path'abc"
-     * BourneShell.unifyQuotes("/test/quotedpath\"abc")    = "/test/quotedpath\"abc"
-     * BourneShell.unifyQuotes("/test/quoted path\"abc")   = "/test/quoted path\"abc"
-     * BourneShell.unifyQuotes("/test/quotedpath\"'abc")   = "/test/quotedpath\"'abc"
-     * BourneShell.unifyQuotes("/test/quoted path\"'abc")  = "/test/quoted path\"'abc"
+     * BourneShell.quoteOneItem(null)                       = null
+     * BourneShell.quoteOneItem("")                         = ''
+     * BourneShell.quoteOneItem("/test/quotedpath'abc")     = '/test/quotedpath'"'"'abc'
+     * BourneShell.quoteOneItem("/test/quoted path'abc")    = '/test/quoted pat'"'"'habc'
+     * BourneShell.quoteOneItem("/test/quotedpath\"abc")    = '/test/quotedpath"abc'
+     * BourneShell.quoteOneItem("/test/quoted path\"abc")   = '/test/quoted path"abc'
+     * BourneShell.quoteOneItem("/test/quotedpath\"'abc")   = '/test/quotedpath"'"'"'abc'
+     * BourneShell.quoteOneItem("/test/quoted path\"'abc")  = '/test/quoted path"'"'"'abc'
      * </pre>
      *
      * @param path not null path.
      * @return the path unified correctly for the Bourne shell.
      */
-    private static String unifyQuotes( String path )
+    protected String quoteOneItem( String path, boolean isExecutable )
     {
         if ( path == null )
         {
             return null;
         }
 
-        if ( path.indexOf( ' ' ) == -1 && path.indexOf( '\'' ) != -1 && path.indexOf( '"' ) == -1 )
-        {
-            return StringUtils.escape( path );
-        }
-
-        return StringUtils.quoteAndEscape( path, '\"', BASH_QUOTING_TRIGGER_CHARS );
+        StringBuilder sb = new StringBuilder();
+        sb.append( "'" );
+        sb.append( path.replace( "'", "'\"'\"'" ) );
+        sb.append( "'" );
+        return sb.toString();
     }
 }
diff --git a/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java b/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
index bec555e..5ef0d04 100644
--- a/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
+++ b/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
@@ -49,6 +49,8 @@ public class Shell
 
     private boolean quotedArgumentsEnabled = true;
 
+    private boolean unconditionalQuoting = false;
+
     private String executable;
 
     private String workingDir;
@@ -112,6 +114,19 @@ public class Shell
         }
     }
 
+    protected String quoteOneItem( String inputString, boolean isExecutable )
+    {
+        char[] escapeChars = getEscapeChars( isSingleQuotedExecutableEscaped(), isDoubleQuotedExecutableEscaped() );
+        return StringUtils.quoteAndEscape(
+                inputString,
+                isExecutable ? getExecutableQuoteDelimiter() : getArgumentQuoteDelimiter(),
+                escapeChars,
+                getQuotingTriggerChars(),
+                '\\',
+                unconditionalQuoting
+        );
+    }
+
     /**
      * Get the command line for the provided executable and arguments in this shell
      *
@@ -144,15 +159,11 @@ public class Shell
 
             if ( isQuotedExecutableEnabled() )
             {
-                char[] escapeChars =
-                    getEscapeChars( isSingleQuotedExecutableEscaped(), isDoubleQuotedExecutableEscaped() );
-
-                sb.append( StringUtils.quoteAndEscape( getExecutable(), getExecutableQuoteDelimiter(), escapeChars,
-                                                       getQuotingTriggerChars(), '\\', false ) );
+                sb.append( quoteOneItem( executableParameter, true ) );
             }
             else
             {
-                sb.append( getExecutable() );
+                sb.append( executableParameter );
             }
         }
         for ( String argument : argumentsParameter )
@@ -164,10 +175,7 @@ public class Shell
 
             if ( isQuotedArgumentsEnabled() )
             {
-                char[] escapeChars = getEscapeChars( isSingleQuotedArgumentEscaped(), isDoubleQuotedArgumentEscaped() );
-
-                sb.append( StringUtils.quoteAndEscape( argument, getArgumentQuoteDelimiter(), escapeChars,
-                                                       getQuotingTriggerChars(), '\\', false ) );
+                sb.append( quoteOneItem( argument, false ) );
             }
             else
             {
@@ -284,7 +292,7 @@ public class Shell
             commandLine.addAll( getShellArgsList() );
         }
 
-        commandLine.addAll( getCommandLine( getExecutable(), arguments ) );
+        commandLine.addAll( getCommandLine( executable, arguments ) );
 
         return commandLine;
 
@@ -398,4 +406,13 @@ public class Shell
         this.singleQuotedExecutableEscaped = singleQuotedExecutableEscaped;
     }
 
+    public boolean isUnconditionalQuoting()
+    {
+        return unconditionalQuoting;
+    }
+
+    public void setUnconditionalQuoting( boolean unconditionalQuoting )
+    {
+        this.unconditionalQuoting = unconditionalQuoting;
+    }
 }
diff --git a/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java b/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
index 7d5c456..4fbcf84 100644
--- a/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
+++ b/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
@@ -44,7 +44,7 @@ public class BourneShellTest
 
         String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
 
-        assertEquals( "/bin/sh -c cd /usr/local/bin && chmod", executable );
+        assertEquals( "/bin/sh -c cd '/usr/local/bin' && 'chmod'", executable );
     }
 
     public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes()
@@ -56,7 +56,7 @@ public class BourneShellTest
 
         String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
 
-        assertEquals( "/bin/sh -c cd \"/usr/local/\'something else\'\" && chmod", executable );
+        assertEquals( "/bin/sh -c cd '/usr/local/'\"'\"'something else'\"'\"'' && 'chmod'", executable );
     }
 
     public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes_BackslashFileSep()
@@ -68,7 +68,7 @@ public class BourneShellTest
 
         String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
 
-        assertEquals( "/bin/sh -c cd \"\\usr\\local\\\'something else\'\" && chmod", executable );
+        assertEquals( "/bin/sh -c cd '\\usr\\local\\'\"'\"'something else'\"'\"'' && 'chmod'", executable );
     }
 
     public void testPreserveSingleQuotesOnArgument()
@@ -84,7 +84,7 @@ public class BourneShellTest
 
         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
-        assertTrue( cli.endsWith( args[0] ) );
+        assertTrue( cli.endsWith( "'\"some arg with spaces\"'" ) );
     }
 
     public void testAddSingleQuotesOnArgumentWithSpaces()
@@ -100,7 +100,21 @@ public class BourneShellTest
 
         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
-        assertTrue( cli.endsWith( "\"" + args[0] + "\"" ) );
+        assertTrue( cli.endsWith("'some arg with spaces'"));
+    }
+
+    public void testAddArgumentWithSingleQuote()
+    {
+        Shell sh = newShell();
+
+        sh.setWorkingDirectory( "/usr/bin" );
+        sh.setExecutable( "chmod" );
+
+        String[] args = { "arg'withquote" };
+
+        List<String> shellCommandLine = sh.getShellCommandLine( args );
+
+        assertEquals("cd '/usr/bin' && 'chmod' 'arg'\"'\"'withquote'", shellCommandLine.get(shellCommandLine.size() - 1));
     }
 
     public void testArgumentsWithSemicolon()
@@ -119,7 +133,7 @@ public class BourneShellTest
 
         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
-        assertTrue( cli.endsWith( "\"" + args[0] + "\"" ) );
+        assertTrue( cli.endsWith( "';some&argwithunix$chars'" ) );
 
         Commandline commandline = new Commandline( newShell() );
         commandline.setExecutable( "chmod" );
@@ -132,7 +146,7 @@ public class BourneShellTest
 
         assertEquals( "/bin/sh", lines.get( 0 ) );
         assertEquals( "-c", lines.get( 1 ) );
-        assertEquals( "chmod --password \";password\"", lines.get( 2 ) );
+        assertEquals( "'chmod' '--password' ';password'", lines.get( 2 ) );
 
         commandline = new Commandline( newShell() );
         commandline.setExecutable( "chmod" );
@@ -144,7 +158,7 @@ public class BourneShellTest
 
         assertEquals( "/bin/sh", lines.get( 0) );
         assertEquals( "-c", lines.get( 1 ) );
-        assertEquals( "chmod --password \";password\"", lines.get( 2 ) );
+        assertEquals( "'chmod' '--password' ';password'", lines.get( 2 ) );
 
         commandline = new Commandline( new CmdShell() );
         commandline.getShell().setQuotedArgumentsEnabled( true );
@@ -193,7 +207,7 @@ public class BourneShellTest
 
         assertEquals( "/bin/sh", lines.get( 0 ) );
         assertEquals( "-c", lines.get( 1 ) );
-        assertEquals( "chmod \" \" \"|\" \"&&\" \"||\" \";\" \";;\" \"&\" \"()\" \"<\" \"<<\" \">\" \">>\" \"*\" \"?\" \"[\" \"]\" \"{\" \"}\" \"`\" \"#\"",
+        assertEquals( "'chmod' ' ' '|' '&&' '||' ';' ';;' '&' '()' '<' '<<' '>' '>>' '*' '?' '[' ']' '{' '}' '`' '#'",
                       lines.get( 2 ) );
     }