[Title] Add help detail for web-signing
authorBon-Yong Lee <bonyong.lee@samsung.com>
Wed, 5 Sep 2012 06:03:10 +0000 (15:03 +0900)
committerBon-Yong Lee <bonyong.lee@samsung.com>
Wed, 5 Sep 2012 06:03:10 +0000 (15:03 +0900)
[Type]      Enhancement
[Module]    Sub
[Priority]  Minor
[CQ#]       // CQ Issue Number
[Redmine#]  // Redmine Isuue Number
[Problem]   // Problem Description
[Cause]     // Cause Description
[Solution]  // Solution Description
[TestCase]  // Executed the test-target (How to)

org.tizen.cli/.settings/org.eclipse.core.resources.prefs [new file with mode: 0755]
org.tizen.cli/doc/install/doc/schema/profiles.xsd [new file with mode: 0755]
org.tizen.cli/src/org/tizen/cli/exec/AbstractLauncher.java [changed mode: 0644->0755]
org.tizen.cli/src/org/tizen/cli/exec/Help.java [new file with mode: 0755]
org.tizen.cli/src/org/tizen/cli/exec/sign/Main.java
org.tizen.cli/src/org/tizen/cli/exec/sign/Main.properties [new file with mode: 0755]
org.tizen.cli/src/org/tizen/cli/exec/sign/profile.help [new file with mode: 0755]
org.tizen.cli/test/src/org/tizen/cli/exec/AbstractLauncherTest.java [changed mode: 0644->0755]
org.tizen.cli/test/src/org/tizen/cli/exec/HelpTest.java [new file with mode: 0755]
org.tizen.cli/test/src/org/tizen/cli/exec/TargetDeviceSelectorTest.java [changed mode: 0644->0755]
org.tizen.cli/test/src/org/tizen/cli/exec/sign/MainTest.java

diff --git a/org.tizen.cli/.settings/org.eclipse.core.resources.prefs b/org.tizen.cli/.settings/org.eclipse.core.resources.prefs
new file mode 100755 (executable)
index 0000000..898ab72
--- /dev/null
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1\r
+encoding/<project>=utf8\r
diff --git a/org.tizen.cli/doc/install/doc/schema/profiles.xsd b/org.tizen.cli/doc/install/doc/schema/profiles.xsd
new file mode 100755 (executable)
index 0000000..220980c
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"\r
+       xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
+       xmlns:target="http://www.samsung.com/schema/profiles"\r
+    targetNamespace="http://www.samsung.com/schema/profiles"\r
+       elementFormDefault="qualified"\r
+       attributeFormDefault="unqualified">\r
+\r
+       <xsd:complexType name="profileitemType">\r
+               <xsd:attribute name="author" type="xsd:string"></xsd:attribute>\r
+               <xsd:attribute name="identifier" type="xsd:string"></xsd:attribute>\r
+               <xsd:attribute name="key" type="xsd:string"></xsd:attribute>\r
+       </xsd:complexType>\r
+\r
+       <xsd:complexType name="profileType">\r
+          <xsd:sequence>\r
+              <xsd:element name="profileitem" type="target:profileitemType" minOccurs="0" maxOccurs="unbounded">\r
+              </xsd:element>\r
+          </xsd:sequence>\r
+               <xsd:attribute name="name" type="xsd:string" use="required"></xsd:attribute>\r
+       </xsd:complexType>\r
+\r
+       <xsd:element name="profiles">\r
+               <xsd:complexType>\r
+                       <xsd:sequence>\r
+                               <xsd:element name="profile" type="target:profileType" minOccurs="0" maxOccurs="unbounded">\r
+                               </xsd:element>\r
+                       </xsd:sequence>\r
+               </xsd:complexType>\r
+       </xsd:element>\r
+\r
+\r
+</xsd:schema>\r
old mode 100644 (file)
new mode 100755 (executable)
index 9096f5a..d8fa49f
  */
 package org.tizen.cli.exec;
 
-import static org.tizen.common.util.StringUtil.nvl;
-
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.Enumeration;
+import java.util.Properties;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
 import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
@@ -50,7 +49,9 @@ import org.tizen.common.core.command.policy.PolicyRegistry;
 import org.tizen.common.file.FileHandler;
 import org.tizen.common.file.FileHandler.Attribute;
 import org.tizen.common.file.StandardFileHandler;
+import org.tizen.common.util.IOUtil;
 import org.tizen.common.util.MapUtil;
+import org.tizen.common.util.PropertyUtil;
 
 /**
  * <p>
@@ -66,10 +67,6 @@ import org.tizen.common.util.MapUtil;
 abstract public class
 AbstractLauncher
 {
-       /**
-        * Program name property key
-        */
-       protected static final String PROP_PRG = "cli.name";
        
        /**
         * <p>
@@ -134,6 +131,14 @@ AbstractLauncher
         */
        protected static final String PROP_PARSER = "tizen.cli.parser";
        
+       
+       /**
+        * <p>
+        * suffix for help properties
+        * </p>
+        */
+       protected static final String SUFFIX_CONFIG = ".properties";
+       
        /**
         * <p>
         * logger for this object
@@ -143,6 +148,13 @@ AbstractLauncher
        
        /**
         * <p>
+        * object for usage help
+        * </p>
+        */
+       protected Help help;
+       
+       /**
+        * <p>
         * optional flag to be specified by user
         * 
         * flag is formatted in POSIX style in default
@@ -182,7 +194,7 @@ AbstractLauncher
         */
        protected String getSyntax()
        {
-               return nvl( System.getProperty( PROP_PRG ), "java " + getClass().getName() );
+               return getHelp().getSyntax();
        }
        
        /**
@@ -205,6 +217,58 @@ AbstractLauncher
        }
        
        /**
+        * <p>
+        * Return {@link Help} in this cli instance
+        * </p>
+        * @return {@link Help}
+        */
+       synchronized protected
+       Help
+       getHelp()
+       {
+           if ( null == help )
+           {
+               this.help = new Help( getOptions() );
+               final ClassLoader cl = getClass().getClassLoader();
+               final String resourceName = getClass().getName().replace( '.', '/' ) + SUFFIX_CONFIG;
+               try
+            {
+                final Enumeration<URL> iter = cl.getResources( resourceName );
+                while ( iter.hasMoreElements() )
+                {
+                    final URL url = iter.nextElement();
+                    final Properties properties = PropertyUtil.loadProperties( url.openStream() );
+                    
+                    for ( final Object key : properties.keySet() )
+                    {
+                        final String value = properties.getProperty( (String) key );
+                        byte[] contents = IOUtil.getBytes( cl.getResourceAsStream( value ), true );
+                        this.help.addHelpDetail( (String) key, new String( contents, Charset.forName( "utf8" ) ) );
+                    }
+                }
+            }
+               catch ( final IOException e )
+            {
+                logger.warn( "Can't load help", e );
+            }
+           }
+           
+           return this.help;
+       }
+       
+       /**
+        * Print out sample usage
+        * 
+        * @return sample usage string
+        */
+       protected
+       String
+       printHelpDetail( String option )
+       {
+           return getHelp().getHelpDetail( option );
+       }
+       
+       /**
         * Print out usage
         * 
         * @return usage string
@@ -213,29 +277,9 @@ AbstractLauncher
        String
        printHelp()
        {
-               final HelpFormatter formatter = new HelpFormatter();
-
-               final StringWriter writer = new StringWriter();
-
-               final PrintWriter stream = new PrintWriter( writer );
-
-               formatter.printHelp(
-                       stream,
-                       formatter.getWidth(),
-                       getSyntax(),
-                       null,
-                       getOptions(),
-                       formatter.getLeftPadding(),
-                       formatter.getDescPadding(),
-                       null,
-                       false
-               );
-               
-               final String help = writer.toString();
-               
-               getPrompter().error( help );
-               
-               return help;
+           String helpStr = getHelp().getHelp();
+               getPrompter().error( helpStr );
+               return helpStr;
        }
        
        
@@ -279,9 +323,14 @@ AbstractLauncher
                        if ( cmd.hasOption( OPT_HELP ) )
                        {
                                printHelp();
+                               
+                               for ( String keyword : cmd.getArgs() )
+                               {
+                                   printHelpDetail( keyword );
+                               }
                                return ;
                        }
-                               
+
                        execute( cmd );
                }
                catch ( final ParseException e )
diff --git a/org.tizen.cli/src/org/tizen/cli/exec/Help.java b/org.tizen.cli/src/org/tizen/cli/exec/Help.java
new file mode 100755 (executable)
index 0000000..16d5712
--- /dev/null
@@ -0,0 +1,92 @@
+package org.tizen.cli.exec;\r
+\r
+import static org.tizen.common.util.StringUtil.EMPTY_STRING;\r
+import static org.tizen.common.util.StringUtil.nvl;\r
+\r
+import java.io.PrintWriter;\r
+import java.io.StringWriter;\r
+import java.util.HashMap;\r
+\r
+import org.apache.commons.cli.HelpFormatter;\r
+import org.apache.commons.cli.Options;\r
+\r
+public class Help\r
+{\r
+    /**\r
+     * Program name property key\r
+     */\r
+    protected static final String PROP_PRG = "cli.name";\r
+    \r
+    protected final Options opts;\r
+    \r
+    protected HashMap<String, String> keyword2help = new HashMap<String, String>();\r
+    \r
+    public Help( Options opts )\r
+    {\r
+        this.opts = opts;\r
+    }\r
+    \r
+    /**\r
+     * {@link Options} for usage\r
+     * \r
+     * @return defined {@link Options}\r
+     */\r
+    protected\r
+    Options\r
+    getOptions()\r
+    {\r
+        return opts;\r
+    }\r
+    \r
+    public void addHelpDetail( String keyword, String help )\r
+    {\r
+        keyword2help.put( keyword.toLowerCase(), help );\r
+    }\r
+    \r
+    /**\r
+     * return execution command for usage\r
+     * \r
+     * @return execution command\r
+     */\r
+    protected String getSyntax()\r
+    {\r
+        return nvl( System.getProperty( PROP_PRG ), "java " + getClass().getName() );\r
+    }\r
+\r
+    \r
+    public String getHelp()\r
+    {\r
+        final HelpFormatter formatter = new HelpFormatter();\r
+\r
+        final StringWriter writer = new StringWriter();\r
+\r
+        final PrintWriter stream = new PrintWriter( writer );\r
+\r
+        formatter.printHelp(\r
+            stream,\r
+            formatter.getWidth(),\r
+            getSyntax(),\r
+            null,\r
+            getOptions(),\r
+            formatter.getLeftPadding(),\r
+            formatter.getDescPadding(),\r
+            null,\r
+            false\r
+        );\r
+        \r
+        final String help = writer.toString();\r
+        \r
+        return help;\r
+    }\r
+    \r
+    public String\r
+    getHelpDetail( final String keyword )\r
+    {\r
+        if ( null == keyword )\r
+        {\r
+            return EMPTY_STRING;\r
+        }\r
+        return nvl( keyword2help.get( keyword.toLowerCase() ) );\r
+    }\r
+\r
+}\r
index d5119db..1b38000 100755 (executable)
@@ -25,6 +25,7 @@
 package org.tizen.cli.exec.sign;
 
 import static org.tizen.common.util.FilenameUtil.addTailingPath;
+import static org.tizen.common.util.StringUtil.nvl;
 
 import java.io.IOException;
 import java.text.MessageFormat;
@@ -41,6 +42,7 @@ import org.tizen.common.core.command.prompter.Option;
 import org.tizen.common.file.FileHandler;
 import org.tizen.common.file.FileHandler.Attribute;
 import org.tizen.common.util.CollectionUtil;
+import org.tizen.common.util.FilenameUtil;
 import org.tizen.web.sign.command.ReadSigningProfileFileCommand;
 import org.tizen.web.sign.command.SignCommand;
 
@@ -88,6 +90,28 @@ implements ILaunchOptions
         */
        protected static final int SEPARATOR_PROFILE = ':';
        
+       
+       /**
+        * <p>
+        * JVM property key for default profile path
+        * </p>
+        */
+       protected static final String PROP_CLI_HOME = "cli.home";
+       
+       /**
+        * <p>
+        * OS environment variable key for default profile path
+        * </p>
+        */
+       protected static final String ENV_CLI_HOME = "CLI_HOME";
+       
+       /**
+        * <p>
+        * default profile file's name
+        * </p>
+        */
+       protected static final String DEFAULT_PROFILE_NAME = "profiles.xml";
+       
        /**
         * Entry point for cli main
         * 
@@ -189,7 +213,7 @@ implements ILaunchOptions
                final int index = profileName.indexOf( SEPARATOR_PROFILE );
                if ( index < 0 )
                {
-                       profilesFilePath = System.getProperty( "user.home" ) + "/.tizen/profiles.xml";
+                       profilesFilePath = getDefaultProfilesFilePath();
                }
                else
                {
@@ -199,6 +223,11 @@ implements ILaunchOptions
                
                logger.debug( "Profile name :{}", profileName );
                logger.debug( "Profiles file path :{}", profilesFilePath );
+               if ( null == profilesFilePath )
+               {
+                   getExecutionContext().getPrompter().error( "Profiles file not found. Try to specify profiles path using -p option or environment variable cli.home" );
+                   return ;
+               }
                
                final ReadSigningProfileFileCommand readProfile = new ReadSigningProfileFileCommand( profilesFilePath, profileName );
                getExecutor().execute( readProfile );
@@ -217,6 +246,30 @@ implements ILaunchOptions
        }
 
        /**
+        * Return default profiles.xml's path
+        * 
+        * default profile path is specified by jvm propertyes naming "cli.home"
+        * 
+        * or os environment variable "CLI_HOME"
+        * 
+        * @return default profiles path
+        */
+       protected
+       String
+       getDefaultProfilesFilePath()
+    {
+        final String cliHome =
+        nvl( System.getProperty( PROP_CLI_HOME ), System.getenv( ENV_CLI_HOME ) );
+        
+        if ( null == cliHome )
+        {
+            return null;
+        }
+        
+        return FilenameUtil.addTailingPath( cliHome, "conf/" + DEFAULT_PROFILE_NAME );
+    }
+
+    /**
         * Check if <code>path</code> is Tizen web project root
         * 
         * @param path directory path to check
diff --git a/org.tizen.cli/src/org/tizen/cli/exec/sign/Main.properties b/org.tizen.cli/src/org/tizen/cli/exec/sign/Main.properties
new file mode 100755 (executable)
index 0000000..17f6922
--- /dev/null
@@ -0,0 +1 @@
+profile=org/tizen/cli/exec/sign/profile.help
\ No newline at end of file
diff --git a/org.tizen.cli/src/org/tizen/cli/exec/sign/profile.help b/org.tizen.cli/src/org/tizen/cli/exec/sign/profile.help
new file mode 100755 (executable)
index 0000000..460a0d3
--- /dev/null
@@ -0,0 +1,14 @@
+Specify profile( profile name and profiles file path )\r
+\r
+* profile name\r
+    Profiles file can contain multiple profiles. You must specify profile to use in signing.\r
+\r
+* profiles file path\r
+    Path of profiles file containing profiles. Default value is "$CLI_HOME/conf/profiles.xml". You can change it using java virtual machine properties( -D ).\r
+\r
+    Ex.)\r
+        web-signing -p develop:/home/tizen/profiles.xml\r
+\r
+* profiles file format\r
+    It is xml-formatted file. Its schema( xml schema ) exists in $CLI_HOME/doc/schema/profiles.xsd\r
+    You don't have to specify schema in profiles file
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index 0cbeb1e..373a85f
@@ -24,6 +24,7 @@
 */
 package org.tizen.cli.exec;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -37,6 +38,7 @@ import org.apache.commons.cli.PosixParser;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.tizen.cli.exec.sign.Main;
 import org.tizen.common.core.command.Executor;
 import org.tizen.common.core.command.prompter.NopPrompter;
 
@@ -70,6 +72,7 @@ AbstractLauncherTest
                 */
                public LauncherSpi() {
                        executor = new CommandLineExecutor( new NopPrompter() );
+                       getHelp().addHelpDetail( "hello", "World" );
                }
                
                /* (non-Javadoc)
@@ -193,6 +196,15 @@ AbstractLauncherTest
                assertNotNull( launcher.printHelp() );
        }
        
+       @Test
+       public
+       void
+       test_printHelpDetail()
+       throws Exception
+       {
+           assertEquals( "World", launcher.printHelpDetail( "Hello" ) );
+       }
+       
     /**
      * Test {@link AbstractLauncher#run(String...)}
      * 
@@ -278,4 +290,26 @@ AbstractLauncherTest
                assertNotNull( executor );
        }
 
+    /**
+     * Test {@link AbstractLauncher#getHelp()}
+     * 
+     * @throws Exception in case of failure in test
+     * 
+     * @see AbstractLauncher#getHelp()
+     */
+       @Test
+       public
+       void
+       test_getHelp()
+       throws Exception
+       {
+           final Main testTarget = new Main();
+           
+           final Help help = testTarget.getHelp();
+           assertNotNull( help );
+           
+           assertTrue( help.getHelpDetail( "profile" ).contains( "profiles.xsd" ) );
+           
+       }
+       
 }
diff --git a/org.tizen.cli/test/src/org/tizen/cli/exec/HelpTest.java b/org.tizen.cli/test/src/org/tizen/cli/exec/HelpTest.java
new file mode 100755 (executable)
index 0000000..d557276
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+*  Command Line Interface\r
+*\r
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+*\r
+* Contact: \r
+* BonYong Lee <bonyong.lee@samsung.com>\r
+* \r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*\r
+* Contributors:\r
+* - S-Core Co., Ltd\r
+*\r
+*/\r
+package org.tizen.cli.exec;\r
+\r
+import static org.junit.Assert.*;\r
+\r
+import org.apache.commons.cli.OptionBuilder;\r
+import org.apache.commons.cli.Options;\r
+import org.junit.Test;\r
+\r
+/**\r
+ * HelpTest\r
+ *\r
+ * Test case for {@link Help}\r
+ * \r
+ * @author BonYong Lee{@literal <bonyong.lee@samsung.com>} (S-Core)\r
+ * \r
+ * @see Help\r
+ */\r
+public class HelpTest\r
+{\r
+\r
+    /**\r
+     * Test {@link Help#getHelp()}\r
+     * \r
+     * @throws Exception in case of failure in test\r
+     * \r
+     * @see Help#getHelp()\r
+     */\r
+    @SuppressWarnings("static-access")\r
+    @Test\r
+    public void test_getHelp()\r
+    {\r
+        \r
+        final Help h = new Help( new Options().addOption( OptionBuilder.withLongOpt( "help" ).create( "h" ) ) );\r
+        \r
+        assertNotNull( h.getHelp() );\r
+        assertTrue( h.getHelp().contains( "-h,--help" ) );\r
+    }\r
+    \r
+    /**\r
+     * Test {@link Help#getHelpDetail(String)}\r
+     * \r
+     * @throws Exception in case of failure in test\r
+     * \r
+     * @see Help#getHelpDetail(String)\r
+     */\r
+    @SuppressWarnings("static-access")\r
+    public void test_getHelpDetail() throws Exception\r
+    {\r
+        final Help h = new Help( new Options().addOption( OptionBuilder.withLongOpt( "help" ).create( "h" ) ) );\r
+        h.addHelpDetail( "command", "command is not supported" );\r
+        \r
+        \r
+        assertEquals( "command is not supported", h.getHelpDetail( "command" ) );\r
+        \r
+        \r
+    }\r
+\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index 6819b59..bc26a9a
 */
 package org.tizen.cli.exec;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 import org.tizen.common.core.command.Prompter;
 import org.tizen.common.core.command.prompter.ChoiceOption;
 import org.tizen.common.core.command.prompter.GenericOption;
 import org.tizen.sdblib.IDevice;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 /**
  * TargetDeviceSelectorTest
  *
@@ -227,11 +231,10 @@ TargetDeviceSelectorTest
                 )
             ).thenReturn( no );
         ChoiceOption cancel = new ChoiceOption( "Cancel", true );
-        GenericOption num = new GenericOption( "Num" );
 
-        when( mockPropter.interact( "select device or cancel process ",
-                cancel,
-                num
+        when( mockPropter.interact( Mockito.eq( "select device or cancel process " ),
+            Mockito.<ChoiceOption>any(),
+            Mockito.<GenericOption>any()
                 )
             ).thenReturn( cancel );
         assertEquals( null, testClass.selectDevice() );
index 400e8f0..aa8b49c 100755 (executable)
@@ -148,4 +148,5 @@ extends AbstractMainTest
                
        }
        
+       
 }