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