Home | History | Annotate | Download | only in export
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.wizards.export;
     18 
     19 import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
     20 import com.android.ide.eclipse.adt.internal.wizards.export.ExportWizard.ExportWizardPage;
     21 
     22 import org.eclipse.core.resources.IProject;
     23 import org.eclipse.jface.wizard.IWizardPage;
     24 import org.eclipse.swt.SWT;
     25 import org.eclipse.swt.events.ModifyEvent;
     26 import org.eclipse.swt.events.ModifyListener;
     27 import org.eclipse.swt.events.SelectionAdapter;
     28 import org.eclipse.swt.events.SelectionEvent;
     29 import org.eclipse.swt.layout.GridData;
     30 import org.eclipse.swt.layout.GridLayout;
     31 import org.eclipse.swt.widgets.Button;
     32 import org.eclipse.swt.widgets.Combo;
     33 import org.eclipse.swt.widgets.Composite;
     34 import org.eclipse.swt.widgets.Label;
     35 import org.eclipse.swt.widgets.Text;
     36 
     37 import java.io.FileInputStream;
     38 import java.io.FileNotFoundException;
     39 import java.io.IOException;
     40 import java.security.KeyStore;
     41 import java.security.KeyStoreException;
     42 import java.security.NoSuchAlgorithmException;
     43 import java.security.cert.CertificateException;
     44 import java.util.ArrayList;
     45 import java.util.Enumeration;
     46 
     47 /**
     48  * Key Selection Page. This is used when an existing keystore is used.
     49  */
     50 final class KeySelectionPage extends ExportWizardPage {
     51 
     52     private final ExportWizard mWizard;
     53     private Label mKeyAliasesLabel;
     54     private Combo mKeyAliases;
     55     private Label mKeyPasswordLabel;
     56     private Text mKeyPassword;
     57     private boolean mDisableOnChange = false;
     58     private Button mUseExistingKey;
     59     private Button mCreateKey;
     60 
     61     protected KeySelectionPage(ExportWizard wizard, String pageName) {
     62         super(pageName);
     63         mWizard = wizard;
     64 
     65         setTitle("Key alias selection");
     66         setDescription(""); // TODO
     67     }
     68 
     69     @Override
     70     public void createControl(Composite parent) {
     71         Composite composite = new Composite(parent, SWT.NULL);
     72         composite.setLayoutData(new GridData(GridData.FILL_BOTH));
     73         GridLayout gl = new GridLayout(3, false);
     74         composite.setLayout(gl);
     75 
     76         GridData gd;
     77 
     78         mUseExistingKey = new Button(composite, SWT.RADIO);
     79         mUseExistingKey.setText("Use existing key");
     80         mUseExistingKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
     81         gd.horizontalSpan = 3;
     82         mUseExistingKey.setSelection(true);
     83 
     84         new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
     85         gd.heightHint = 0;
     86         gd.widthHint = 50;
     87         mKeyAliasesLabel = new Label(composite, SWT.NONE);
     88         mKeyAliasesLabel.setText("Alias:");
     89         mKeyAliases = new Combo(composite, SWT.READ_ONLY);
     90         mKeyAliases.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
     91 
     92         new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
     93         gd.heightHint = 0;
     94         gd.widthHint = 50;
     95         mKeyPasswordLabel = new Label(composite, SWT.NONE);
     96         mKeyPasswordLabel.setText("Password:");
     97         mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
     98         mKeyPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
     99 
    100         mCreateKey = new Button(composite, SWT.RADIO);
    101         mCreateKey.setText("Create new key");
    102         mCreateKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
    103         gd.horizontalSpan = 3;
    104 
    105         // Show description the first time
    106         setErrorMessage(null);
    107         setMessage(null);
    108         setControl(composite);
    109 
    110         mUseExistingKey.addSelectionListener(new SelectionAdapter() {
    111             @Override
    112             public void widgetSelected(SelectionEvent e) {
    113                 mWizard.setKeyCreationMode(!mUseExistingKey.getSelection());
    114                 enableWidgets();
    115                 onChange();
    116             }
    117         });
    118 
    119         mKeyAliases.addSelectionListener(new SelectionAdapter() {
    120             @Override
    121             public void widgetSelected(SelectionEvent e) {
    122                 mWizard.setKeyAlias(mKeyAliases.getItem(mKeyAliases.getSelectionIndex()));
    123                 onChange();
    124             }
    125         });
    126 
    127         mKeyPassword.addModifyListener(new ModifyListener() {
    128             @Override
    129             public void modifyText(ModifyEvent e) {
    130                 mWizard.setKeyPassword(mKeyPassword.getText());
    131                 onChange();
    132             }
    133         });
    134     }
    135 
    136     @Override
    137     void onShow() {
    138         // fill the texts with information loaded from the project.
    139         if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
    140             // disable onChange for now. we'll call it once at the end.
    141             mDisableOnChange = true;
    142 
    143             // reset the alias from the content of the project
    144             try {
    145                 // reset to using a key
    146                 mWizard.setKeyCreationMode(false);
    147                 mUseExistingKey.setSelection(true);
    148                 mCreateKey.setSelection(false);
    149                 enableWidgets();
    150 
    151                 // remove the content of the alias combo always and first, in case the
    152                 // keystore password is wrong
    153                 mKeyAliases.removeAll();
    154 
    155                 // get the alias list (also used as a keystore password test)
    156                 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    157                 FileInputStream fis = new FileInputStream(mWizard.getKeystore());
    158                 keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
    159                 fis.close();
    160 
    161                 Enumeration<String> aliases = keyStore.aliases();
    162 
    163                 // get the alias from the project previous export, and look for a match as
    164                 // we add the aliases to the combo.
    165                 IProject project = mWizard.getProject();
    166 
    167                 String keyAlias = ProjectHelper.loadStringProperty(project,
    168                         ExportWizard.PROPERTY_ALIAS);
    169 
    170                 ArrayList<String> aliasList = new ArrayList<String>();
    171 
    172                 int selection = -1;
    173                 int count = 0;
    174                 while (aliases.hasMoreElements()) {
    175                     String alias = aliases.nextElement();
    176                     mKeyAliases.add(alias);
    177                     aliasList.add(alias);
    178                     if (selection == -1 && alias.equalsIgnoreCase(keyAlias)) {
    179                         selection = count;
    180                     }
    181                     count++;
    182                 }
    183 
    184                 mWizard.setExistingAliases(aliasList);
    185 
    186                 if (selection != -1) {
    187                     mKeyAliases.select(selection);
    188 
    189                     // since a match was found and is selected, we need to give it to
    190                     // the wizard as well
    191                     mWizard.setKeyAlias(keyAlias);
    192                 } else {
    193                     mKeyAliases.clearSelection();
    194                 }
    195 
    196                 // reset the password
    197                 mKeyPassword.setText(""); //$NON-NLS-1$
    198 
    199                 // enable onChange, and call it to display errors and enable/disable pageCompleted.
    200                 mDisableOnChange = false;
    201                 onChange();
    202             } catch (KeyStoreException e) {
    203                 onException(e);
    204             } catch (FileNotFoundException e) {
    205                 onException(e);
    206             } catch (NoSuchAlgorithmException e) {
    207                 onException(e);
    208             } catch (CertificateException e) {
    209                 onException(e);
    210             } catch (IOException e) {
    211                 onException(e);
    212             } finally {
    213                 // in case we exit with an exception, we need to reset this
    214                 mDisableOnChange = false;
    215             }
    216         }
    217     }
    218 
    219     @Override
    220     public IWizardPage getPreviousPage() {
    221         return mWizard.getKeystoreSelectionPage();
    222     }
    223 
    224     @Override
    225     public IWizardPage getNextPage() {
    226         if (mWizard.getKeyCreationMode()) {
    227             return mWizard.getKeyCreationPage();
    228         }
    229 
    230         return mWizard.getKeyCheckPage();
    231     }
    232 
    233     /**
    234      * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
    235      */
    236     private void onChange() {
    237         if (mDisableOnChange) {
    238             return;
    239         }
    240 
    241         setErrorMessage(null);
    242         setMessage(null);
    243 
    244         if (mWizard.getKeyCreationMode() == false) {
    245             if (mKeyAliases.getSelectionIndex() == -1) {
    246                 setErrorMessage("Select a key alias.");
    247                 setPageComplete(false);
    248                 return;
    249             }
    250 
    251             if (mKeyPassword.getText().trim().length() == 0) {
    252                 setErrorMessage("Enter key password.");
    253                 setPageComplete(false);
    254                 return;
    255             }
    256         }
    257 
    258         setPageComplete(true);
    259     }
    260 
    261     private void enableWidgets() {
    262         boolean useKey = !mWizard.getKeyCreationMode();
    263         mKeyAliasesLabel.setEnabled(useKey);
    264         mKeyAliases.setEnabled(useKey);
    265         mKeyPassword.setEnabled(useKey);
    266         mKeyPasswordLabel.setEnabled(useKey);
    267     }
    268 }
    269