[Title] Add common signing module to develop branch
authorho.namkoong <ho.namkoong@samsung.com>
Thu, 1 Nov 2012 05:23:52 +0000 (14:23 +0900)
committerho.namkoong <ho.namkoong@samsung.com>
Thu, 1 Nov 2012 05:23:52 +0000 (14:23 +0900)
[Type]
[Module]
[Priority]
[Jira#]
[Redmine#] 7122
[Problem]
[Cause]
[Solution]
[TestCase]

Change-Id: Ie7b7059370e7b826ccf80c86ebeb221ee2e62c56

36 files changed:
org.tizen.common.sign/.classpath [new file with mode: 0644]
org.tizen.common.sign/.project [new file with mode: 0644]
org.tizen.common.sign/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
org.tizen.common.sign/META-INF/MANIFEST.MF [new file with mode: 0644]
org.tizen.common.sign/OSGI-INF/l10n/bundle.properties [new file with mode: 0644]
org.tizen.common.sign/build.properties [new file with mode: 0644]
org.tizen.common.sign/key/samsung.devmode.sdk.cert.p12 [new file with mode: 0644]
org.tizen.common.sign/lib/CertificateGenerator.jar [new file with mode: 0644]
org.tizen.common.sign/lib/HashSign.jar [new file with mode: 0644]
org.tizen.common.sign/lib/xmlsec-1.4.5.jar [new file with mode: 0644]
org.tizen.common.sign/plugin.xml [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/Activator.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/command/ReadSigningProfileFileCommand.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/exception/CertificationException.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/exception/ComplicatedCertificationException.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/exception/SigningErrorDialog.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/model/Certification.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/FileBrowserCellEditor.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/Messages.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/Messages.properties [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileCellModifier.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileItemContentProvider.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileItemLabelProvider.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningPreferencePage.java [new file with mode: 0755]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfile.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfileItem.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfileItemFactory.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/UIMessages.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/preferences/UIMessages.properties [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/signer/BuildNumber.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/signer/TizenSigner.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/ui/Messages.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/ui/TizenSigningDialog.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/ui/messages.properties [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/util/SigningProfileUtil.java [new file with mode: 0644]
org.tizen.common.sign/src/org/tizen/common/sign/util/XMLUtil.java [new file with mode: 0644]

diff --git a/org.tizen.common.sign/.classpath b/org.tizen.common.sign/.classpath
new file mode 100644 (file)
index 0000000..e397434
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry exported="true" kind="lib" path="lib/CertificateGenerator.jar"/>
+       <classpathentry exported="true" kind="lib" path="lib/HashSign.jar"/>
+       <classpathentry exported="true" kind="lib" path="lib/xmlsec-1.4.5.jar"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.tizen.common.sign/.project b/org.tizen.common.sign/.project
new file mode 100644 (file)
index 0000000..f416e24
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.tizen.common.sign</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/org.tizen.common.sign/.settings/org.eclipse.jdt.core.prefs b/org.tizen.common.sign/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..4735ca7
--- /dev/null
@@ -0,0 +1,8 @@
+#Sat Oct 20 17:22:06 KST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/org.tizen.common.sign/META-INF/MANIFEST.MF b/org.tizen.common.sign/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..5c1e687
--- /dev/null
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.tizen.common.sign; singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.tizen.common.sign.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.tizen.common
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Import-Package: org.eclipse.core.resources
+Bundle-Vendor: %Bundle-Vendor
+Export-Package: hashsign,
+ org.tizen.common.sign,
+ org.tizen.common.sign.command,
+ org.tizen.common.sign.exception,
+ org.tizen.common.sign.model,
+ org.tizen.common.sign.preferences,
+ org.tizen.common.sign.signer,
+ org.tizen.common.sign.ui,
+ org.tizen.common.sign.util
+Bundle-ClassPath: lib/CertificateGenerator.jar,
+ lib/HashSign.jar,
+ lib/xmlsec-1.4.5.jar,
+ .
diff --git a/org.tizen.common.sign/OSGI-INF/l10n/bundle.properties b/org.tizen.common.sign/OSGI-INF/l10n/bundle.properties
new file mode 100644 (file)
index 0000000..c6330bd
--- /dev/null
@@ -0,0 +1,4 @@
+#Properties file for org.tizen.common.sign
+Bundle-Vendor = Samsung Electronics
+Bundle-Name = Sign
+page.name = Secure Profiles
\ No newline at end of file
diff --git a/org.tizen.common.sign/build.properties b/org.tizen.common.sign/build.properties
new file mode 100644 (file)
index 0000000..187f793
--- /dev/null
@@ -0,0 +1,10 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .,\
+               key/,\
+               OSGI-INF/,\
+               lib/CertificateGenerator.jar,\
+               lib/HashSign.jar,\
+               lib/xmlsec-1.4.5.jar
diff --git a/org.tizen.common.sign/key/samsung.devmode.sdk.cert.p12 b/org.tizen.common.sign/key/samsung.devmode.sdk.cert.p12
new file mode 100644 (file)
index 0000000..8302b60
Binary files /dev/null and b/org.tizen.common.sign/key/samsung.devmode.sdk.cert.p12 differ
diff --git a/org.tizen.common.sign/lib/CertificateGenerator.jar b/org.tizen.common.sign/lib/CertificateGenerator.jar
new file mode 100644 (file)
index 0000000..0f94b29
Binary files /dev/null and b/org.tizen.common.sign/lib/CertificateGenerator.jar differ
diff --git a/org.tizen.common.sign/lib/HashSign.jar b/org.tizen.common.sign/lib/HashSign.jar
new file mode 100644 (file)
index 0000000..12eac89
Binary files /dev/null and b/org.tizen.common.sign/lib/HashSign.jar differ
diff --git a/org.tizen.common.sign/lib/xmlsec-1.4.5.jar b/org.tizen.common.sign/lib/xmlsec-1.4.5.jar
new file mode 100644 (file)
index 0000000..fd2d493
Binary files /dev/null and b/org.tizen.common.sign/lib/xmlsec-1.4.5.jar differ
diff --git a/org.tizen.common.sign/plugin.xml b/org.tizen.common.sign/plugin.xml
new file mode 100644 (file)
index 0000000..e340406
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+   <extension
+         point="org.eclipse.ui.preferencePages">
+      <page
+            category="org.tizen.common.preferences.tizencommon"
+            class="org.tizen.common.sign.preferences.SigningPreferencePage"
+            id="org.tizen.common.sign.preferences.SigningPreferencePage"
+            name="%page.name">
+      </page>
+   </extension>
+
+</plugin>
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/Activator.java b/org.tizen.common.sign/src/org/tizen/common/sign/Activator.java
new file mode 100644 (file)
index 0000000..be94762
--- /dev/null
@@ -0,0 +1,67 @@
+package org.tizen.common.sign;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+import org.tizen.common.CommonPlugin;
+import org.tizen.common.core.command.Prompter;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.tizen.common.sign"; //$NON-NLS-1$
+
+       // The shared instance
+       private static Activator plugin;
+       
+       /**
+        * The constructor
+        */
+       public Activator() {
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        *
+        * @return the shared instance
+        */
+       public static Activator getDefault() {
+               return plugin;
+       }
+
+       /**
+        * Returns an image descriptor for the image file at the given
+        * plug-in relative path
+        *
+        * @param path the path
+        * @return the image descriptor
+        */
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return imageDescriptorFromPlugin(PLUGIN_ID, path);
+       }
+       
+       public Prompter getPrompter() {
+        return CommonPlugin.getDefault().getPrompter();
+    }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/command/ReadSigningProfileFileCommand.java b/org.tizen.common.sign/src/org/tizen/common/sign/command/ReadSigningProfileFileCommand.java
new file mode 100644 (file)
index 0000000..5df5735
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.command;
+
+import static org.tizen.common.util.IOUtil.tryClose;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.tizen.common.core.command.AbstractCommand;
+import org.tizen.common.core.command.ExecutionContext;
+import org.tizen.common.core.command.Executor;
+import org.tizen.common.file.FileHandler;
+import org.tizen.common.file.FileHandler.Attribute;
+import org.tizen.common.file.FileHandler.Type;
+import org.tizen.common.sign.preferences.SigningProfileItem;
+import org.tizen.common.sign.util.SigningProfileUtil;
+
+public class
+ReadSigningProfileFileCommand
+extends AbstractCommand<Object>
+{
+       protected final Logger logger = LoggerFactory.getLogger( getClass() );
+
+       protected final String path;
+
+       protected final String profileName;
+
+       protected List<SigningProfileItem> profileItems = new ArrayList<SigningProfileItem>();
+
+       public ReadSigningProfileFileCommand( final String path, final String profileName )
+       {
+               this.path = path;
+               this.profileName = profileName;
+
+               logger.info( "Read profile[{}] from {}", profileName, path );
+       }
+
+       public void run(
+               final Executor executor,
+               final ExecutionContext context
+       )
+       throws Exception
+       {
+               final FileHandler fileHandler = context.getFileHandler();
+               if ( !canRun( context ) )
+               {
+                       return ;
+               }
+
+               final InputStream in = fileHandler.read( path );
+
+               try
+               {
+                       profileItems = SigningProfileUtil.parseProfileFile( in, profileName );
+               }
+               finally
+               {
+                       tryClose( in );
+               }
+       }
+
+       protected
+       boolean
+       canRun(
+               final ExecutionContext context
+       )
+       throws IOException
+       {
+               final FileHandler fileHandler = context.getFileHandler();
+               if ( !fileHandler.is( path, Attribute.EXISTS ) )
+               {
+                       return false;
+               }
+               if ( !fileHandler.is( path, Attribute.READABLE ) )
+               {
+                       return false;
+               }
+               return ( Type.FILE.equals( fileHandler.get( path, Attribute.TYPE ) ) );
+       }
+
+       public List<SigningProfileItem> getProfileItems()
+       {
+               return this.profileItems;
+       }
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/exception/CertificationException.java b/org.tizen.common.sign/src/org/tizen/common/sign/exception/CertificationException.java
new file mode 100644 (file)
index 0000000..dfaae55
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.exception;
+
+public class
+CertificationException
+extends Exception {
+       
+       private static final long serialVersionUID = 7001672806422880543L;
+       
+       public CertificationException( final String msg, final Throwable cause ) {
+               super( msg, cause );
+       }
+       public CertificationException( final String msg ) {
+               super( msg );
+       }
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/exception/ComplicatedCertificationException.java b/org.tizen.common.sign/src/org/tizen/common/sign/exception/ComplicatedCertificationException.java
new file mode 100644 (file)
index 0000000..dcc49e9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.exception;
+
+public class ComplicatedCertificationException
+extends CertificationException
+{
+
+       /**
+        * 
+        */
+       private static final long serialVersionUID = -8921261148323181356L;
+
+       public ComplicatedCertificationException(String msg) {
+               super(msg);
+               // TODO Auto-generated constructor stub
+       }
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/exception/SigningErrorDialog.java b/org.tizen.common.sign/src/org/tizen/common/sign/exception/SigningErrorDialog.java
new file mode 100644 (file)
index 0000000..26ae082
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.exception;
+
+import static org.tizen.common.util.SWTUtil.getActiveShell;
+import static org.tizen.common.util.StringUtil.nvl;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IconAndMessageDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.tizen.common.sign.preferences.SigningPreferencePage;
+
+
+public class
+SigningErrorDialog
+extends IconAndMessageDialog
+{
+       /**
+        * The title of the dialog.
+        */
+       private String title;
+
+       public
+       SigningErrorDialog(
+               final String message
+       )
+       {
+               this( getActiveShell(), "Signing", message );
+       }
+
+       /**
+        * Creates an error dialog. Note that the dialog will have no visual
+        * representation (no widgets) until it is told to open.
+        * <p>
+        * Normally one should use <code>openError</code> to create and open one
+        * of these. This constructor is useful only if the error object being
+        * displayed contains child items <it>and </it> you need to specify a mask
+        * which will be used to filter the displaying of these children. The error
+        * dialog will only be displayed if there is at least one child status
+        * matching the mask.
+        * </p>
+        * 
+        * @param parentShell
+        *            the shell under which to create this dialog
+        * @param dialogTitle
+        *            the title to use for this dialog, or <code>null</code> to
+        *            indicate that the default title should be used
+        * @param message
+        *            the message to show in this dialog, or <code>null</code> to
+        *            indicate that the error's message should be shown as the
+        *            primary message
+        * @param status
+        *            the error to show to the user
+        * @param displayMask
+        *            the mask to use to filter the displaying of child items, as
+        *            per <code>IStatus.matches</code>
+        * @see org.eclipse.core.runtime.IStatus#matches(int)
+        */
+       public
+       SigningErrorDialog(
+               final Shell parentShell,
+               final String dialogTitle,
+               final String message
+       )
+       {
+               super( parentShell );
+               this.title = nvl( dialogTitle, JFaceResources.getString( "Problem_Occurred" ) );
+               this.message = message;
+       }
+
+       /*
+        * (non-Javadoc) Method declared in Window.
+        */
+       protected void configureShell(Shell shell) {
+               super.configureShell(shell);
+               shell.setText(title);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
+        */
+       protected void createButtonsForButtonBar(Composite parent) {
+               // create OK and Details buttons
+               createButton( parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true );
+       }
+
+       /**
+        * This implementation of the <code>Dialog</code> framework method creates
+        * and lays out a composite. Subclasses that require a different dialog area
+        * may either override this method, or call the <code>super</code>
+        * implementation and add controls to the created composite.
+        * 
+        * Note:  Since 3.4, the created composite no longer grabs excess vertical space.
+        * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=72489.
+        * If the old behavior is desired by subclasses, get the returned composite's
+        * layout data and set grabExcessVerticalSpace to true.
+        */
+       protected
+       Control
+       createDialogArea(
+               final Composite parent
+       )
+       {
+               // Create a composite with standard margins and spacing
+               // Add the messageArea to this composite so that as subclasses add widgets to the messageArea
+               // and dialogArea, the number of children of parent remains fixed and with consistent layout.
+               // Fixes bug #240135
+               Composite composite = new Composite(parent, SWT.NONE);
+               createMessageArea(composite);
+               GridLayout layout = new GridLayout();
+               layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+               layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+               layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+               layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+               layout.numColumns = 2;
+               composite.setLayout(layout);
+               GridData childData = new GridData(GridData.FILL_BOTH);
+               childData.horizontalSpan = 2;
+               childData.grabExcessVerticalSpace = false;
+               composite.setLayoutData(childData);
+               composite.setFont(parent.getFont());
+
+               return composite;
+       }
+
+       @Override
+       protected Control createMessageArea(Composite composite) {
+
+               // create composite
+               // create image
+               Image image = getImage();
+               if (image != null) {
+                       imageLabel = new Label(composite, SWT.NULL);
+                       image.setBackground(imageLabel.getBackground());
+                       imageLabel.setImage(image);
+                       addAccessibleListeners(imageLabel, image);
+                       GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING)
+                                       .applyTo(imageLabel);
+               }
+               // create message
+               if (message != null) {
+                       Link messageLabel = new Link(composite, getMessageLabelStyle());
+                       messageLabel.setText( message );
+                       GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).hint(
+                                                       convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH),
+                                                       SWT.DEFAULT).applyTo(messageLabel);
+                       messageLabel.addSelectionListener(new SelectionListener() {
+                               
+                               @Override
+                               public void widgetSelected(SelectionEvent e) {
+                                       PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), SigningPreferencePage.PREFERENCE_PAGE_ID, new String[] { SigningPreferencePage.PREFERENCE_PAGE_ID }, null);
+                                       dialog.open();
+                               }
+                               
+                               @Override
+                               public void widgetDefaultSelected(SelectionEvent e) {
+                               }
+                       });
+               }
+               
+               return composite;
+       }
+       
+       /**
+        * Add an accessible listener to the label if it can be inferred from the
+        * image.
+        * 
+        * @param label
+        * @param image
+        */
+       private void addAccessibleListeners(Label label, final Image image) {
+               label.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+                       public void getName(AccessibleEvent event) {
+                               final String accessibleMessage = getAccessibleMessageFor(image);
+                               if (accessibleMessage == null) {
+                                       return;
+                               }
+                               event.result = accessibleMessage;
+                       }
+               });
+       }
+       
+       private String getAccessibleMessageFor(Image image) {
+               if (image.equals(getErrorImage())) {
+                       return JFaceResources.getString("error");//$NON-NLS-1$
+               }
+
+               if (image.equals(getWarningImage())) {
+                       return JFaceResources.getString("warning");//$NON-NLS-1$
+               }
+
+               if (image.equals(getInfoImage())) {
+                       return JFaceResources.getString("info");//$NON-NLS-1$
+               }
+
+               if (image.equals(getQuestionImage())) {
+                       return JFaceResources.getString("question"); //$NON-NLS-1$
+               }
+
+               return null;
+       }
+       
+       /*
+        * @see IconAndMessageDialog#createDialogAndButtonArea(Composite)
+        */
+       protected void createDialogAndButtonArea(Composite parent) {
+               super.createDialogAndButtonArea(parent);
+               if (this.dialogArea instanceof Composite) {
+                       // Create a label if there are no children to force a smaller layout
+                       Composite dialogComposite = (Composite) dialogArea;
+                       if (dialogComposite.getChildren().length == 0) {
+                               new Label(dialogComposite, SWT.NULL);
+                       }
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.jface.dialogs.IconAndMessageDialog#getImage()
+        */
+       protected Image getImage() {
+               /*if (status != null) {
+                       if (status.getSeverity() == IStatus.WARNING) {
+                               return getWarningImage();
+                       }
+                       if (status.getSeverity() == IStatus.INFO) {
+                               return getInfoImage();
+                       }
+               }*/
+               // If it was not a warning or an error then return the error image
+               return getErrorImage();
+       }
+
+       /**
+        * Opens an error dialog to display the given error. Use this method if the
+        * error object being displayed does not contain child items, or if you wish
+        * to display all such items without filtering.
+        * 
+        * @param parent
+        *            the parent shell of the dialog, or <code>null</code> if none
+        * @param dialogTitle
+        *            the title to use for this dialog, or <code>null</code> to
+        *            indicate that the default title should be used
+        * @param message
+        *            the message to show in this dialog, or <code>null</code> to
+        *            indicate that the error's message should be shown as the
+        *            primary message
+        * @param status
+        *            the error to show to the user
+        * @return the code of the button that was pressed that resulted in this
+        *         dialog closing. This will be <code>Dialog.OK</code> if the OK
+        *         button was pressed, or <code>Dialog.CANCEL</code> if this
+        *         dialog's close window decoration or the ESC key was used.
+        */
+       public static int openError(Shell parent, String dialogTitle,
+                       String message, IStatus status) {
+               return openError(parent, dialogTitle, message, status, IStatus.OK
+                               | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
+       }
+
+       /**
+        * Opens an error dialog to display the given error. Use this method if the
+        * error object being displayed contains child items <it>and </it> you wish
+        * to specify a mask which will be used to filter the displaying of these
+        * children. The error dialog will only be displayed if there is at least
+        * one child status matching the mask.
+        * 
+        * @param parentShell
+        *            the parent shell of the dialog, or <code>null</code> if none
+        * @param title
+        *            the title to use for this dialog, or <code>null</code> to
+        *            indicate that the default title should be used
+        * @param message
+        *            the message to show in this dialog, or <code>null</code> to
+        *            indicate that the error's message should be shown as the
+        *            primary message
+        * @param status
+        *            the error to show to the user
+        * @param displayMask
+        *            the mask to use to filter the displaying of child items, as
+        *            per <code>IStatus.matches</code>
+        * @return the code of the button that was pressed that resulted in this
+        *         dialog closing. This will be <code>Dialog.OK</code> if the OK
+        *         button was pressed, or <code>Dialog.CANCEL</code> if this
+        *         dialog's close window decoration or the ESC key was used.
+        * @see org.eclipse.core.runtime.IStatus#matches(int)
+        */
+       public static int openError(Shell parentShell, String title,
+                       String message, IStatus status, int displayMask) {
+               ErrorDialog dialog = new ErrorDialog(parentShell, title, message,
+                               status, displayMask);
+               return dialog.open();
+       }
+
+       /**
+        * Returns whether the given status object should be displayed.
+        * 
+        * @param status
+        *            a status object
+        * @param mask
+        *            a mask as per <code>IStatus.matches</code>
+        * @return <code>true</code> if the given status should be displayed, and
+        *         <code>false</code> otherwise
+        * @see org.eclipse.core.runtime.IStatus#matches(int)
+        */
+       protected static boolean shouldDisplay(IStatus status, int mask) {
+               IStatus[] children = status.getChildren();
+               if (children == null || children.length == 0) {
+                       return status.matches(mask);
+               }
+               for (int i = 0; i < children.length; i++) {
+                       if (children[i].matches(mask)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+    /*
+     * (non-Javadoc)
+     * @see org.eclipse.jface.dialogs.Dialog#isResizable()
+     */
+    protected boolean isResizable() {
+       return true;
+    }
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/model/Certification.java b/org.tizen.common.sign/src/org/tizen/common/sign/model/Certification.java
new file mode 100644 (file)
index 0000000..79c9948
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.model;
+
+import static org.tizen.common.util.IOUtil.tryClose;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.tizen.common.core.command.Prompter;
+import org.tizen.common.sign.exception.CertificationException;
+import org.tizen.common.sign.exception.ComplicatedCertificationException;
+import org.tizen.common.sign.preferences.UIMessages;
+import org.tizen.common.sign.preferences.SigningProfileItem;
+
+public class Certification {
+       
+       protected final Logger logger = LoggerFactory.getLogger( getClass() );
+       
+       public static enum KeyExtension {
+           p12( "PKCS12" ),
+           keystore( "JKS" );
+           
+           private String keyType;
+           
+           KeyExtension(String keyType) {
+               this.keyType = keyType;
+           }
+           
+           public String getKeyType() {
+               return this.keyType;
+           }
+           
+           public static boolean hasExtension( String extension ) {
+               for ( KeyExtension keyExt : KeyExtension.values() ) {
+                   if ( keyExt.name().equalsIgnoreCase( extension ) ) {
+                       return true;
+                   }
+               }
+               return false;
+           }
+       }
+
+       protected Prompter prompter;
+       
+       protected KeyStore keyStore;
+       
+       protected PrivateKey privateKey;
+
+       protected String privateKeyAlias;
+       
+       protected List<X509Certificate> certificationChain;
+
+       protected X509Certificate certificate;
+       
+       protected String password;
+       
+       public Certification(
+               final Prompter prompter
+       )
+       {
+               this.prompter = prompter; 
+       }
+       
+       protected Prompter getPrompter()
+       {
+               return this.prompter;
+       }
+       
+       protected char[] inputPassword( final String message )
+       {
+               final Prompter prompter = getPrompter();
+               return prompter.password( message );
+       }
+
+       public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public
+       boolean
+       load(
+               final SigningProfileItem profileItem
+       )
+       throws CertificationException
+       {
+               final String keyLocation = profileItem.getKeyLocation();
+               char[] password = profileItem.getPassword();
+               
+               if ( null == password || password.length == 0 )
+               {
+                       password = inputPassword( "Enter password for file" + keyLocation );
+                       
+                       if ( null == password  || password.length == 0 )
+                       {
+                               return false;
+                       }
+               }
+               
+               this.setPassword( new String( password ) );
+               /*
+               loadKeyStore( profileItem, password );
+               
+               try
+               {
+                       loadPrivateKey( password );
+               }
+               catch ( Exception e )
+               {
+                       if ( profileItem.isAuthor() )
+                       {
+                               throw new CertificationException( UIMessages.getString( "org.tizen.common.sign.authcertkeyerror" ), e );
+                       }
+                       else 
+                       {
+                               throw new CertificationException( UIMessages.getString( "org.tizen.common.sign.districertkeyerror" ), e );
+                       }
+               }
+               
+               try {
+                       loadCertificate( keyLocation );
+               } catch (Exception e) {
+                       if ( profileItem.isAuthor() )
+                       {
+                               throw new CertificationException( UIMessages.getString( "org.tizen.common.sign.authcerterror" ), e );
+                       }
+                       else 
+                       {
+                               throw new CertificationException( UIMessages.getString( "org.tizen.common.sign.districerterror" ), e );
+                       }
+               }
+               
+               loadCertificateChain();
+               */
+               return true;
+       }
+       protected
+       void
+       loadKeyStore(
+               SigningProfileItem item,
+//             final InputStream keyIn,
+               final char[] password
+       )
+       throws CertificationException
+       {
+               InputStream keyIn = null;
+               try
+               {
+                   keyIn = item.openKeyInputStream();
+                   
+                   IPath path = new Path( item.getKeyLocation() );
+                   String fileExtension = path.getFileExtension();
+                   
+                   for ( KeyExtension keyExtension : KeyExtension.values() ) {
+                       if ( keyExtension.name().equalsIgnoreCase( fileExtension ) ) {
+                           keyStore = KeyStore.getInstance( keyExtension.getKeyType() );
+                           keyStore.load( keyIn, password );
+                           return ;
+                       }
+                   }
+                       
+                   throw new KeyStoreException("couldn't find a matched key type.");
+               }
+               catch ( NoSuchAlgorithmException e )
+               {
+                       logger.error( "Error occured", e );
+               }
+               catch ( final CertificateException e )
+               {
+                       logger.error( "Error occured", e );
+               }
+               catch ( final IOException e )
+               {
+                       logger.error( "Error occured", e );
+               }
+               catch ( final KeyStoreException e )
+               {
+                       logger.error( "Error occured", e );
+               }
+               finally
+               {
+                       tryClose( keyIn );
+               }
+               
+               throw new CertificationException(
+                       UIMessages.getString( "org.tizen.common.sign.errorloadingkeystore")
+                       + " " + item.getKeyLocation() + ". "
+                       + UIMessages.getString( "org.tizen.common.sign.checkpassword" )
+               );
+       }
+       
+       protected void loadPrivateKey( char[] password ) {
+               try {
+                       java.util.Enumeration<String> alias = keyStore.aliases();
+                       while (alias.hasMoreElements()) {
+                               String aliasEntry = alias.nextElement();
+                               if ( keyStore.isKeyEntry( aliasEntry ) )
+                               {
+                                       privateKeyAlias = aliasEntry;
+                                       privateKey = (PrivateKey)keyStore.getKey( aliasEntry, password );
+                               }
+                       }
+               } catch (java.security.KeyStoreException e) {
+                       logger.error( "Error occured", e );
+               } catch (NoSuchAlgorithmException e) {
+                       logger.error( "Error occured", e );
+               } catch (java.security.UnrecoverableKeyException e) {
+                       logger.error( "Error occured", e );
+               }
+       }
+       
+       private void assertInvalidCertificate( X509Certificate interCertificate, String p12FileLocation ) throws ComplicatedCertificationException
+       {
+               Date notBefore = interCertificate.getNotBefore();
+               Date notAfter = interCertificate.getNotAfter();
+               Date date = new Date();
+               if (date.before(notBefore) || date.after(notAfter)) {
+                       String detailsText = UIMessages.getString( "org.tizen.common.sign.certificatevaliditymessage1") //$NON-NLS-1$
+                       + " " + p12FileLocation + " " + UIMessages.getString( "org.tizen.common.sign.certificatevaliditymessage2") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                       + " " + notBefore + " " + UIMessages.getString( "org.tizen.common.sign.certificatevaliditymessage3") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                       + " " + notAfter; //$NON-NLS-1$
+                       throw new ComplicatedCertificationException(detailsText);
+               } 
+       }
+
+
+       protected void loadCertificate( final String location ) throws KeyStoreException, ComplicatedCertificationException {
+               final Certificate cert = keyStore.getCertificate(privateKeyAlias);
+               if (cert instanceof X509Certificate) {
+                       // check expired
+                       assertInvalidCertificate( (X509Certificate) cert, location );
+                       certificate = (X509Certificate) cert;
+               }
+       }
+       
+       
+       protected void loadCertificateChain() throws CertificationException{
+               certificationChain = new ArrayList<X509Certificate>();
+               try {
+                       Certificate[] chain = keyStore.getCertificateChain( privateKeyAlias );
+                       if (chain != null && chain.length > 0) {
+                               for (int i = 0; i < chain.length; i++) {
+                                       if (chain[i] instanceof X509Certificate) {
+                                               certificationChain.add((X509Certificate) chain[i]);
+                                       }
+                               }
+                       }
+               } catch ( KeyStoreException e ) {
+                       throw new CertificationException( e.getMessage(), e );
+               }
+               
+       }
+
+
+       public Key getPrivateKey() {
+               return privateKey;
+       }
+
+       public X509Certificate[] getCertificationChain() {
+               return certificationChain.toArray( new X509Certificate[0] );
+       }
+
+
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/FileBrowserCellEditor.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/FileBrowserCellEditor.java
new file mode 100644 (file)
index 0000000..ae23a1d
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import org.eclipse.jface.viewers.DialogCellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Text;
+
+public class FileBrowserCellEditor extends DialogCellEditor {
+
+       private Text text;
+       
+       private boolean isSelection = false;
+       private boolean isDeleteable = false;
+       private boolean isSelectable = false;
+       private ModifyListener modifyListener;
+
+       private Button button;
+       
+       public FileBrowserCellEditor(Composite parent) {
+               super(parent, SWT.NONE);
+               doSetValue(""); //$NON-NLS-1$
+       }
+       
+       public FileBrowserCellEditor(Composite parent, boolean toModify) {
+               this(parent);
+       }
+
+       protected String[] getDialogFilter() {
+           // return new String[]{"*.p12;*.keystore", "*.p12", "*.keystore"}; // for Android KeyStore
+        return new String[]{"*.p12"};
+       }
+       
+       @Override
+       protected Object openDialogBox(Control cellEditorWindow) {
+               FileDialog dialog = new FileDialog(cellEditorWindow.getShell(), SWT.NONE );
+               dialog.setFilterExtensions( getDialogFilter() );
+               dialog.setText(Messages.FileBrowserCellEditor_2);
+               
+               Object value = getValue();
+        if (value != null) {
+                       dialog.setFileName((String) value);
+               }
+               String filePath = dialog.open();
+               return filePath;
+       }
+
+       protected Button createButton(Composite parent) {
+               Button result = new Button(parent, SWT.DOWN);
+               result.setText(".."); //$NON-NLS-1$
+               this.button = result;
+               return result;
+       }
+       
+    /**
+     * Creates the controls used to show the value of this cell editor.
+     * <p>
+     * The default implementation of this framework method creates
+     * a label widget, using the same font and background color as the parent control.
+     * </p>
+     * <p>
+     * Subclasses may reimplement.  If you reimplement this method, you
+     * should also reimplement <code>updateContents</code>.
+     * </p>
+     *
+     * @param cell the control for this cell editor 
+     * @return the underlying control
+     */
+    protected Control createContents(Composite cell) {
+       
+       text = new Text(cell, getStyle());
+        text.addSelectionListener(new SelectionAdapter() {
+            public void widgetDefaultSelected(SelectionEvent e) {
+                handleDefaultSelection(e);
+            }
+        });
+        text.addKeyListener(new KeyAdapter() {
+            // hook key pressed - see PR 14201  
+            public void keyPressed(KeyEvent e) {
+                keyReleaseOccured(e);
+
+                // as a result of processing the above call, clients may have
+                // disposed this cell editor
+                if ((getControl() == null) || getControl().isDisposed()) {
+                                       return;
+                               }
+                checkSelection(); // see explanation below
+                checkDeleteable();
+                checkSelectable();
+            }
+        });
+        text.addTraverseListener(new TraverseListener() {
+            public void keyTraversed(TraverseEvent e) {
+                if (e.detail == SWT.TRAVERSE_ESCAPE
+                        || e.detail == SWT.TRAVERSE_RETURN) {
+                    e.doit = false;
+                }
+            }
+        });
+        // We really want a selection listener but it is not supported so we
+        // use a key listener and a mouse listener to know when selection changes
+        // may have occurred
+        text.addMouseListener(new MouseAdapter() {
+            public void mouseUp(MouseEvent e) {
+                checkSelection();
+                checkDeleteable();
+                checkSelectable();
+            }
+        });
+        /*text.addFocusListener(new FocusAdapter() {
+            public void focusLost(FocusEvent e) {
+                FileBrowserCellEditor.this.focusLost();
+            }
+        });*/
+        text.setFont(cell.getFont());
+        text.setBackground(cell.getBackground());
+        text.addModifyListener(getModifyListener());
+       
+        return text;
+    }
+    
+    /**
+     * Return the modify listener.
+     */
+    private ModifyListener getModifyListener() {
+        if (modifyListener == null) {
+            modifyListener = new ModifyListener() {
+                public void modifyText(ModifyEvent e) {
+                    editOccured(e);
+                }
+            };
+        }
+        return modifyListener;
+    }
+    
+    /**
+     * Processes a modify event that occurred in this text cell editor.
+     * This framework method performs validation and sets the error message
+     * accordingly, and then reports a change via <code>fireEditorValueChanged</code>.
+     * Subclasses should call this method at appropriate times. Subclasses
+     * may extend or reimplement.
+     *
+     * @param e the SWT modify event
+     */
+    protected void editOccured(ModifyEvent e) {
+       String value = text.getText();
+       if (value == null) {
+               value = "";//$NON-NLS-1$
+       }
+       Object typedValue = value;
+
+       boolean oldValidState = isValueValid();
+       boolean newValidState = isCorrect(typedValue);
+
+       valueChanged(oldValidState, newValidState);
+
+    }
+    
+    /**
+     * Checks to see if the selection state (selection /
+     * no selection) has changed and if so fire an
+     * enablement changed notification.
+     */
+    private void checkSelection() {
+        boolean oldIsSelection = isSelection;
+        isSelection = text.getSelectionCount() > 0;
+        if (oldIsSelection != isSelection) {
+            fireEnablementChanged(COPY);
+            fireEnablementChanged(CUT);
+        }
+    }
+    
+    /**
+     * Checks to see if the "deletable" state (can delete/
+     * nothing to delete) has changed and if so fire an
+     * enablement changed notification.
+     */
+    private void checkDeleteable() {
+        boolean oldIsDeleteable = isDeleteable;
+        isDeleteable = isDeleteEnabled();
+        if (oldIsDeleteable != isDeleteable) {
+            fireEnablementChanged(DELETE);
+        }
+    }
+    
+    /**
+     * Checks to see if the "selectable" state (can select)
+     * has changed and if so fire an enablement changed notification.
+     */
+    private void checkSelectable() {
+        boolean oldIsSelectable = isSelectable;
+        isSelectable = isSelectAllEnabled();
+        if (oldIsSelectable != isSelectable) {
+            fireEnablementChanged(SELECT_ALL);
+        }
+    }
+
+    
+    /**
+     * Handles a default selection event from the text control by applying the editor
+     * value and deactivating this cell editor.
+     * 
+     * @param event the selection event
+     * 
+     * @since 3.0
+     */
+    protected void handleDefaultSelection(SelectionEvent event) {
+        // same with enter-key handling code in keyReleaseOccured(e);
+        fireApplyEditorValue();
+        deactivate();
+    }
+    
+    /**
+     * Updates the controls showing the value of this cell editor.
+     * <p>
+     * 
+     * The default implementation of this framework method just converts
+     * the passed object to a string using <code>toString</code> and
+     * sets this as the text of the label widget.
+     * </p>
+     * <p>
+     * Subclasses may reimplement.  If you reimplement this method, you
+     * should also reimplement <code>createContents</code>.
+     * </p>
+     *
+     * @param value the new value of this cell editor
+     */
+    protected void updateContents(Object value) {
+        if (text == null) {
+                       return;
+               }
+
+        String text = "";//$NON-NLS-1$
+        if (value != null) {
+                       text = value.toString();
+               }
+
+        this.text.setText(text);
+    }
+    
+    /** The <code>TextCellEditor</code> implementation of
+    * this <code>CellEditor</code> framework method accepts
+    * a text string (type <code>String</code>).
+    *
+    * @param value a text string (type <code>String</code>)
+    */
+   protected void doSetValue(Object value) {
+     //  Assert.isTrue(text != null && (value instanceof String));
+       text.removeModifyListener(getModifyListener());
+       if(value == null){
+          value = ""; //$NON-NLS-1$
+       }
+       text.setText((String) value);
+       text.addModifyListener(getModifyListener());
+       super.doSetValue(value);
+   }
+       
+    /* (non-Javadoc)
+     * Method declared on CellEditor.
+     */
+    protected void doSetFocus() {
+       if (text != null) {
+               text.selectAll();
+               text.setFocus();
+               checkSelection();
+               checkDeleteable();
+               checkSelectable();
+       }
+       button.setFocus();
+//     super.doSetFocus();
+    }
+    
+    /**
+     * Processes a key release event that occurred in this cell editor.
+     * <p>
+     * The <code>TextCellEditor</code> implementation of this framework method 
+     * ignores when the RETURN key is pressed since this is handled in 
+     * <code>handleDefaultSelection</code>.
+     * An exception is made for Ctrl+Enter for multi-line texts, since
+     * a default selection event is not sent in this case. 
+     * </p>
+     *
+     * @param keyEvent the key event
+     */
+    protected void keyReleaseOccured(KeyEvent keyEvent) {
+        if (keyEvent.character == '\r') { // Return key
+            // Enter is handled in handleDefaultSelection.
+            // Do not apply the editor value in response to an Enter key event
+            // since this can be received from the IME when the intent is -not-
+            // to apply the value.  
+            // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control
+            //
+            // An exception is made for Ctrl+Enter for multi-line texts, since
+            // a default selection event is not sent in this case. 
+            if (text != null && !text.isDisposed()
+                    && (text.getStyle() & SWT.MULTI) != 0) {
+                if ((keyEvent.stateMask & SWT.CTRL) != 0) {
+                    super.keyReleaseOccured(keyEvent);
+                }
+            }
+            return;
+        }
+        super.keyReleaseOccured(keyEvent);
+    }
+    
+    /**
+     * The <code>TextCellEditor</code> implementation of
+     * this <code>CellEditor</code> framework method returns
+     * the text string.
+     *
+     * @return the text string
+     */
+    protected Object doGetValue() {
+        return text.getText();
+    }
+    
+    /**
+     * The <code>TextCellEditor</code>  implementation of this 
+     * <code>CellEditor</code> method returns <code>true</code>
+     * if there is a selection or if the caret is not positioned 
+     * at the end of the text.
+     */
+    public boolean isDeleteEnabled() {
+        if (text == null || text.isDisposed()) {
+                       return false;
+               }
+        return text.getSelectionCount() > 0
+                || text.getCaretPosition() < text.getCharCount();
+    }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/Messages.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/Messages.java
new file mode 100644 (file)
index 0000000..7b4c58f
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import org.eclipse.osgi.util.NLS;
+
+public class
+Messages
+extends NLS
+{
+       private static final String BUNDLE_NAME = Messages.class.getName();
+       
+       public static String ELEMENT_NOT_FOUND;
+       
+       public static String AUTOINSERT_BTN;
+       
+       
+       // Profile Items
+       public static String PROFILES_COLUMN1;
+       public static String PROFILES_COLUMN2;
+       public static String PROFILES_COLUMN3;
+       public static String PROFILES_COLUMN4;
+       
+       public static String PROFILES_ADD_BTN;
+       public static String PROFILES_ADD_TOOLTIP;
+       
+       public static String PROFILES_REMOVE_BTN;
+       public static String PROFILES_REMOVE_TOOLTIP;
+       
+       public static String PROFILES_SETACTIVE_BTN;
+       public static String PROFILES_SETACTIVE_TOOLTIP;
+       
+       public static String NOTE_LABEL;
+       public static String NOTE_DESC;
+       
+       
+       public static String ERROR_DIALOG_TITLE;
+       public static String ERROR_DIALOG_NOT_SELECTED;
+       
+       public static String FileBrowserCellEditor_2;
+       
+       static {
+               // initialize resource bundle
+               NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+       }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/Messages.properties b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/Messages.properties
new file mode 100644 (file)
index 0000000..8737002
--- /dev/null
@@ -0,0 +1,23 @@
+ELEMENT_NOT_FOUND=element not found
+AUTOINSERT_BTN=Insert signature at launching
+
+PROFILES_COLUMN1=Certificate path
+PROFILES_COLUMN2=Pass
+PROFILES_COLUMN3=CA path(Optional)
+PROFILES_COLUMN4=Root CA path(Optional)
+PROFILES_ADD_BTN=Add
+PROFILES_ADD_TOOLTIP=Add Profile
+
+PROFILES_REMOVE_BTN=Remove
+PROFILES_REMOVE_TOOLTIP=Remove Profile
+
+NOTE_LABEL=Note:
+NOTE_DESC=(The following format characters are supported in identifier string\n%a:Author, %f:Fingerprint, %w:Widget, %h:Hash, %t:Time)
+
+PROFILES_SETACTIVE_BTN=Set Active
+PROFILES_SETACTIVE_TOOLTIP=Set Active Profile
+
+ERROR_DIALOG_TITLE=Profile does not exist
+ERROR_DIALOG_NOT_SELECTED=Select a profile first
+
+FileBrowserCellEditor_2=Select a certificate file
\ No newline at end of file
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileCellModifier.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileCellModifier.java
new file mode 100644 (file)
index 0000000..1a1e550
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.widgets.TableItem;
+import org.tizen.common.sign.util.SigningProfileUtil;
+
+public class ProfileCellModifier implements ICellModifier {
+
+       private TableViewer viewer;
+       private SigningPreferencePage page;
+       
+
+       public ProfileCellModifier(TableViewer viewer, SigningPreferencePage signingPreferencePage) {
+               this.viewer = viewer;
+               this.page = signingPreferencePage;
+       }
+       
+       @Override
+       public boolean canModify(Object element, String property) {
+               return true;
+       }
+
+       @Override
+       public Object getValue(Object element, String property) {
+               
+               if (element instanceof SigningProfileItem) {
+                       if (property.equals(SigningProfileUtil.ITEM_ATTR_PASS)) {
+                               return ((SigningProfileItem)element).getPassword();
+                       } else if (property.equals(SigningProfileUtil.ITEM_ATTR_KEY)) {
+                               return ((SigningProfileItem)element).getKeyLocation();
+                       }
+                       else if (property.equals(SigningProfileUtil.ITEM_ATTR_CA)) {
+                return ((SigningProfileItem)element).getCAPath();
+            }
+                       else if (property.equals(SigningProfileUtil.ITEM_ATTR_ROOTCA)) {
+                return ((SigningProfileItem)element).getRootCAPath();
+            }
+               }
+               return null;
+       }
+
+       @Override
+       public void modify(Object element, String property, Object value) {
+               if (element instanceof TableItem) {
+                       Object data = ((TableItem)element).getData();
+                       SigningProfileItem profileItem = (SigningProfileItem)data;
+                       String _value = (String) value;
+                       if (data instanceof SigningProfileItem) {
+                               if (property.equals(SigningProfileUtil.ITEM_ATTR_PASS)) {
+                                   profileItem.setPassword(_value.toCharArray());
+                               }
+                               else if (property.equals(SigningProfileUtil.ITEM_ATTR_KEY)) {
+                                       if (profileItem.getKeyLocation() == null || profileItem.getKeyLocation().trim().length() == 0) {
+                                               if (profileItem.getIdentifier() == null || profileItem.getIdentifier().trim().length() == 0) {
+                                               }
+                                       }
+                                       profileItem.setKeyLocation(_value);
+                               }
+                               else if(property.equals(SigningProfileUtil.ITEM_ATTR_CA)) {
+                                   profileItem.setCAPath(_value);
+                               }
+                               else if(property.equals(SigningProfileUtil.ITEM_ATTR_ROOTCA)) {
+                                   profileItem.setRootCAPath(_value);
+                               }
+                       }
+               viewer.update(data, null);
+               page.validatePreferencePage();
+               }
+       }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileItemContentProvider.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileItemContentProvider.java
new file mode 100644 (file)
index 0000000..40251b8
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class ProfileItemContentProvider implements IStructuredContentProvider {
+       
+       @Override
+       public Object[] getElements(Object inputElement) {
+               if (inputElement instanceof SigningProfile) {
+                       List<SigningProfileItem> profileItemList = ((SigningProfile)inputElement).getProfileItemList();
+                       return profileItemList.toArray();
+               }
+               return null;
+       }
+
+       @Override
+       public void dispose() {
+       }
+
+       @Override
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+       }
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileItemLabelProvider.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/ProfileItemLabelProvider.java
new file mode 100644 (file)
index 0000000..b8e545b
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class
+ProfileItemLabelProvider
+extends LabelProvider
+implements ITableLabelProvider
+{
+
+       @Override
+       public Image getColumnImage(Object element, int columnIndex) {
+               return null;
+       }
+
+       @Override
+       public String getColumnText(Object element, int columnIndex) {
+               if (columnIndex == 0) {
+                       if (element instanceof SigningProfileItem) {
+                               return ((SigningProfileItem)element).getKeyLocation();
+                       }
+               } else if (columnIndex == 1) {
+                       if (element instanceof SigningProfileItem) {
+                           char[] identifier = ((SigningProfileItem)element).getPassword();
+                           if(identifier == null) {
+                               return null;
+                           }
+                           int passLength = identifier.length;
+                           StringBuffer result = new StringBuffer();
+                           for(int i=0; i<passLength; i++) {
+                               result.append("*");
+                           }
+                               return result.toString();
+                       }
+               }  else if (columnIndex == 2) {
+                   if(element instanceof SigningProfileItem) {
+                       return ((SigningProfileItem)element).getCAPath();
+                   }
+               } else if(columnIndex == 3) {
+            if(element instanceof SigningProfileItem) {
+                return ((SigningProfileItem)element).getRootCAPath();
+            }              
+               }
+               return Messages.ELEMENT_NOT_FOUND;
+       }
+}
+
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningPreferencePage.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningPreferencePage.java
new file mode 100755 (executable)
index 0000000..4b945b3
--- /dev/null
@@ -0,0 +1,985 @@
+package org.tizen.common.sign.preferences;
+
+import static org.tizen.common.util.SWTUtil.getDisplay;
+import static org.tizen.common.util.StringUtil.EMPTY_STRING;
+import static org.tizen.common.util.StringUtil.isEmpty;
+import static org.tizen.common.util.StringUtil.trim;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.tizen.common.sign.Activator;
+import org.tizen.common.sign.model.Certification.KeyExtension;
+import org.tizen.common.sign.util.SigningProfileUtil;
+import org.tizen.common.util.FileUtil;
+
+public class SigningPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+    public static final String PREFERENCE_PAGE_ID = "org.tizen.common.sign.preferences.SigningPreferencePage"; //$NON-NLS-1$
+    List<SigningProfile> profileList;
+    private TableViewer authorTableViewer;
+    private TableViewer distributorTableViewer;
+    private TableViewer listViewer;
+    public static String defaultProfileKey = "defaultprofile"; //$NON-NLS-1$
+    public String defaultProfileString;
+    private Button addButton, removeButton;
+    private Button clearButton;
+    private Button distClearButton;
+
+    public static String testCertKey = "testCert"; //$NON-NLS-1$
+    private Button testCertButton;
+
+    private IPreferenceStore preferenceStore;
+    
+    public SigningPreferencePage() {
+       preferenceStore = Activator.getDefault().getPreferenceStore();
+       profileList = new ArrayList<SigningProfile>();
+    }
+
+    @Override
+    protected Control createContents(Composite parent) {
+        initializeDialogUnits(parent);
+        List<SigningProfile> _profileList = SigningProfileUtil.populateProfiles();
+        if(_profileList != null) {
+            profileList = _profileList;
+        }
+        Composite composite = new Composite(parent, SWT.NONE);
+        GridLayout layout = new GridLayout();
+        layout.numColumns = 1;
+        layout.marginWidth = 0;
+        layout.marginHeight = 0;
+        composite.setLayout(layout);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        createTestCertButton(composite);
+        createProfileListButtons(composite);
+        createProfileItemsTable(composite);
+        return parent;
+    }
+
+    @Override
+    public void createControl(Composite parent) {
+        super.createControl(parent);
+        Button defaultButton = getDefaultsButton();
+        if (defaultButton != null) {
+            defaultButton.setVisible(false);
+        }
+    }
+    
+    @Override
+    protected void contributeButtons(Composite parent) {
+        GridLayout layout = createGridLayout(3);
+        layout.makeColumnsEqualWidth = false;
+        parent.setLayout(layout);
+        GridData parentData = new GridData(GridData.FILL_BOTH);
+        parentData.grabExcessVerticalSpace = false;
+        parent.setLayoutData(parentData);
+        
+        Composite labelComposite = new Composite(parent, SWT.NONE);
+        GridLayout compLayout = new GridLayout();
+        compLayout.numColumns = 2;
+        
+        labelComposite.setLayout(compLayout);
+        GridData compData = new GridData(GridData.FILL_HORIZONTAL);
+        labelComposite.setLayoutData(compData);
+        
+//        final Label noteLabel = new Label(labelComposite, SWT.NONE);
+//        noteLabel.setText( Messages.NOTE_LABEL );
+//        noteLabel.setFont( new Font( getDisplay(), boldFont( noteLabel.getParent().getFont() ) ) );
+//        GridData noteData = new GridData();
+//        noteData.verticalAlignment = SWT.TOP;
+//        noteLabel.setLayoutData( noteData );
+        
+//        Label label = new Label(labelComposite, SWT.WRAP);
+//        Font smallFont = new Font(Display.getDefault(), smallFont(label.getParent().getFont()));
+//        label.setFont(smallFont);
+//        label.setText( Messages.NOTE_DESC );
+    }
+
+    private void createTestCertButton(Composite composite) {
+        this.testCertButton = new Button(composite, SWT.LEFT | SWT.CHECK);
+        this.testCertButton.setText( Messages.AUTOINSERT_BTN );
+        
+        // get preference value
+        //FIXME make default value false release a4 RC1
+       preferenceStore.setDefault( testCertKey, false );
+               testCertButton.setSelection(preferenceStore.getBoolean(testCertKey));
+               
+        this.testCertButton.addSelectionListener(new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               preferenceStore.setValue(testCertKey, testCertButton.getSelection());
+                       }
+        });
+
+        GridData gridData = new GridData();
+        gridData.horizontalAlignment = GridData.FILL;
+        this.testCertButton.setLayoutData(gridData);
+        this.testCertButton.setFont( composite.getFont() );
+    }
+    
+    private void createProfileItemButtons(Composite composite) {
+        
+        //Add clear button
+        distClearButton = new Button(composite, SWT.NONE);
+        distClearButton.setText(UIMessages.getString("org.tizen.common.sign.profileitem.clear")); //$NON-NLS-1$
+        distClearButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        distClearButton.setEnabled(false);
+        distClearButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                Object distItem = distributorTableViewer.getElementAt(0);
+                if (distItem != null && distItem instanceof SigningProfileItem) {
+                    SigningProfileItem item = (SigningProfileItem)distItem;
+                    item.setIdentifier(EMPTY_STRING); //$NON-NLS-1$
+                    item.setKeyLocation(EMPTY_STRING); //$NON-NLS-1$
+                    item.setCAPath(EMPTY_STRING);
+                    item.setRootCAPath(EMPTY_STRING);
+                    item.setPassword(EMPTY_STRING.toCharArray());
+                    distributorTableViewer.refresh(true);
+                    validatePreferencePage();
+                } 
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+        
+        //Add profile item button
+//        addButton = new Button(composite, SWT.NONE);
+//        addButton.setText( Messages.PROFILES_ADD_BTN );
+//        addButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+//        addButton.addSelectionListener(new SelectionListener() {
+//            @Override
+//            public void widgetSelected(SelectionEvent e) {
+//             final IStructuredSelection ss = (IStructuredSelection) listViewer.getSelection();
+//                if ( ss.isEmpty() )
+//                {
+//                     MessageDialog.openError( getActiveShell(), Messages.ERROR_DIALOG_TITLE, Messages.ERROR_DIALOG_NOT_SELECTED );
+//                     return ;
+//                }
+//                SigningProfileItem profileItem = new SigningProfileItem();
+//                profileItem.setAuthor(false);
+//                profileItem.setIdentifier("%a:%f:%w:%h:%t"); //$NON-NLS-1$
+//                profileItem.setKeyLocation(""); //$NON-NLS-1$
+//                Object input = distributorTableViewer.getInput();
+//                if (input instanceof SigningProfile) {
+//                     SigningProfile profile = (SigningProfile) input;
+//                     profile.addProfileItem(profileItem);
+//                     validatePreferencePage();
+//                }
+//                distributorTableViewer.add(profileItem);
+//            }
+//
+//            @Override
+//            public void widgetDefaultSelected(SelectionEvent e) {
+//            }
+//        });
+//        addButton.setEnabled(false);
+//        
+//        //remove profile item button
+//        removeButton = new Button(composite, SWT.NONE);
+//        removeButton.setText( Messages.PROFILES_REMOVE_BTN );
+//        removeButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+//        removeButton.addSelectionListener(new SelectionListener() {
+//            @Override
+//            public void widgetSelected(SelectionEvent e) {
+//                ISelection selection = distributorTableViewer.getSelection();
+//                if (selection instanceof IStructuredSelection) {
+//                    IStructuredSelection strSelection = (IStructuredSelection) selection;
+//                    Object selelement = strSelection.getFirstElement();
+//                    if (selelement instanceof SigningProfileItem) {
+//                        SigningProfileItem item = (SigningProfileItem) selelement;
+//                        distributorTableViewer.remove(item);
+//                        Object input = distributorTableViewer.getInput();
+//                        if (input instanceof SigningProfile) {
+//                            SigningProfile profile = (SigningProfile) input;
+//                            profile.removeProfileItem(item);
+//                            validatePreferencePage();
+//                        }
+//                    }
+//                }
+//            }
+//
+//            @Override
+//            public void widgetDefaultSelected(SelectionEvent e) {
+//            }
+//        });
+//        removeButton.setEnabled(false);
+    }
+
+    private void createProfileItemsTable(Composite composite) {
+        
+        Group profileItemComosite = new Group(composite, SWT.NONE);
+        profileItemComosite.setText(UIMessages.getString("org.tizen.common.sign.profileitemgrouptitle")); //$NON-NLS-1$
+        GridLayout profileItemLayout = new GridLayout();
+        profileItemLayout.numColumns = 1;
+        profileItemLayout.horizontalSpacing = 4;
+        profileItemComosite.setLayout(profileItemLayout);
+        GridData profileData = new GridData(GridData.FILL_BOTH);
+        profileItemComosite.setLayoutData(profileData);    
+        createAuthorSignatureComp(profileItemComosite);
+        createDistributorSignatureComp(profileItemComosite);
+    }
+    
+    private GridLayout createGridLayout(int numColumns) {
+        GridLayout layout = new GridLayout();
+        layout.numColumns = numColumns;
+        layout.marginHeight = 0;
+        layout.marginWidth = 0;
+        return layout;
+    }
+
+    private void createDistributorSignatureComp(Group profileItemComosite) {
+        Composite distributorComposite = new Composite(profileItemComosite, SWT.NONE);
+        distributorComposite.setLayout(createGridLayout(1));
+        distributorComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        
+        Label distributorLabel = new Label(distributorComposite, SWT.NONE);
+        distributorLabel.setText(UIMessages.getString("org.tizen.common.sign.distrisigtitle")); //$NON-NLS-1$
+        
+        final Composite composite = new Composite(distributorComposite, SWT.NONE);
+        composite.setLayout(createGridLayout(2));
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+    
+        final Composite profileItemTableComposite = new Composite(composite, SWT.NONE);
+        profileItemTableComposite.setLayout(createGridLayout(1));
+        profileItemTableComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+        final Table table = new Table(profileItemTableComposite, SWT.BORDER | SWT.FULL_SELECTION);
+        GridLayout layout = new GridLayout();
+        table.setLayout(layout);
+        table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        
+        table.setHeaderVisible(true);
+        table.setLinesVisible(true);
+
+        final TableColumn column0 = new TableColumn(table, SWT.NONE, 0);
+        column0.setText( Messages.PROFILES_COLUMN1 ); //$NON-NLS-1$
+        column0.pack();
+
+        final TableColumn column1 = new TableColumn(table, SWT.NONE, 1);
+        column1.setText( Messages.PROFILES_COLUMN2 ); //$NON-NLS-1$
+        column1.pack();
+        
+        final TableColumn column2 = new TableColumn(table, SWT.NONE, 2);
+        column2.setText( Messages.PROFILES_COLUMN3 ); //$NON-NLS-1$
+        column2.pack();
+        
+        final TableColumn column3 = new TableColumn(table, SWT.NONE, 3);
+        column3.setText( Messages.PROFILES_COLUMN4 ); //$NON-NLS-1$
+        column3.pack();
+        
+        final CellEditor[] editors = new CellEditor[4];
+        editors[0] = new FileBrowserCellEditor(table);
+        editors[1] = new PasswordTextCellEditor(table);
+        editors[2] = new FileBrowserCellEditor(table) {
+            @Override
+            protected String[] getDialogFilter() {
+                return new String[]{"*.cer"};
+            }
+        };
+        editors[3] = new FileBrowserCellEditor(table) {
+            @Override
+            protected String[] getDialogFilter() {
+                return new String[]{"*.cer"};
+            }
+        };
+
+        distributorTableViewer = new TableViewer(table);
+        distributorTableViewer.setColumnProperties(new String[] { SigningProfileUtil.ITEM_ATTR_KEY, SigningProfileUtil.ITEM_ATTR_PASS, SigningProfileUtil.ITEM_ATTR_CA, SigningProfileUtil.ITEM_ATTR_ROOTCA });
+        distributorTableViewer.setCellEditors(editors);
+        distributorTableViewer.setCellModifier(new ProfileCellModifier(distributorTableViewer, this));
+        distributorTableViewer.setContentProvider(new ProfileItemContentProvider());
+        distributorTableViewer.setLabelProvider(new ProfileItemLabelProvider());
+        table.setEnabled(false);
+        
+        profileItemTableComposite.addControlListener(new ControlAdapter() {
+            public void controlResized(ControlEvent e) {
+                Rectangle area = profileItemTableComposite.getClientArea();
+                Point size = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+                ScrollBar vBar = table.getVerticalBar();
+                
+                int width = area.width  - vBar.getSize().x;
+                if (size.y > area.height + table.getHeaderHeight()) {
+                    Point vBarSize = vBar.getSize();
+                    width -= vBarSize.x;
+                }
+                Point oldSize = table.getSize();
+                int locWidth = (int)(width* .3);
+                int passWidth = width - (locWidth*3);
+                if (oldSize.x > area.width) {
+                    column0.setWidth(locWidth);
+                    column1.setWidth(passWidth);
+                    column2.setWidth(locWidth);
+                    column3.setWidth(locWidth);
+                    table.setSize(area.width, area.height);
+                } else {
+                    table.setSize(area.width, area.height);
+                    column0.setWidth(locWidth);
+                    column1.setWidth(passWidth);
+                    column2.setWidth(locWidth);
+                    column3.setWidth(locWidth);
+                }
+            }
+        });
+        
+        final Composite profileItemButtonComposite = new Composite(composite, SWT.NONE);
+        GridLayout profileItemButtonLayout = new GridLayout();
+        profileItemButtonLayout.numColumns = 1;
+        profileItemButtonLayout.marginWidth = 0;
+        profileItemButtonComposite.setLayout(profileItemButtonLayout);
+        GridData data = new GridData();;
+        data.verticalAlignment = SWT.TOP;
+        profileItemButtonComposite.setLayoutData(data);
+        createProfileItemButtons(profileItemButtonComposite);
+        String defaultProfile = preferenceStore.getString(defaultProfileKey);
+        if (defaultProfile != null) {
+            for (SigningProfile profile : profileList) {
+                if (defaultProfile.equals(profile.getProfileName())) {
+                    if (addButton != null) {
+                        addButton.setEnabled(true);
+                    }
+                    if (removeButton != null) {
+                        removeButton.setEnabled(true);
+                    }
+                    if (clearButton != null) {
+                        clearButton.setEnabled(true);
+                    }
+                    if (distClearButton != null) {
+                        distClearButton.setEnabled(true);
+                    }
+                    distributorTableViewer.getTable().setEnabled(true);
+                    distributorTableViewer.setInput(profile);
+                    authorTableViewer.getTable().setEnabled(true);
+                    authorTableViewer.setInput(profile);
+                }
+            }
+        }
+        
+        if(distributorTableViewer.getTable().getItemCount() == 0) {
+            distributorTableViewer.add(new SigningProfileItem());
+        }
+        composite.addControlListener(new ControlListenerImpl(composite, profileItemTableComposite, profileItemButtonComposite));
+    }
+
+    private void createAuthorSignatureComp(final Group profileItemComosite) {
+        
+        //Create author signature group
+        Composite authorComposite = new Composite(profileItemComosite, SWT.NONE);
+        authorComposite.setLayout(createGridLayout(1));
+        authorComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+        Label authorLabel = new Label(authorComposite, SWT.NONE);
+        authorLabel.setText(UIMessages.getString("org.tizen.common.sign.authorsigtitle")); //$NON-NLS-1$
+
+        final Composite composite = new Composite(authorComposite, SWT.NONE);
+        composite.setLayout(createGridLayout(2));
+        GridData data = new GridData(GridData.FILL_BOTH);
+        composite.setLayoutData(data);
+
+        final Composite authorItemTableComposite = new Composite(composite, SWT.NONE);
+        authorItemTableComposite.setLayout(createGridLayout(1));
+        GridData authorTableData = new GridData(GridData.FILL_BOTH);
+        authorItemTableComposite.setLayoutData(authorTableData);;
+
+        final Table table = new Table(authorItemTableComposite, SWT.BORDER | SWT.FULL_SELECTION | SWT.NO_SCROLL);
+        GridLayout layout = new GridLayout();
+        table.setLayout(layout);
+        GridData tableData = new GridData(GridData.FILL_HORIZONTAL);
+        tableData.grabExcessVerticalSpace = false;
+        table.setLayoutData(tableData);
+        table.setHeaderVisible(true);
+        table.setLinesVisible(true);
+        
+        final TableColumn column0 = new TableColumn(table, SWT.NONE, 0);
+        column0.setText( Messages.PROFILES_COLUMN1 ); //$NON-NLS-1$
+        column0.pack();
+
+        final TableColumn column1 = new TableColumn(table, SWT.NONE, 1);
+        column1.setText( Messages.PROFILES_COLUMN2 ); //$NON-NLS-1$
+        column1.pack();
+        
+        final CellEditor[] editors = new CellEditor[2];
+        editors[0] = new FileBrowserCellEditor(table);
+        editors[1] = new PasswordTextCellEditor(table);
+
+        authorTableViewer = new TableViewer(table);
+        authorTableViewer.setColumnProperties(new String[] { SigningProfileUtil.ITEM_ATTR_KEY, SigningProfileUtil.ITEM_ATTR_PASS});
+        authorTableViewer.setCellEditors(editors);
+        authorTableViewer.setCellModifier(new ProfileCellModifier(authorTableViewer, this));
+        authorTableViewer.getTable().setEnabled(false);
+        authorTableViewer.setContentProvider(new IStructuredContentProvider() {
+            @Override
+            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+            }
+
+            @Override
+            public void dispose() {
+            }
+
+            @Override
+            public Object[] getElements(Object inputElement) {
+                if (inputElement instanceof SigningProfile) {
+                    SigningProfile profile = (SigningProfile)inputElement;
+                    if (profile.getAuthorItem() != null) {
+                        return new SigningProfileItem[] {((SigningProfile)inputElement).getAuthorItem()};
+                    }
+                } 
+                return null;
+            }
+        });
+        authorTableViewer.setLabelProvider(new ProfileItemLabelProvider());
+        authorTableViewer.add(new SigningProfileItem());
+
+        authorItemTableComposite.addControlListener(new ControlAdapter() {
+            public void controlResized(ControlEvent e) {
+                Rectangle area = authorItemTableComposite.getClientArea();
+            
+                Point size = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+                int width = area.width - 15;
+                if (size.y > area.height + table.getHeaderHeight()) {
+                    width -= 15;
+                }
+                Point oldSize = table.getSize();
+                if (oldSize.x > area.width) {
+                    column0.setWidth((int) (width * .75));
+                    column1.setWidth(width - column0.getWidth());
+                    table.setSize(area.width, area.height);
+                } else {
+                    table.setSize(area.width, area.height);
+                    column0.setWidth((int) (width * .75));
+                    column1.setWidth(width - column0.getWidth());
+                }
+            }
+        });
+        
+        final Composite authorItemButtonComposite = new Composite(composite, SWT.NONE);
+        GridData clearButtonData = new GridData();
+        clearButtonData.verticalAlignment = SWT.TOP;
+        authorItemButtonComposite.setLayout(createGridLayout(1));
+        authorItemButtonComposite.setLayoutData(clearButtonData);
+
+        clearButton = new Button(authorItemButtonComposite, SWT.NONE);
+        clearButton.setText(UIMessages.getString("org.tizen.common.sign.profileitem.clear")); //$NON-NLS-1$
+        clearButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        clearButton.setEnabled(false);
+        clearButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                Object authorItem = authorTableViewer.getElementAt(0);
+                if (authorItem != null && authorItem instanceof SigningProfileItem) {
+                    SigningProfileItem item = (SigningProfileItem)authorItem;
+                    item.setPassword(EMPTY_STRING.toCharArray()); //$NON-NLS-1$
+                    item.setKeyLocation(""); //$NON-NLS-1$
+                    authorTableViewer.refresh(true);
+                    validatePreferencePage();
+                } 
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+
+        composite.addControlListener(new ControlListenerImpl(composite, authorItemTableComposite, authorItemButtonComposite));
+    }
+
+    private void createProfileListButtons(Composite composite) {
+        
+        final Group profileComposite = new Group(composite, SWT.NONE);
+        profileComposite.setText(UIMessages.getString("org.tizen.common.sign.profilegrouptitle")); //$NON-NLS-1$
+        GridLayout profileLayout = new GridLayout();
+        profileLayout.numColumns = 2;
+        profileLayout.makeColumnsEqualWidth = false;    
+        profileComposite.setLayout(profileLayout);
+        GridData profileData = new GridData(GridData.FILL_BOTH);
+        profileComposite.setLayoutData(profileData);
+    
+        final Composite profileListComposite = new Composite(profileComposite, SWT.NONE);
+        GridLayout profileListLayout = new GridLayout();
+        profileListLayout.numColumns = 1;
+        profileListLayout.marginWidth = 0;
+        profileListLayout.marginHeight = 3;
+        profileListComposite.setLayout(profileListLayout);    
+        GridData listCompositeData = new GridData(GridData.FILL_BOTH);
+        profileListComposite.setLayoutData(listCompositeData);
+        
+        final Composite profileButtonComposite = new Composite(profileComposite, SWT.NONE);
+        GridLayout profileButtonLayout = new GridLayout();
+        profileButtonLayout.numColumns = 1;
+        profileButtonLayout.marginWidth = 0;
+        profileButtonLayout.marginHeight = 3;
+        GridData data = new GridData();
+        data.verticalAlignment = SWT.TOP;
+        profileButtonComposite.setLayout(profileButtonLayout);
+        profileButtonComposite.setLayoutData(data);
+        
+        profileComposite.addControlListener(new ControlListenerImpl(profileComposite, profileListComposite, profileButtonComposite));
+        
+        final Button addProfileButton = new Button(profileButtonComposite, SWT.NONE);
+        addProfileButton.setText( Messages.PROFILES_ADD_BTN );
+        addProfileButton.setLayoutData(new GridData(GridData.FILL_BOTH));
+        addProfileButton.setToolTipText( Messages.PROFILES_ADD_TOOLTIP );
+        addProfileButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+               InputValidator validator = new InputValidator(profileList);
+                InputDialog dialog = new InputDialog(Display.getDefault().getActiveShell(), UIMessages.getString("org.tizen.common.sign.profilename"), UIMessages.getString("org.tizen.common.sign.entername"), "", validator); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                dialog.open();
+                if (dialog.getReturnCode() == Dialog.OK) {
+                    SigningProfile profile = new SigningProfile();
+                    profile.setProfileName(dialog.getValue().trim());
+                    SigningProfileItem authorProfileItem = new SigningProfileItem();
+                    authorProfileItem.setAuthor(true);
+                    authorProfileItem.setIdentifier(EMPTY_STRING); //$NON-NLS-1$
+                    authorProfileItem.setKeyLocation(EMPTY_STRING); //$NON-NLS-1$
+                    authorProfileItem.setCAPath( SigningProfileUtil.getAuthorCAPath() );
+                    authorProfileItem.setRootCAPath(EMPTY_STRING);
+                    profile.setAuthorItem(authorProfileItem);
+                    profileList.add(profile);
+                    if ("".equals(defaultProfileString) && profileList.size() == 1) { //$NON-NLS-1$
+                        defaultProfileString = dialog.getValue().trim();
+                    }
+                    listViewer.add(profile);
+                    listViewer.setSelection(new StructuredSelection(profile));
+                    validatePreferencePage();
+                }
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+
+        Button modifyProfilesButton = new Button(profileButtonComposite, SWT.NONE);
+        modifyProfilesButton.setText(UIMessages.getString("org.tizen.common.sign.profile.modify")); //$NON-NLS-1$
+        modifyProfilesButton.setLayoutData(new GridData(GridData.FILL_BOTH));
+        modifyProfilesButton.setToolTipText(UIMessages.getString("org.tizen.common.sign.modifytooltip")); //$NON-NLS-1$
+        modifyProfilesButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                ISelection selection = listViewer.getSelection();
+                if (selection instanceof IStructuredSelection) {
+                    Object object = ((IStructuredSelection) selection).getFirstElement();
+                    if (object instanceof SigningProfile) {
+                        SigningProfile profile = (SigningProfile) object;
+                        InputValidator validator = new InputValidator(profileList, profile.getProfileName());
+                        InputDialog dialog = new InputDialog(Display.getDefault().getActiveShell(), UIMessages.getString("org.tizen.common.sign.profilename"), UIMessages.getString("org.tizen.common.sign.entername"), profile.getProfileName(), validator); //$NON-NLS-1$ //$NON-NLS-2$
+                        dialog.open();
+                        if (dialog.getReturnCode() == Dialog.OK) {
+                            if (((SigningProfile) object).getProfileName().compareTo(defaultProfileString) == 0) {
+                                defaultProfileString = dialog.getValue().trim();
+                            }                        
+                            ((SigningProfile) object).setProfileName(dialog.getValue().trim());
+                            listViewer.update(object, null);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+        
+        Button defaultProfileButton = new Button(profileButtonComposite, SWT.NONE);
+        defaultProfileButton.setText( Messages.PROFILES_SETACTIVE_BTN );
+        defaultProfileButton.setLayoutData(new GridData(GridData.FILL_BOTH));
+        defaultProfileButton.setToolTipText( Messages.PROFILES_SETACTIVE_TOOLTIP );
+        defaultProfileButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                ISelection selection = listViewer.getSelection();
+                if (selection instanceof IStructuredSelection) {
+                    Object object = ((IStructuredSelection) selection).getFirstElement();
+                    if (object instanceof SigningProfile) {
+                        defaultProfileString = ((SigningProfile) object).getProfileName();
+                        listViewer.refresh(true);
+                    }
+                }
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+        
+        final Button removeProfileButton = new Button(profileButtonComposite, SWT.NONE);
+        removeProfileButton.setText( Messages.PROFILES_REMOVE_BTN );
+        removeProfileButton.setLayoutData(new GridData(GridData.FILL_BOTH));
+        removeProfileButton.setToolTipText( Messages.PROFILES_REMOVE_TOOLTIP );
+        removeProfileButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                ISelection selection = listViewer.getSelection();
+                if (selection instanceof IStructuredSelection) {
+                    Object object = ((IStructuredSelection) selection).getFirstElement();
+                    if (object instanceof SigningProfile) {
+                        profileList.remove(object);
+                        if (((SigningProfile) object).getProfileName().compareTo(defaultProfileString) == 0) {
+                            defaultProfileString = EMPTY_STRING;
+                        }    
+                        if (addButton != null) {
+                            addButton.setEnabled(false);
+                        }
+                        if (removeButton != null) {
+                            removeButton.setEnabled(false);
+                        }
+                        if (clearButton != null) {
+                            clearButton.setEnabled(false);
+                            authorTableViewer.getTable().setEnabled(false);
+                        }
+                        if (distClearButton != null) {
+                            distClearButton.setEnabled(true);
+                        }
+                        if (profileList.size() == 1) {
+                            SigningProfile profile = profileList.get(0);
+                            if (profile != null) {
+                                defaultProfileString = profile.getProfileName();
+                                listViewer.setSelection(new StructuredSelection(profile));
+                            } 
+                        } 
+                        listViewer.remove(object);
+                        listViewer.refresh(true);
+                        distributorTableViewer.remove(((SigningProfile) object).getProfileItemList().toArray());
+                        authorTableViewer.remove(((SigningProfile) object).getAuthorItem());
+                        validatePreferencePage();
+                    }
+                }
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+        
+        listViewer = new TableViewer(profileListComposite);
+        GridData listData = new GridData(GridData.FILL_BOTH);
+        listViewer.getTable().setLayoutData(listData);
+        listViewer.setContentProvider(new ListViewerContentProvider(profileList));
+
+        class ListLabelProvider extends LabelProvider implements IFontProvider{
+            @Override
+            public Font getFont(Object element) {
+                if (element instanceof SigningProfile) {
+                    if (defaultProfileString != null && ((SigningProfile) element).profileName.compareTo(defaultProfileString) == 0) {
+                        return new Font(Display.getDefault(), boldFont(listViewer.getTable().getFont()));
+                    }
+                }
+                return null;
+            };
+            
+            public String getText(Object element) {
+                if (element instanceof SigningProfile) {
+                    if (defaultProfileString != null && ((SigningProfile) element).profileName.compareTo(defaultProfileString) == 0) {
+                        return ((SigningProfile) element).profileName + " (Active)"; //$NON-NLS-1$
+                    }
+                    return ((SigningProfile) element).profileName;
+                }
+                return null;
+            }
+            
+            @Override
+            public Image getImage(Object element) {
+                return super.getImage(element);
+            }
+        }
+        listViewer.setLabelProvider(new ListLabelProvider());
+
+        listViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+            @Override
+            public void selectionChanged(SelectionChangedEvent event) {
+                ISelection selection = event.getSelection();
+                if (selection instanceof IStructuredSelection) {
+                    StructuredSelection structuredSel = (StructuredSelection) selection;
+                    Object selElement = structuredSel.getFirstElement();
+                    if (selElement instanceof SigningProfile) {
+                        if (addButton != null) {
+                            addButton.setEnabled(true);
+                        }
+                        if (removeButton != null) {
+                            removeButton.setEnabled(true);
+                        }
+                        if (clearButton != null) {
+                            clearButton.setEnabled(true);
+                        }
+                        if (distClearButton != null) {
+                            distClearButton.setEnabled(true);
+                        }
+                        
+                        SigningProfile profile = (SigningProfile) selElement;
+                        if (distributorTableViewer != null) {
+                            distributorTableViewer.getTable().setEnabled(true);
+                            distributorTableViewer.setInput(profile);
+                        }
+                        if (authorTableViewer != null) {
+                            authorTableViewer.getTable().setEnabled(true);
+                            authorTableViewer.setInput(profile);
+                        }
+                        
+                        if(distributorTableViewer != null && distributorTableViewer.getTable().getItemCount() == 0) {
+                            SigningProfileItem profileItem = new SigningProfileItem();
+                            profileItem.setAuthor(false);
+                            profileItem.setIdentifier(EMPTY_STRING); //$NON-NLS-1$
+                            profileItem.setKeyLocation(EMPTY_STRING); //$NON-NLS-1$
+                            profileItem.setCAPath(EMPTY_STRING);
+                            profileItem.setRootCAPath(EMPTY_STRING);
+                            profile.addProfileItem(profileItem);
+                            validatePreferencePage();
+                            distributorTableViewer.add(profileItem);
+                        }
+                    }
+                }
+            }
+        });
+        defaultProfileString = preferenceStore.getString(defaultProfileKey);
+        listViewer.setInput("profile"); //$NON-NLS-1$
+        if (defaultProfileString != null) {
+            for (SigningProfile profile : profileList) {
+                if (defaultProfileString.equals(profile.getProfileName())) {
+                    listViewer.setSelection(new StructuredSelection(profile));
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void performDefaults() {
+    }
+
+    private void checkFile(String filePath) {
+        if (filePath != null && filePath.trim().length() > 0) {
+            File file = new File(filePath);
+            boolean isValid = true;
+            if (!file.exists() || !file.isFile()) {
+                isValid = false;
+            } else {
+                String fileExtension = FileUtil.getFileExtension( filePath );
+                //isValid = KeyExtension.hasExtension( fileExtension ); // for Android keystore
+                isValid = KeyExtension.p12.name().equalsIgnoreCase( fileExtension );
+            }
+            if (!isValid) {
+                setValid(false);
+                setErrorMessage(filePath + ": " + UIMessages.getString("org.tizen.common.sign.entervalidp12"));
+            }
+        }
+    }
+
+    protected void validatePreferencePage() {
+        setValid(true);
+        setErrorMessage(null);
+        for (SigningProfile profile : profileList) {
+            if (profile == null) continue;
+
+            List<SigningProfileItem> profileItemList = profile.getProfileItemList();
+            for (SigningProfileItem item : profileItemList) {
+                if (item == null) continue;
+
+                checkFile(item.getKeyLocation());
+            }
+            
+            SigningProfileItem authorItem = profile.getAuthorItem();
+            if (authorItem != null) {
+                checkFile(authorItem.getKeyLocation());
+            }
+        } 
+    }
+
+    @Override
+    public void init(IWorkbench workbench) {
+    }
+
+    public FontData[] boldFont(Font font) {
+        FontData[] datas = font.getFontData();
+        for (FontData data : datas)
+            data.setStyle(SWT.BOLD);
+        return datas;
+    }
+
+    public FontData[] smallFont(Font font) {
+        FontData[] datas = font.getFontData();
+        for (FontData data : datas)
+            data.setHeight(data.getHeight() - 1);
+        return datas;
+    }
+
+    @Override
+    public boolean performOk() {
+       preferenceStore.setValue(defaultProfileKey, defaultProfileString);
+        SigningProfileUtil.writeProfilesAndProfileItems(this.profileList);
+        return super.performOk();
+    }
+    
+    public class PasswordTextCellEditor extends TextCellEditor {
+        
+        public PasswordTextCellEditor(Composite composite) {
+            super(composite);
+        }
+        
+        @Override
+        protected void doSetValue(Object value) {
+            String _value = null;
+            if(value == null) {
+                _value = "";
+            }
+            else if(value instanceof char[]) {
+                _value = new String((char[])value);
+            }
+            super.doSetValue(_value);
+        }
+        
+        @Override
+        public int getStyle() {
+            return super.getStyle() | SWT.PASSWORD;
+        }
+        
+    }
+}
+
+class ControlListenerImpl implements ControlListener {
+    Composite composite, authorItemTableComposite, authorItemButtonComposite;
+
+    ControlListenerImpl(Composite composite, Composite authorItemTableComposite, Composite authorItemButtonComposite) {
+        this.composite = composite;
+        this.authorItemTableComposite = authorItemTableComposite;
+        this.authorItemButtonComposite = authorItemButtonComposite;
+    }
+
+    @Override
+    public void controlResized(ControlEvent e) {
+        Rectangle area = composite.getClientArea();
+        int width85 = (int) (area.width * 0.85);
+        int width15 = (int) (area.width * 0.15);
+        
+        GridData listCompositeData = new GridData(GridData.FILL_BOTH);
+        listCompositeData.widthHint = width85;
+        authorItemTableComposite.setLayoutData(listCompositeData);
+        
+        GridData data = new GridData();
+        data.verticalAlignment = SWT.TOP;
+        data.widthHint = width15;
+        authorItemButtonComposite.setLayoutData(data);
+    }
+    
+    @Override
+    public void controlMoved(ControlEvent e) {
+    }
+}
+
+class ListViewerContentProvider implements IStructuredContentProvider {
+
+    private List<SigningProfile> list;
+
+    public ListViewerContentProvider(List<SigningProfile> list) {
+        this.list = list;
+    }
+    
+    @Override
+    public Object[] getElements(Object inputElement) {
+        if (inputElement instanceof String) {
+            SigningProfile[] profileItems = new SigningProfile[list.size()];
+            if (((String) inputElement).compareTo("profile") == 0) { //$NON-NLS-1$
+                for (int i=0;i<list.size();i++) {
+                    profileItems[i] = list.get(i);
+                }
+            }
+            return profileItems; 
+        }
+        return null;
+    }
+
+    @Override
+    public void dispose() {
+    }
+
+    @Override
+    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+    }
+}
+
+class InputValidator implements IInputValidator {
+    protected final String profileName;
+
+    protected final List<SigningProfile> list;
+
+    InputValidator(List<SigningProfile> profileList) {
+       this( profileList, null );
+    }
+
+    InputValidator(List<SigningProfile> profileList, final String profileName ) {
+       this.list = profileList;
+       this.profileName = profileName;
+    }
+    
+    public String isValid(String newText) {
+       if ( isEmpty( newText ) )
+       {
+               return EMPTY_STRING;
+       }
+       final String safeText = trim( newText );
+       
+       if ( null != profileName && profileName.equals( safeText ) )
+       {
+               return null;
+       }
+       if (checkForDuplicateProfile(newText.trim())) {
+               return UIMessages.getString("org.tizen.common.sign.profile") + " " + safeText + " " + UIMessages.getString("org.tizen.common.sign.aldreadyexists"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+       } else {
+               return null;
+       }
+    }
+
+    protected boolean checkForDuplicateProfile(String string) {
+        for (SigningProfile profile : list) {
+            if (profile.getProfileName().compareTo(string) == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
+
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfile.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfile.java
new file mode 100644 (file)
index 0000000..2443b31
--- /dev/null
@@ -0,0 +1,44 @@
+package org.tizen.common.sign.preferences;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SigningProfile {
+
+       protected String profileName;
+       
+       ArrayList<SigningProfileItem> profileItemList = new ArrayList<SigningProfileItem>();
+       
+       SigningProfileItem authorItem = null;
+       
+       public String getProfileName() {
+               return profileName;
+       }
+       
+       public void setProfileName(String profileName) {
+               this.profileName = profileName;
+       }
+       
+       
+       public void addProfileItem(SigningProfileItem item){
+               profileItemList.add(item);
+       }
+       
+       public void removeProfileItem(SigningProfileItem item){
+               profileItemList.remove(item);
+       }
+       
+       public List<SigningProfileItem> getProfileItemList() {
+               return Collections.unmodifiableList( profileItemList );
+       }
+       
+       public void setAuthorItem(SigningProfileItem authorItem) {
+               this.authorItem = authorItem;
+       }
+       
+       public SigningProfileItem getAuthorItem() {
+               return authorItem;
+       }
+       
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfileItem.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfileItem.java
new file mode 100644 (file)
index 0000000..17b04e4
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ * Bonyong Lee <bonyong.lee@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+
+
+/**
+ * <p>
+ * SigningProfileItem.
+ * 
+ * Singing Profile Item information container
+ * </p>
+ * 
+ * @author BonYong Lee{@literal <bonyong.lee@samsung.com>} (S-Core)
+ */
+public class
+SigningProfileItem
+{
+    /**
+     * Key file path
+     */
+    protected String keyLocation;
+    
+    protected String caPath;
+    
+    protected String rootCAPath;
+    
+    /**
+     * Identifier
+     */
+    protected String id;
+    
+    /**
+     * Password if exists
+     */
+    protected char[] password;
+    
+    /**
+     * Flag if signature is for author
+     */
+    protected boolean bAuthor;
+    
+    public SigningProfileItem()
+    {
+        this("", "", false, "", "");
+    }
+    
+    public SigningProfileItem( final String keyLocation, final String id, final boolean bAuthor )
+    {
+        this( keyLocation, id, bAuthor, "", "");
+    }
+
+    public SigningProfileItem( final String keyLocation, final String id, final boolean bAuthor, final String caPath, final String rootCAPath ) {
+        this.keyLocation = keyLocation;
+        this.id = id;
+        this.bAuthor = bAuthor;
+        this.caPath = caPath;
+        this.rootCAPath = rootCAPath;
+        this.password = "".toCharArray();
+    }
+    
+    /**
+     * Return identifier
+     * 
+     * example - "%a:%f:%w:%h:%t"
+     * 
+     * @return identifier
+     * 
+     * @see #id
+     */
+    public
+    String
+    getIdentifier()
+    {
+        return this.id;
+    }
+    
+    /**
+     * Set identifier
+     * 
+     * @param id new identifier
+     * 
+     * @see #id
+     */
+    public
+    void
+    setIdentifier(
+        final String id
+    )
+    {
+        this.id = id;
+    }
+    
+    /**
+     * Return key location path
+     * 
+     * @return key location
+     */
+    public
+    String
+    getKeyLocation()
+    {
+        return this.keyLocation;
+    }
+    
+    /**
+     * Set key location path
+     * 
+     * @param keyLocation
+     */
+    public
+    void
+    setKeyLocation(
+        final String keyLocation
+    )
+    {
+        this.keyLocation = keyLocation;
+    }
+    
+    public String getCAPath() {
+        return caPath;
+    }
+
+    public void setCAPath(final String caPath) {
+        this.caPath = caPath;
+    }
+
+    public String getRootCAPath() {
+        return rootCAPath;
+    }
+
+    public void setRootCAPath(final String rootCAPath) {
+        this.rootCAPath = rootCAPath;
+    }
+
+    /**
+     * open {@link InputStream} for key file
+     * 
+     * @return {@link InputStream}
+     * 
+     * @throws IOException If exception occureed in open stream
+     */
+    public
+    InputStream
+    openKeyInputStream()
+    throws IOException
+    {
+        return new FileInputStream( this.keyLocation );
+    }
+    
+    /**
+     * Return flag if signing is for author or distributor
+     * 
+     * @return <code>true</code> if signing is for author
+     */
+    public
+    boolean
+    isAuthor()
+    {
+        return this.bAuthor;
+    }
+    
+    /**
+     * Set flag for author
+     * 
+     * @param isAuthor new flag
+     */
+    public
+    void
+    setAuthor(
+        final boolean isAuthor
+    )
+    {
+        this.bAuthor = isAuthor;
+    }
+    
+    /**
+     * Return password for certification file
+     * 
+     * @return password
+     */
+    public
+    char[] getPassword()
+    {
+        if ( null == this.password )
+        {
+            return null;
+        }
+        final char[] password = new char[this.password.length];
+        System.arraycopy( this.password, 0, password, 0, this.password.length );
+        
+        return password;
+    }
+    /**
+     * Set password for certification file
+     * 
+     * @param password password
+     */
+    public
+    void
+    setPassword(
+        final char[] password
+    )
+    {
+        if ( null == password )
+        {
+            this.password = password;
+            return ;
+        }
+        this.password = new char[password.length];
+        System.arraycopy( password, 0, this.password, 0, password.length );
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder()
+        .append( this.bAuthor )
+        .append( this.id )
+        .append( this.keyLocation )
+        .append( this.caPath )
+        .append( this.rootCAPath )
+        .toHashCode();
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public
+    boolean
+    equals(
+        final Object obj
+    )
+    {
+        if ( !( obj instanceof SigningProfileItem ) )
+        {
+            return false;
+        }
+        final SigningProfileItem profileItem = (SigningProfileItem) obj;
+        return new EqualsBuilder()
+        .append( this.bAuthor, profileItem.bAuthor )
+        .append( this.id, profileItem.id )
+        .append( this.keyLocation, profileItem.keyLocation )
+        .append( this.caPath, profileItem.caPath )
+        .append( this.rootCAPath, profileItem.rootCAPath )
+        .isEquals();
+    }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfileItemFactory.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/SigningProfileItemFactory.java
new file mode 100644 (file)
index 0000000..01da031
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.preferences;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.tizen.common.Factory;
+import org.tizen.common.core.application.InstallPathConfig;
+import org.tizen.common.sign.Activator;
+import org.tizen.common.util.StringUtil;
+import org.tizen.common.util.log.Logger;
+
+public class
+SigningProfileItemFactory
+implements Factory<SigningProfileItem>{
+
+    protected static final String DEVELOPER_KEY_PASSWORD = "tizenpkcs12passfordsigner"; //$NON-NLS-1$
+
+    /**
+     * Return {@link Activator}
+     * 
+     * @return {@link Activator}
+     * 
+     * @see #getActivator()
+     */
+    public Activator getActivator()
+    {
+        return Activator.getDefault();
+    }
+
+    protected String getDeveloperKeyPath() throws IOException
+    {
+        IPath sdkpath= new Path( InstallPathConfig.getSDKPath() )
+            .append( "tools" )
+            .append( "certificate-generator" )
+            .append( "certificates" )
+            .append( "distributor" )
+            .append( "tizen-distributor-signer.p12" );
+        return sdkpath.toOSString();
+    }
+
+    public SigningProfileItem create() {
+        final SigningProfileItem profileItem = new SigningProfileItem();
+
+        try {
+            profileItem.setKeyLocation( getDeveloperKeyPath() );
+            profileItem.setPassword( DEVELOPER_KEY_PASSWORD.toCharArray() );
+        } catch (IOException e) {
+            Logger.log(e);
+        }
+        profileItem.setIdentifier(StringUtil.EMPTY_STRING); //$NON-NLS-1$
+        profileItem.setAuthor(false);
+        profileItem.setCAPath(StringUtil.EMPTY_STRING);
+        profileItem.setRootCAPath(StringUtil.EMPTY_STRING);
+
+        return profileItem;
+    }
+
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/UIMessages.java b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/UIMessages.java
new file mode 100644 (file)
index 0000000..8c27bb0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Web IDE - sign
+ * 
+ * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Jihoon Song <jihoon80.song@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ * 
+ * Contributors:
+ * - S-Core Co., Ltd
+ * 
+ */
+
+package org.tizen.common.sign.preferences;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class UIMessages {
+
+       private static final String BUNDLE_NAME = "org.tizen.common.sign.preferences.UIMessages"; //$NON-NLS-1$
+       private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+       
+       private UIMessages(){
+       }
+       
+       public static String getString(String key) {
+               try {
+                       return RESOURCE_BUNDLE.getString(key);
+               } catch (MissingResourceException e) {
+                       return '!' + key + '!';
+               }
+       }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/preferences/UIMessages.properties b/org.tizen.common.sign/src/org/tizen/common/sign/preferences/UIMessages.properties
new file mode 100644 (file)
index 0000000..e755cb2
--- /dev/null
@@ -0,0 +1,31 @@
+#Signing
+org.tizen.common.sign.authorerrordialogtitle=Error generating Author Signature
+org.tizen.common.sign.distrierrordialogtitle=Error generating Distributor Signature
+org.tizen.common.sign.authcerterror=Problem generating Author signature. Aborting Author Signature generation.
+org.tizen.common.sign.checkauthorcertificate=Please check the signing configurations at
+org.tizen.common.sign.preference=Signing Preferences
+org.tizen.common.sign.authkeyerror=Problem loading Author private key. Aborting Author Signature generation.
+org.tizen.common.sign.authcertkeyerror=Problem generating Author Signature. Aborting Author Signature generation.
+org.tizen.common.sign.districerterror=Problem generating Distributor signature. Aborting Distributor Signature generation.
+org.tizen.common.sign.distrikeyerror=Problem loading Distributor private key. Aborting Distributor Signature generation.
+org.tizen.common.sign.districertkeyerror=Problem generating Distributor signature. Aborting Distributor Signature generation.
+org.tizen.common.sign.errorloadingkeystore=There was an error while loading certificate file 
+org.tizen.common.sign.authorsignaturegnerated=Author signature generated successfully
+org.tizen.common.sign.distributorsignaturegenerated=Distributor signature generated successfully
+org.tizen.common.sign.checkpassword=Please check the password.
+org.tizen.common.sign.profile=Profile
+org.tizen.common.sign.aldreadyexists=already exists
+org.tizen.common.sign.entervalidp12=Certificate file does not exist
+org.tizen.common.sign.profilename=Profile Name
+org.tizen.common.sign.entername=Enter profile name
+org.tizen.common.sign.modifytooltip=Edit profile name
+org.tizen.common.sign.profilegrouptitle=Profiles
+org.tizen.common.sign.profileitemgrouptitle=Profile Items
+org.tizen.common.sign.profile.modify=Rename
+org.tizen.common.sign.profileitem.clear=Clear
+org.tizen.common.sign.authorsigtitle=Author Certificate
+org.tizen.common.sign.distrisigtitle=Distributor Certificate (Optional)
+org.tizen.common.sign.certificatevalidityerror=There was an error in certificate validity. Aborting Signature generation.
+org.tizen.common.sign.certificatevaliditymessage1=The certificate corresponding to 
+org.tizen.common.sign.certificatevaliditymessage2=is not valid.\nThe certificate is not valid before
+org.tizen.common.sign.certificatevaliditymessage3=and after
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/signer/BuildNumber.java b/org.tizen.common.sign/src/org/tizen/common/sign/signer/BuildNumber.java
new file mode 100644 (file)
index 0000000..5e72951
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ * NativeAppCommon\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Kangho Kim <kh5325.kim@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
+\r
+package org.tizen.common.sign.signer;\r
+\r
+public class BuildNumber {\r
+    static final String DESCRIPTION = "Tizen Signer";\r
+    static final String VERSION_NUMBER = "1.0.0";\r
+    private static final String BUILD_NUMBER = "0001";\r
+    private static final String RECENT_CHANGES = "initial commit";\r
+\r
+    private static final String LINE_SEPARATOR = System.getProperty("line.separator");\r
+    static final String MODULE_INFO =\r
+        DESCRIPTION + LINE_SEPARATOR + "Version: " + VERSION_NUMBER + " [" + BUILD_NUMBER + "]"\r
+            + LINE_SEPARATOR + "Changes: " + RECENT_CHANGES;\r
+\r
+    public static void main(String[] args) {\r
+        System.out.println(MODULE_INFO);\r
+    }\r
+}\r
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/signer/TizenSigner.java b/org.tizen.common.sign/src/org/tizen/common/sign/signer/TizenSigner.java
new file mode 100644 (file)
index 0000000..fff29d4
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Common
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Kangho Kim <kh5325.kim@samsung.com>
+ * NamKoong Ho <ho.namkoong@samsung.com>
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.common.sign.signer;
+
+import org.tizen.common.util.StringUtil;
+import hashsign.HashingSigning;
+
+public class TizenSigner {
+
+    public static void usage() {
+        System.out.println(BuildNumber.DESCRIPTION + " "
+                + BuildNumber.VERSION_NUMBER);
+        System.out.println("Usage:");
+        System.out
+                .println(" java org.tizen.nativeappcommon.signing.signer.TizenSigner dirName certDirName authorAlias authorP12Path authorPassword distAlias distP12Path distPassword");
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length != 11) {
+            usage();
+            return;
+        }
+
+        String targetDir = args[0];
+        String authorCAPath = args[1];
+        String authorP12Path = args[2];
+        String authorPass = args[3];
+        String dist1P12Path = args[4];
+        String dist1Pass = args[5];
+        String dist1CAPath = args[6];
+        String dist2P12Path = args[7];
+        String dist2Pass = args[8];
+        String dist2CAPath = args[9];
+        String dist2RootPath = args[10];
+        
+        authorSign(targetDir, authorP12Path, authorPass, authorCAPath, null);
+        distSign(targetDir, dist1P12Path, dist1Pass, dist1CAPath, null, 1);
+        dist2SignWithParameterCheck(targetDir, dist2P12Path, dist2Pass, dist2CAPath, dist2RootPath);
+    }
+    
+    public static void authorSign(String targetDir, String authorP12Path, String authorPass, String authorCAPath, String rootCaPath) throws Exception{
+        checkNullParameters(targetDir, authorP12Path, authorPass);
+        HashingSigning.AuthorSignature(targetDir, authorP12Path, authorPass, authorCAPath, null);
+    }
+    
+    public static void distSign(String targetDir, String distP12Path, String distPass, String distCAPath, String distRootPath, int distNumber) throws Exception{
+        checkNullParameters(targetDir, distP12Path, distPass);
+        HashingSigning.DistributorSignature(targetDir, distP12Path, distPass, distCAPath, distRootPath, distNumber);
+    }
+    
+    private static void checkNullParameters(String targetDir, String p12Path, String pass) throws IllegalArgumentException{
+        String emptyParameter = null;
+        if(StringUtil.isEmpty(targetDir)) {
+            emptyParameter = "target directory";
+        }
+        else if(StringUtil.isEmpty(p12Path)) {
+            emptyParameter = "certificate location";
+        }
+        else if(StringUtil.isEmpty(pass)) {
+            emptyParameter = "password";
+        }
+        else {
+            return;
+        }
+        throw new IllegalArgumentException(emptyParameter + " is empty");
+    }
+    
+    public static void dist2SignWithParameterCheck(String targetDir, String dist2P12Path, String dist2Pass, String dist2CAPath, String dist2RootPath) throws Exception{
+        if(!StringUtil.isEmpty(dist2P12Path) && !StringUtil.isEmpty(dist2Pass)) {
+            if(StringUtil.isEmpty(dist2CAPath) || StringUtil.isEmpty(dist2RootPath)) {
+                dist2CAPath = null;
+                dist2RootPath = null;
+            }
+            distSign(targetDir, dist2P12Path, dist2Pass, dist2CAPath, dist2RootPath, 2);
+        }
+    }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/ui/Messages.java b/org.tizen.common.sign/src/org/tizen/common/sign/ui/Messages.java
new file mode 100644 (file)
index 0000000..8982699
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+ * Common\r
+*\r
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+*\r
+* Contact:\r
+* NamKoong Ho <ho.namkoong@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
+\r
+package org.tizen.common.sign.ui;\r
+\r
+import org.eclipse.osgi.util.NLS;\r
+import org.tizen.common.sign.Activator;\r
+\r
+public final class Messages extends NLS {\r
+\r
+    private static final String BUNDLE_NAME = Activator.PLUGIN_ID + ".ui.messages";//$NON-NLS-1$\r
+    \r
+    private Messages() {\r
+        // Do not instantiate\r
+    }\r
+\r
+    public static String TizenSigningDialog_title;\r
+    public static String TizenSigningDIalog_messageAuthorPassEmpty;\r
+    public static String TizenSigningDIalog_passGroupLabel;\r
+    public static String TizenSigningDIalog_authorPassLabel;\r
+    public static String TizenSigningDIalog_distPassLabel;\r
+    public static String TizenSigningDIalog_authorPassTooltip;\r
+    public static String TizenSigningDIalog_distPassTooltip;\r
+    public static String TizenSigningDIalog_messageDistPassEmpty;\r
+    public static String TizenSigningDIalog_messageFirst;\r
+    \r
+    static {\r
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/ui/TizenSigningDialog.java b/org.tizen.common.sign/src/org/tizen/common/sign/ui/TizenSigningDialog.java
new file mode 100644 (file)
index 0000000..569d1dc
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Common
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Contact:
+* NamKoong Ho <ho.namkoong@samsung.com>
+*  
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* Contributors:
+* - S-Core Co., Ltd
+*
+*/ 
+
+package org.tizen.common.sign.ui;
+
+import java.util.List;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.window.ApplicationWindow;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.tizen.common.sign.preferences.SigningProfile;
+import org.tizen.common.sign.preferences.SigningProfileItem;
+import org.tizen.common.sign.util.SigningProfileUtil;
+import org.tizen.common.util.SWTUtil;
+import org.tizen.common.util.StringUtil;
+
+public class TizenSigningDialog extends ApplicationWindow{
+
+    private final int GROUP_WIDTH = 500;
+    private final int GROUP_HEIGHT= 150;
+    private final int BUTTON_WIDTH = 70;
+    private boolean closedByOk = false;
+    private final ModifyListener callValidateDialogListener = new ModifyListener() {
+        @Override
+        public void modifyText(ModifyEvent e) {
+            if(validateDialog()) {
+                okButton.setEnabled(true);
+            }
+            else {
+                okButton.setEnabled(false);
+            }
+        }
+    };
+    
+    private Label titleLabel;
+    private Text messageLabel;
+    private Text authorPassText ;
+    private Text distPassText;
+    private Button okButton;
+    private Button saveAuthorPassButton;
+    private Button saveDistPassButton;
+    
+    private String authorPass;
+    private String distPass;
+    private boolean isDistEnabled = false;
+    private boolean open = false;
+    
+    private List<SigningProfile> profileList;
+    private SigningProfile defaultProfile;
+    private SigningProfileItem distProfile;
+    private SigningProfileItem authorProfile;
+    
+    public  TizenSigningDialog(Shell parentShell, List<SigningProfile> profileList) {
+        super(parentShell);
+        
+        this.distPass = "";
+        this.authorPass = "";
+        this.profileList = profileList;
+        this.defaultProfile = SigningProfileUtil.getDefaultProfile(profileList);
+        this.authorProfile = this.defaultProfile.getAuthorItem();
+        char[] _authorPass = this.authorProfile.getPassword(); 
+        if(_authorPass.length == 0) {
+            this.authorPass = "";
+            this.open = true;
+        }
+        else {
+            this.authorPass = new String(_authorPass);
+        }
+        
+        List<SigningProfileItem> distProfileList = this.defaultProfile.getProfileItemList();
+        if(distProfileList.size() > 0) {
+            this.distProfile = distProfileList.get(0);
+            if(!StringUtil.isEmpty(distProfile.getKeyLocation())) {
+                this.isDistEnabled = true;
+                char[] _distPass = this.distProfile.getPassword();
+                if(_distPass.length == 0) {
+                    this.distPass = "";
+                    this.open = true;
+                }
+                else {
+                    this.distPass = new String(_distPass);
+                }
+            }
+        }
+        else {
+            this.distPass = "";
+        }
+    }
+    
+    public boolean isClosedByOk() {
+        return closedByOk;
+    }
+    
+    public boolean isDistEnabled() {
+        return isDistEnabled;
+    }
+    
+    public boolean isOpen() {
+        return open;
+    }
+    
+    protected boolean validateDialog() {
+        
+        String authorPass = this.authorPassText.getText();
+        if("".equals(authorPass)) {
+            setMessage(Messages.TizenSigningDIalog_messageAuthorPassEmpty);
+            return false;
+        }
+        
+        if(isDistEnabled) {
+            String distPass = this.distPassText.getText();
+            if("".equals(distPass)) {
+                setMessage(Messages.TizenSigningDIalog_messageDistPassEmpty);
+                return false;
+            }
+        }
+        
+        
+        setMessage(null);
+        return true;
+    }
+    
+    @Override
+    protected int getShellStyle() {
+        int style = super.getShellStyle();
+        style = style | SWT.APPLICATION_MODAL;
+        return style;
+    }
+    
+    private void setMessage(String message) {
+        if(message == null) {
+            this.messageLabel.setText("");
+            return;
+        }
+        this.messageLabel.setText(message);
+    }
+    
+    @Override
+    protected Control createContents(Composite parent) {
+        Composite mainComposite = new Composite(parent, SWT.NONE);
+        
+        GridLayout layout = new GridLayout();
+        layout.numColumns = 1;
+        layout.marginWidth = 0;
+        layout.marginHeight = 0;
+        layout.marginLeft = 5;
+        layout.marginRight = 5;
+        layout.marginTop = 5;
+        layout.marginBottom = 5;
+        mainComposite.setLayout(layout);
+        SWTUtil.setGridLayoutData(mainComposite, 700, -1, -1, -1, SWT.NONE);
+        createMessageText(mainComposite);
+        createPassGroup(mainComposite);
+        createButtons(mainComposite);
+        this.getShell().setText(Messages.TizenSigningDialog_title);
+        addListeners();
+        
+        if(validateDialog()) {
+            okButton.setEnabled(true);
+        }
+        
+        titleLabel.setText(Messages.TizenSigningDIalog_messageFirst);
+
+        authorPassText.setFocus();
+        this.getShell().setDefaultButton(okButton);
+
+        return mainComposite;
+    }
+
+    private void createMessageText(Composite mainComposite) {
+        titleLabel = new Label(mainComposite, SWT.LEFT);
+        titleLabel.setFont(JFaceResources.getBannerFont());
+        SWTUtil.setGridLayoutData(titleLabel, -1, -1, -1, -1, GridData.FILL_BOTH);
+
+        messageLabel = new Text(mainComposite, SWT.WRAP | SWT.READ_ONLY);
+        messageLabel.setText(" \n "); // two lines//$NON-NLS-1$
+        messageLabel.setFont(JFaceResources.getDialogFont());
+        SWTUtil.setGridLayoutData(messageLabel, -1, -1, -1, -1, GridData.FILL_BOTH);
+    }
+
+    private void addListeners() {
+        this.authorPassText.addModifyListener(this.callValidateDialogListener);
+        this.distPassText.addModifyListener(this.callValidateDialogListener);
+        
+        okButton.addSelectionListener(new SelectionListener() {
+            
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                performOk();
+            }
+            
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+    }
+
+    private void createButtons(Composite parent) {
+        Composite buttonComposite = new Composite(parent, SWT.None);
+        GridLayout buttonComositeLayout = new GridLayout();
+        buttonComositeLayout.numColumns = 3;
+        buttonComositeLayout.makeColumnsEqualWidth = false;
+        buttonComposite.setLayout(buttonComositeLayout);
+        SWTUtil.setGridLayoutData(buttonComposite, -1, -1, -1, -1, GridData.FILL_HORIZONTAL);
+        
+        Label emptyLabel = new Label(buttonComposite, SWT.None);
+        SWTUtil.setGridLayoutData(emptyLabel, -1, -1, -1, -1, GridData.FILL_HORIZONTAL);
+        
+        Button cancelButton = new Button(buttonComposite, SWT.PUSH | SWT.CENTER);
+        cancelButton.setText("Cancel");
+        SWTUtil.setGridLayoutData(cancelButton, -1, BUTTON_WIDTH, -1, -1, SWT.NONE);
+        cancelButton.addSelectionListener(new SelectionListener() {
+            
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                close();
+            }
+            
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+        
+        okButton = new Button(buttonComposite, SWT.PUSH | SWT.CENTER);
+        okButton.setText("OK");
+        SWTUtil.setGridLayoutData(okButton, -1, BUTTON_WIDTH, -1, -1, SWT.NONE);
+        okButton.setEnabled(false);
+    }
+
+    private void createPassGroup(Composite parent) {
+        final Composite passComposite = new Composite(parent, SWT.NONE);
+        GridLayout authorGroupLayout = new GridLayout();
+        authorGroupLayout.numColumns = 2;
+        authorGroupLayout.makeColumnsEqualWidth = false;
+        passComposite.setLayout(authorGroupLayout);
+        
+        SWTUtil.setGridLayoutData(passComposite, GROUP_HEIGHT, GROUP_WIDTH, -1, -1, GridData.FILL_BOTH);
+        
+        Label authorPassLabel = new Label(passComposite, SWT.None);
+        authorPassLabel.setText(Messages.TizenSigningDIalog_authorPassLabel);
+        authorPassLabel.setToolTipText(Messages.TizenSigningDIalog_authorPassTooltip);
+        
+        authorPassText = new Text(passComposite, SWT.BORDER | SWT.PASSWORD);
+        SWTUtil.setGridLayoutData(authorPassText, -1, -1, -1, -1, GridData.FILL_HORIZONTAL);
+        authorPassText.setText(this.authorPass);
+        
+        saveAuthorPassButton = new Button(passComposite, SWT.CHECK);
+        
+        this.saveAuthorPassButton.setSelection(false);
+        SWTUtil.setGridLayoutData(saveAuthorPassButton, -1, -1, 2, -1, SWT.None);
+        saveAuthorPassButton.setText("Save author password");
+        
+        Label distPassLabel = new Label(passComposite, SWT.None);
+        distPassLabel.setText(Messages.TizenSigningDIalog_distPassLabel);
+        distPassLabel.setToolTipText(Messages.TizenSigningDIalog_distPassTooltip);
+        
+        distPassText = new Text(passComposite, SWT.BORDER | SWT.PASSWORD);
+        SWTUtil.setGridLayoutData(distPassText, -1, -1, -1, -1, GridData.FILL_HORIZONTAL);
+        distPassText.setText(this.distPass);
+        
+        saveDistPassButton = new Button(passComposite, SWT.CHECK);
+        this.saveDistPassButton.setSelection(false);
+        SWTUtil.setGridLayoutData(saveDistPassButton, -1, -1, 2, -1, SWT.None);
+        saveDistPassButton.setText("Save distributor password");
+        
+        if(!isDistEnabled) {
+            distPassText.setEnabled(false);
+            saveDistPassButton.setEnabled(false);
+            distPassLabel.setEnabled(false);
+        }
+    }
+    
+    private void performOk() {
+        
+        if(!validateDialog()) {
+            return;
+        }
+        
+        boolean save = false;
+        this.distPass = this.distPassText.getText();
+        this.authorPass = this.authorPassText.getText();
+        
+        if(this.saveAuthorPassButton.getSelection()) {
+            this.authorProfile.setPassword(this.authorPassText.getTextChars());
+            save = true;
+        }
+        if(this.saveDistPassButton.getSelection()) {
+            this.distProfile.setPassword(this.distPassText.getTextChars());
+            save = true;
+        }
+        
+        if(save) {
+            SigningProfileUtil.writeProfilesAndProfileItems(profileList);
+        }
+        
+        this.closedByOk = true;
+        this.close();
+    }
+    
+    public String getAuthorPass() {
+        return this.authorPass;
+    }
+    
+    public String getDistPass() {
+        return this.distPass;
+    }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/ui/messages.properties b/org.tizen.common.sign/src/org/tizen/common/sign/ui/messages.properties
new file mode 100644 (file)
index 0000000..1bc7575
--- /dev/null
@@ -0,0 +1,9 @@
+TizenSigningDIalog_messageAuthorPassEmpty=Input author password.
+TizenSigningDIalog_messageDistPassEmpty=Input dist password.
+TizenSigningDialog_title=Sign Application
+TizenSigningDIalog_messageFirst=Sign your project
+TizenSigningDIalog_authorGroupLabel=Password
+TizenSigningDIalog_authorPassLabel=Author Password:
+TizenSigningDIalog_distPassLabel=Distributor Password:  
+TizenSigningDIalog_authorPassTooltip=Input Author Password
+TizenSigningDIalog_distPassTooltip=Input Distributor Password
\ No newline at end of file
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/util/SigningProfileUtil.java b/org.tizen.common.sign/src/org/tizen/common/sign/util/SigningProfileUtil.java
new file mode 100644 (file)
index 0000000..73f3fc0
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.util;
+
+import static org.tizen.common.util.StringUtil.isEmpty;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.tizen.common.core.application.InstallPathConfig;
+import org.tizen.common.sign.Activator;
+import org.tizen.common.sign.preferences.SigningPreferencePage;
+import org.tizen.common.sign.preferences.SigningProfile;
+import org.tizen.common.sign.preferences.SigningProfileItem;
+import org.tizen.common.util.ObjectUtil;
+import org.tizen.common.util.ParsingUtil;
+import org.tizen.common.util.StringUtil;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+public class SigningProfileUtil
+{
+       protected static final String PROFILE_ATTR_NAME = "name"; //$NON-NLS-1$
+
+       protected static final String ELEMENT_PROFILE = "profile"; //$NON-NLS-1$
+       protected static final String PROFILE_ELEMENT_ITEM = "profileitem"; //$NON-NLS-1$
+       
+       public static final String ITEM_ATTR_KEY = "key"; //$NON-NLS-1$
+       public static final String ITEM_ATTR_AUTHOR = "author"; //$NON-NLS-1$
+       public static final String ITEM_ATTR_CA = "ca";  //$NON-NLS-1$
+       public static final String ITEM_ATTR_ROOTCA = "rootca";  //$NON-NLS-1$
+       public static final String ITEM_ATTR_PASS = "password";
+       
+       protected static final String PROFILES_FILE = "profiles.xml"; //$NON-NLS-1$
+       
+       protected static final String CERTIFICATE_PATH = "/tools/certificate-generator/certificates/";
+       protected static final String DEVELOPER = "developer";
+       protected static final String DISTRIBUTOR = "distributor";
+       
+       protected static final String AUTHOR_CA = "tizen-developer-ca.cer";
+       protected static final String DISTRIBUTOR1_P12 = "tizen-distributor-signer.p12";
+       protected static final String DISTRIBUTOR1_CA = "tizen-distributor-ca.cer";
+       
+       protected static final String DISTRIBUTOR1_PWD = "tizenpkcs12passfordsigner"; //$NON-NLS-1$
+       
+       protected static final Logger logger = LoggerFactory.getLogger( SigningProfileUtil.class );
+
+       public static SigningProfileItem createDeveloperItem() throws IOException {
+            final SigningProfileItem profileItem = new SigningProfileItem();
+            
+            profileItem.setKeyLocation( getDeveloperKeyPath() );
+            profileItem.setPassword( DISTRIBUTOR1_PWD.toCharArray() );
+            profileItem.setIdentifier( StringUtil.EMPTY_STRING ); //$NON-NLS-1$
+            profileItem.setAuthor( false );
+            profileItem.setCAPath( SigningProfileUtil.getDeveloperCAPath() );
+            profileItem.setRootCAPath( StringUtil.EMPTY_STRING );
+            
+            return profileItem;
+           }
+       
+       protected static SigningProfileItem createItem( Node node )
+       {
+               if ( !(node instanceof Element ) )
+               {
+                       return null;
+               }
+                       
+               final SigningProfileItem profileItem = new SigningProfileItem();
+               
+               final Element itemElement = (Element) node;
+               
+               final String key = itemElement.getAttribute( ITEM_ATTR_KEY );
+               final String author = itemElement.getAttribute( ITEM_ATTR_AUTHOR );
+               final String ca = itemElement.getAttribute( ITEM_ATTR_CA );
+               final String rootca = itemElement.getAttribute( ITEM_ATTR_ROOTCA );
+               final String pass = itemElement.getAttribute(ITEM_ATTR_PASS);
+               logger.trace( "item - key :{}, author :{}, ca :{}, rootca :{}, pass {}", new Object[] { key, author, ca, rootca, pass} );
+               
+               profileItem.setKeyLocation( key );
+               profileItem.setAuthor( ParsingUtil.parseBoolean( author, false ) );
+               profileItem.setCAPath( ca );
+               profileItem.setRootCAPath( rootca );
+               profileItem.setPassword( pass.toCharArray() );
+               
+               return profileItem;
+       }
+       
+       protected static SigningProfile create( final Node node )
+       {
+       if ( !( node instanceof Element ) )
+       {
+               return null;
+       }
+       
+       final SigningProfile profile = new SigningProfile();
+       final Element profileElement = (Element) node;
+       
+       final String profileName = profileElement.getAttribute( PROFILE_ATTR_NAME );
+       profile.setProfileName( profileName );
+       
+       final NodeList itemNodes = profileElement.getElementsByTagName( PROFILE_ELEMENT_ITEM );
+       for ( int i=0, n = itemNodes.getLength() ; i<n ; ++i )
+       {
+               
+               final SigningProfileItem item = createItem( itemNodes.item( i ) );
+               
+               if ( null == item )
+               {
+                       continue;
+               }
+               else if ( item.isAuthor() )
+               {
+                       profile.setAuthorItem( item );
+               }
+               else
+               {
+                       profile.addProfileItem( item );
+               }
+       }
+       
+       return profile;
+       }
+       
+    public static List<SigningProfile> populateProfiles( final InputStream in )
+    {
+        final List<SigningProfile> ret = new ArrayList<SigningProfile>();
+
+        try {
+            final Document document = XMLUtil.create( in );
+            final Node rootNode = document.getFirstChild();
+
+            if ( !( rootNode instanceof Element ) )
+            {
+               return ret;
+            }
+
+            final Element rootElement = (Element) rootNode;
+            final NodeList profileNodes = rootElement.getElementsByTagName( ELEMENT_PROFILE );
+            for ( int i = 0, n = profileNodes.getLength() ; i < n ; ++i )
+            {
+               final Node profileNode = profileNodes.item( i );
+               
+               SigningProfile profile = create( profileNode );
+               if ( null == profile )
+               {
+                       continue;
+               }
+               ret.add(profile);
+            }
+        } catch (ParserConfigurationException e) {
+            logger.error( "Can't parse xml", e );
+        } catch (SAXException e) {
+               logger.error( "Can't parse xml", e );
+        } catch (IOException e) {
+               logger.error( "Can't parse xml", e );
+        }
+        return ret;
+    }
+
+    public static SigningProfile extractProfile( final InputStream in, final String profileName )
+    {
+       if ( isEmpty( profileName ) )
+       {
+               return null;
+       }
+       
+        try {
+            final Document document = XMLUtil.create( in );
+            final Node rootNode = document.getFirstChild();
+
+            if ( !( rootNode instanceof Element ) )
+            {
+               return null;
+            }
+
+            final Element rootElement = (Element) rootNode;
+            final NodeList profileNodes = rootElement.getElementsByTagName( ELEMENT_PROFILE );
+            for ( int i = 0, n = profileNodes.getLength() ; i < n ; ++i )
+            {
+               final Node profileNode = profileNodes.item( i );
+               
+               final SigningProfile profile = create( profileNode );
+               if ( null == profile )
+               {
+                       continue;
+               }
+               if ( ObjectUtil.equals( profileName, profile.getProfileName()) )
+               {
+                       return profile;
+               }
+            }
+        } catch (ParserConfigurationException e) {
+            logger.error( "Can't parse xml", e );
+        } catch (SAXException e) {
+               logger.error( "Can't parse xml", e );
+        } catch (IOException e) {
+               logger.error( "Can't parse xml", e );
+        }
+        return null;
+    }
+    
+    
+       public static InputStream openProfileFile( File file )
+       {
+               try {
+                       if (!file.exists()) {
+                               return null;
+                       }
+                       
+                       return new FileInputStream( file );
+               }
+               catch ( final IllegalStateException e)
+               {
+                       logger.error( "Can't access state location", e );
+               }
+               catch ( final FileNotFoundException e )
+               {
+                       logger.debug( "Can't open profile", e );
+               }
+               
+               return null;
+       }
+       
+       public static List<SigningProfileItem> parseProfileFile( final InputStream in, final String profileName )
+       {
+               final ArrayList<SigningProfileItem> ret = new ArrayList<SigningProfileItem>();
+               if ( null == in )
+               {
+                       return ret;
+               }
+               
+               final SigningProfile profile = SigningProfileUtil.extractProfile( in, profileName );
+               if ( null == profile )
+               {
+                       return ret;
+               }
+               if ( null != profile.getAuthorItem() )
+               {
+                       ret.add( profile.getAuthorItem() );
+               }
+               ret.addAll( profile.getProfileItemList() );
+               return ret;
+       }
+
+       public static IPreferenceStore getPreferenceStore() {
+           return Activator.getDefault().getPreferenceStore();
+       }
+
+    public static String getProfilesPath() {
+        IPath location = Activator.getDefault().getStateLocation().append( PROFILES_FILE );
+        return location.toPortableString();
+    }
+    
+    public static void writeProfilesAndProfileItems(List<SigningProfile> profileList) {
+        IPath location = Activator.getDefault().getStateLocation();
+        IPath xmlFiePath = location.append("profiles.xml"); //$NON-NLS-1$
+        File file = new File(xmlFiePath.toOSString());
+
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder documentBuilder;
+        try {
+            documentBuilder = documentBuilderFactory.newDocumentBuilder();
+            Document document = documentBuilder.newDocument();
+            Element profilesElement = document.createElement("profiles"); //$NON-NLS-1$
+
+            for (SigningProfile profile : profileList) {
+                Element profileElement = document.createElement("profile"); //$NON-NLS-1$
+                Attr attribute = document.createAttribute("name"); //$NON-NLS-1$
+                attribute.setNodeValue(profile.getProfileName());
+                profileElement.setAttributeNode(attribute);
+                if (profile.getAuthorItem() != null) {
+                    SigningProfileItem authorItem = profile.getAuthorItem();
+                    profileElement.appendChild(createSigningProfileItem(document, authorItem, "true"));
+                }
+                List<SigningProfileItem> profileItemList = profile.getProfileItemList();
+                for (SigningProfileItem profileItem : profileItemList) {
+                    profileElement.appendChild(createSigningProfileItem(document, profileItem, new Boolean(profileItem.isAuthor()).toString()));
+                }
+                
+                profilesElement.appendChild(profileElement);
+            }
+            
+            document.appendChild(profilesElement);
+            TransformerFactory transformerFactory = TransformerFactory.newInstance();
+            Transformer transformer;
+            try {
+                transformer = transformerFactory.newTransformer();
+                DOMSource source = new DOMSource(document);
+                StreamResult result = new StreamResult(new FileOutputStream(file.getPath()));
+                transformer.transform(source, result);
+            } catch (TransformerConfigurationException e) {
+                org.tizen.common.util.log.Logger.log(e);
+            } catch (TransformerException e) {
+                org.tizen.common.util.log.Logger.log(e);
+            }
+            IFile xmlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(location);
+            xmlFile.refreshLocal(IResource.DEPTH_INFINITE, null);
+        } catch (Exception e) {
+            org.tizen.common.util.log.Logger.error( e.getMessage(), e );
+        }
+    }
+    
+    private static Element createSigningProfileItem(Document document, SigningProfileItem item, String author) {
+        Element profileItemElement = document.createElement("profileitem"); //$NON-NLS-1$
+        Attr keyAttr = document.createAttribute(SigningProfileUtil.ITEM_ATTR_KEY); //$NON-NLS-1$
+        keyAttr.setNodeValue(item.getKeyLocation());
+        Attr caAttr = document.createAttribute(SigningProfileUtil.ITEM_ATTR_CA);
+        caAttr.setNodeValue(item.getCAPath());
+        Attr rootCaAttr = document.createAttribute(SigningProfileUtil.ITEM_ATTR_ROOTCA);
+        rootCaAttr.setNodeValue(item.getRootCAPath());
+        Attr passAttr = document.createAttribute(SigningProfileUtil.ITEM_ATTR_PASS);
+        passAttr.setNodeValue(new String(item.getPassword()));
+        Attr authorAttr = document.createAttribute(SigningProfileUtil.ITEM_ATTR_AUTHOR); //$NON-NLS-1$
+        authorAttr.setNodeValue(author); //$NON-NLS-1$
+        profileItemElement.setAttributeNode(keyAttr);
+        profileItemElement.setAttributeNode(authorAttr);
+        profileItemElement.setAttributeNode(caAttr);
+        profileItemElement.setAttributeNode(rootCaAttr);
+        profileItemElement.setAttributeNode(passAttr);
+        return profileItemElement;
+    }
+    
+    public static List<SigningProfile> populateProfiles() {
+
+        List<SigningProfile> profileList = new ArrayList<SigningProfile>();
+        IPath location = Activator.getDefault().getStateLocation();
+        IPath filePath = location.append("profiles.xml"); //$NON-NLS-1$
+        File file = new File(filePath.toOSString());
+
+        if (!file.exists()) {
+            return profileList;
+        }
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder;
+        try {
+            builder = factory.newDocumentBuilder();
+            Document document = builder.parse(file);
+            Node rootNode = document.getFirstChild();
+
+            if (rootNode != null && rootNode instanceof Element) {
+                Element rootElement = (Element) rootNode;
+                NodeList profileNodes = rootElement.getElementsByTagName("profile"); //$NON-NLS-1$
+                for (int i = 0; i < profileNodes.getLength(); i++) {
+                    Node profileNode = profileNodes.item(i);
+                    if (profileNode instanceof Element) {
+                        SigningProfile profile = new SigningProfile();
+                        Element profileElement = (Element) profileNode;
+                        String profileName = profileElement.getAttribute("name"); //$NON-NLS-1$
+                        profile.setProfileName(profileName);
+                        NodeList profileItemNodes = profileElement.getElementsByTagName("profileitem"); //$NON-NLS-1$
+                        for (int j = 0; j < profileItemNodes.getLength(); j++) {
+                            Node profileItemNode = profileItemNodes.item(j);
+                            if (profileItemNode instanceof Element) {
+                                SigningProfileItem profileItem = new SigningProfileItem();
+                                Element profileItemElement = (Element) profileItemNode;
+                                String profileItemKey = profileItemElement.getAttribute("key"); //$NON-NLS-1$
+                                profileItem.setKeyLocation(profileItemKey);
+                                String profileItemIdentifier = profileItemElement.getAttribute("identifier"); //$NON-NLS-1$
+                                profileItem.setIdentifier(profileItemIdentifier);
+                                String ca = profileItemElement.getAttribute(SigningProfileUtil.ITEM_ATTR_CA);
+                                profileItem.setCAPath(ca);
+                                String pass = profileItemElement.getAttribute(SigningProfileUtil.ITEM_ATTR_PASS);
+                                profileItem.setPassword(pass.toCharArray());
+                                String rootCA = profileItemElement.getAttribute(SigningProfileUtil.ITEM_ATTR_ROOTCA);
+                                profileItem.setRootCAPath(rootCA);
+                                String profileItemAuthor = profileItemElement.getAttribute(SigningProfileUtil.ITEM_ATTR_AUTHOR); //$NON-NLS-1$
+                                if (profileItemAuthor.compareTo("true") == 0) { //$NON-NLS-1$
+                                    profileItem.setAuthor(true);
+                                    profile.setAuthorItem(profileItem);
+                                } else {
+                                    profileItem.setAuthor(false);
+                                    profile.addProfileItem(profileItem);
+                                }
+                            }
+                        }
+                        profileList.add(profile);
+                    }
+                }
+            }
+        } catch (ParserConfigurationException e) {
+            org.tizen.common.util.log.Logger.log(e);
+        } catch (SAXException e) {
+            org.tizen.common.util.log.Logger.log(e);
+        } catch (IOException e) {
+            org.tizen.common.util.log.Logger.log(e);
+        }
+        return profileList;
+    
+    }
+    
+    public static String getAuthorCAPath() {
+         IPath sdkpath= new Path( InstallPathConfig.getSDKPath() )
+             .append( CERTIFICATE_PATH )
+             .append( DEVELOPER )
+             .append( AUTHOR_CA );
+         return sdkpath.toOSString();
+    }
+    
+    public static String getDeveloperKeyPath() {
+         IPath sdkpath= new Path( InstallPathConfig.getSDKPath() )
+             .append( CERTIFICATE_PATH )
+             .append( DISTRIBUTOR )
+             .append( DISTRIBUTOR1_P12 );
+         return sdkpath.toOSString();
+    }
+    
+    public static String getDeveloperCAPath() {
+         IPath sdkpath= new Path( InstallPathConfig.getSDKPath() )
+             .append( CERTIFICATE_PATH )
+             .append( DISTRIBUTOR )
+             .append( DISTRIBUTOR1_CA );
+         return sdkpath.toOSString();
+    }
+    
+    public static SigningProfile getDefaultProfile(List<SigningProfile> profileList) {
+        IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore();
+        
+        String defaultProfile = preferenceStore.getString(SigningPreferencePage.defaultProfileKey);
+        
+        if(defaultProfile == null) {
+            return null;
+        }
+        for(SigningProfile profile: profileList) {
+            if(defaultProfile.equals(profile.getProfileName())) {
+                return profile;
+            }
+        }
+        return null;
+    }
+}
diff --git a/org.tizen.common.sign/src/org/tizen/common/sign/util/XMLUtil.java b/org.tizen.common.sign/src/org/tizen/common/sign/util/XMLUtil.java
new file mode 100644 (file)
index 0000000..9513d2e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Web IDE - sign
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.common.sign.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>
+ * XMLUtil.
+ * 
+ * Util class for DOM
+ * 
+ * </p>
+ * 
+ * @author BonYong Lee{@literal <bonyong.lee@samsung.com>} (S-Core)
+ */
+public class XMLUtil
+{
+       /**
+        * Create {@link Document}
+        * 
+        * @param in {@link InputStream} to provide xml contents
+        * 
+        * @return {@link Document} to be created
+        * 
+        * @throws ParserConfigurationException When {@link DocumentBuilder} can't be created
+        * @throws SAXException When xml can't be parsed
+        * @throws IOException When <code>in</code> throw {@link IOException}
+        */
+       public static
+       Document
+       create(
+               final InputStream in
+       )
+       throws ParserConfigurationException, SAXException, IOException
+       {
+               final DocumentBuilderFactory factory =
+                       DocumentBuilderFactory.newInstance();
+               
+               final DocumentBuilder builder = factory.newDocumentBuilder();
+               
+               return builder.parse( in );
+       }
+
+
+       /**
+        * Create empty {@link Document}
+        * 
+        * @return {@link Document} to be created
+        * 
+        * @throws ParserConfigurationException When {@link DocumentBuilder} can't be created
+        */
+       public static
+       Document
+       create()
+       throws ParserConfigurationException
+       {
+               final DocumentBuilderFactory factory =
+                       DocumentBuilderFactory.newInstance();
+               
+               final DocumentBuilder builder = factory.newDocumentBuilder();
+               
+               return builder.newDocument();
+       }
+
+}