blob: aea94ad8dddf2a197c153fad90cd7eba6770dd70 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
*
* 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.
*/
package com.android.ide.eclipse.adt.internal.wizards.export;
import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
import com.android.ide.eclipse.adt.internal.wizards.export.ExportWizard.ExportWizardPage;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import java.util.List;
/**
* Key creation page.
*/
final class KeyCreationPage extends ExportWizardPage {
private final ExportWizard mWizard;
private Text mAlias;
private Text mKeyPassword;
private Text mKeyPassword2;
private Text mCnField;
private boolean mDisableOnChange = false;
private Text mOuField;
private Text mOField;
private Text mLField;
private Text mStField;
private Text mCField;
private String mDName;
private int mValidity = 0;
private List<String> mExistingAliases;
protected KeyCreationPage(ExportWizard wizard, String pageName) {
super(pageName);
mWizard = wizard;
setTitle("Key Creation");
setDescription(""); // TODO?
}
@Override
public void createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NULL);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout gl = new GridLayout(2, false);
composite.setLayout(gl);
GridData gd;
new Label(composite, SWT.NONE).setText("Alias:");
mAlias = new Text(composite, SWT.BORDER);
mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
new Label(composite, SWT.NONE).setText("Password:");
mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
mKeyPassword.addVerifyListener(sPasswordVerifier);
new Label(composite, SWT.NONE).setText("Confirm:");
mKeyPassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
mKeyPassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
mKeyPassword2.addVerifyListener(sPasswordVerifier);
new Label(composite, SWT.NONE).setText("Validity (years):");
final Text validityText = new Text(composite, SWT.BORDER);
validityText.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
validityText.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent e) {
// check for digit only.
for (int i = 0 ; i < e.text.length(); i++) {
char letter = e.text.charAt(i);
if (letter < '0' || letter > '9') {
e.doit = false;
return;
}
}
}
});
new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(
gd = new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalSpan = 2;
new Label(composite, SWT.NONE).setText("First and Last Name:");
mCnField = new Text(composite, SWT.BORDER);
mCnField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
new Label(composite, SWT.NONE).setText("Organizational Unit:");
mOuField = new Text(composite, SWT.BORDER);
mOuField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
new Label(composite, SWT.NONE).setText("Organization:");
mOField = new Text(composite, SWT.BORDER);
mOField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
new Label(composite, SWT.NONE).setText("City or Locality:");
mLField = new Text(composite, SWT.BORDER);
mLField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
new Label(composite, SWT.NONE).setText("State or Province:");
mStField = new Text(composite, SWT.BORDER);
mStField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
new Label(composite, SWT.NONE).setText("Country Code (XX):");
mCField = new Text(composite, SWT.BORDER);
mCField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
// Show description the first time
setErrorMessage(null);
setMessage(null);
setControl(composite);
mAlias.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
mWizard.setKeyAlias(mAlias.getText().trim());
onChange();
}
});
mKeyPassword.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
mWizard.setKeyPassword(mKeyPassword.getText());
onChange();
}
});
mKeyPassword2.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
onChange();
}
});
validityText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
try {
mValidity = Integer.parseInt(validityText.getText());
} catch (NumberFormatException e2) {
// this should only happen if the text field is empty due to the verifyListener.
mValidity = 0;
}
mWizard.setValidity(mValidity);
onChange();
}
});
ModifyListener dNameListener = new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
onDNameChange();
}
};
mCnField.addModifyListener(dNameListener);
mOuField.addModifyListener(dNameListener);
mOField.addModifyListener(dNameListener);
mLField.addModifyListener(dNameListener);
mStField.addModifyListener(dNameListener);
mCField.addModifyListener(dNameListener);
}
@Override
void onShow() {
// fill the texts with information loaded from the project.
if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
// reset the keystore/alias from the content of the project
IProject project = mWizard.getProject();
// disable onChange for now. we'll call it once at the end.
mDisableOnChange = true;
String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
if (alias != null) {
mAlias.setText(alias);
}
// get the existing list of keys if applicable
if (mWizard.getKeyCreationMode()) {
mExistingAliases = mWizard.getExistingAliases();
} else {
mExistingAliases = null;
}
// reset the passwords
mKeyPassword.setText(""); //$NON-NLS-1$
mKeyPassword2.setText(""); //$NON-NLS-1$
// enable onChange, and call it to display errors and enable/disable pageCompleted.
mDisableOnChange = false;
onChange();
}
}
@Override
public IWizardPage getPreviousPage() {
if (mWizard.getKeyCreationMode()) { // this means we create a key from an existing store
return mWizard.getKeySelectionPage();
}
return mWizard.getKeystoreSelectionPage();
}
@Override
public IWizardPage getNextPage() {
return mWizard.getKeyCheckPage();
}
/**
* Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
*/
private void onChange() {
if (mDisableOnChange) {
return;
}
setErrorMessage(null);
setMessage(null);
if (mAlias.getText().trim().length() == 0) {
setErrorMessage("Enter key alias.");
setPageComplete(false);
return;
} else if (mExistingAliases != null) {
// we cannot use indexOf, because we need to do a case-insensitive check
String keyAlias = mAlias.getText().trim();
for (String alias : mExistingAliases) {
if (alias.equalsIgnoreCase(keyAlias)) {
setErrorMessage("Key alias already exists in keystore.");
setPageComplete(false);
return;
}
}
}
String value = mKeyPassword.getText();
if (value.length() == 0) {
setErrorMessage("Enter key password.");
setPageComplete(false);
return;
} else if (value.length() < 6) {
setErrorMessage("Key password is too short - must be at least 6 characters.");
setPageComplete(false);
return;
}
if (value.equals(mKeyPassword2.getText()) == false) {
setErrorMessage("Key passwords don't match.");
setPageComplete(false);
return;
}
if (mValidity == 0) {
setErrorMessage("Key certificate validity is required.");
setPageComplete(false);
return;
} else if (mValidity < 25) {
setMessage("A 25 year certificate validity is recommended.", WARNING);
} else if (mValidity > 1000) {
setErrorMessage("Key certificate validity must be between 1 and 1000 years.");
setPageComplete(false);
return;
}
if (mDName == null || mDName.length() == 0) {
setErrorMessage("At least one Certificate issuer field is required to be non-empty.");
setPageComplete(false);
return;
}
setPageComplete(true);
}
/**
* Handles changes in the DName fields.
*/
private void onDNameChange() {
StringBuilder sb = new StringBuilder();
buildDName("CN", mCnField, sb);
buildDName("OU", mOuField, sb);
buildDName("O", mOField, sb);
buildDName("L", mLField, sb);
buildDName("ST", mStField, sb);
buildDName("C", mCField, sb);
mDName = sb.toString();
mWizard.setDName(mDName);
onChange();
}
/**
* Builds the distinguished name string with the provided {@link StringBuilder}.
* @param prefix the prefix of the entry.
* @param textField The {@link Text} field containing the entry value.
* @param sb the string builder containing the dname.
*/
private void buildDName(String prefix, Text textField, StringBuilder sb) {
if (textField != null) {
String value = textField.getText().trim();
if (value.length() > 0) {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(prefix);
sb.append('=');
sb.append(value);
}
}
}
}