diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export')
6 files changed, 0 insertions, 2166 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java deleted file mode 100644 index 170da6d33..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java +++ /dev/null @@ -1,626 +0,0 @@ -/* - * 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.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.ide.eclipse.adt.internal.utils.FingerprintUtils; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; -import com.android.ide.eclipse.adt.internal.project.ExportHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectHelper; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.BuildToolInfo.PathId; -import com.android.sdklib.internal.build.DebugKeyProvider.IKeyGenOutput; -import com.android.sdklib.internal.build.KeystoreHelper; -import com.android.utils.GrabProcessOutput; -import com.android.utils.GrabProcessOutput.IProcessOutput; -import com.android.utils.GrabProcessOutput.Wait; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IExportWizard; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.PlatformUI; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.lang.reflect.InvocationTargetException; -import java.security.KeyStore; -import java.security.KeyStore.PrivateKeyEntry; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.List; - -/** - * Export wizard to export an apk signed with a release key/certificate. - */ -public final class ExportWizard extends Wizard implements IExportWizard { - - private static final String PROJECT_LOGO_LARGE = "icons/android-64.png"; //$NON-NLS-1$ - - private static final String PAGE_PROJECT_CHECK = "Page_ProjectCheck"; //$NON-NLS-1$ - private static final String PAGE_KEYSTORE_SELECTION = "Page_KeystoreSelection"; //$NON-NLS-1$ - private static final String PAGE_KEY_CREATION = "Page_KeyCreation"; //$NON-NLS-1$ - private static final String PAGE_KEY_SELECTION = "Page_KeySelection"; //$NON-NLS-1$ - private static final String PAGE_KEY_CHECK = "Page_KeyCheck"; //$NON-NLS-1$ - - static final String PROPERTY_KEYSTORE = "keystore"; //$NON-NLS-1$ - static final String PROPERTY_ALIAS = "alias"; //$NON-NLS-1$ - static final String PROPERTY_DESTINATION = "destination"; //$NON-NLS-1$ - - static final int APK_FILE_SOURCE = 0; - static final int APK_FILE_DEST = 1; - static final int APK_COUNT = 2; - - /** - * Base page class for the ExportWizard page. This class add the {@link #onShow()} callback. - */ - static abstract class ExportWizardPage extends WizardPage { - - /** bit mask constant for project data change event */ - protected static final int DATA_PROJECT = 0x001; - /** bit mask constant for keystore data change event */ - protected static final int DATA_KEYSTORE = 0x002; - /** bit mask constant for key data change event */ - protected static final int DATA_KEY = 0x004; - - protected static final VerifyListener sPasswordVerifier = new VerifyListener() { - @Override - public void verifyText(VerifyEvent e) { - // verify the characters are valid for password. - int len = e.text.length(); - - // first limit to 127 characters max - if (len + ((Text)e.getSource()).getText().length() > 127) { - e.doit = false; - return; - } - - // now only take non control characters - for (int i = 0 ; i < len ; i++) { - if (e.text.charAt(i) < 32) { - e.doit = false; - return; - } - } - } - }; - - /** - * Bit mask indicating what changed while the page was hidden. - * @see #DATA_PROJECT - * @see #DATA_KEYSTORE - * @see #DATA_KEY - */ - protected int mProjectDataChanged = 0; - - ExportWizardPage(String name) { - super(name); - } - - abstract void onShow(); - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) { - onShow(); - mProjectDataChanged = 0; - } - } - - final void projectDataChanged(int changeMask) { - mProjectDataChanged |= changeMask; - } - - /** - * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a - * {@link Throwable} object. - */ - protected void onException(Throwable t) { - String message = getExceptionMessage(t); - - setErrorMessage(message); - setPageComplete(false); - } - } - - private ExportWizardPage mPages[] = new ExportWizardPage[5]; - - private IProject mProject; - - private String mKeystore; - private String mKeystorePassword; - private boolean mKeystoreCreationMode; - - private String mKeyAlias; - private String mKeyPassword; - private int mValidity; - private String mDName; - - private PrivateKey mPrivateKey; - private X509Certificate mCertificate; - - private File mDestinationFile; - - private ExportWizardPage mKeystoreSelectionPage; - private ExportWizardPage mKeyCreationPage; - private ExportWizardPage mKeySelectionPage; - private ExportWizardPage mKeyCheckPage; - - private boolean mKeyCreationMode; - - private List<String> mExistingAliases; - - public ExportWizard() { - setHelpAvailable(false); // TODO have help - setWindowTitle("Export Android Application"); - setImageDescriptor(); - } - - @Override - public void addPages() { - addPage(mPages[0] = new ProjectCheckPage(this, PAGE_PROJECT_CHECK)); - addPage(mKeystoreSelectionPage = mPages[1] = new KeystoreSelectionPage(this, - PAGE_KEYSTORE_SELECTION)); - addPage(mKeyCreationPage = mPages[2] = new KeyCreationPage(this, PAGE_KEY_CREATION)); - addPage(mKeySelectionPage = mPages[3] = new KeySelectionPage(this, PAGE_KEY_SELECTION)); - addPage(mKeyCheckPage = mPages[4] = new KeyCheckPage(this, PAGE_KEY_CHECK)); - } - - @Override - public boolean performFinish() { - // save the properties - ProjectHelper.saveStringProperty(mProject, PROPERTY_KEYSTORE, mKeystore); - ProjectHelper.saveStringProperty(mProject, PROPERTY_ALIAS, mKeyAlias); - ProjectHelper.saveStringProperty(mProject, PROPERTY_DESTINATION, - mDestinationFile.getAbsolutePath()); - - // run the export in an UI runnable. - IWorkbench workbench = PlatformUI.getWorkbench(); - final boolean[] result = new boolean[1]; - try { - workbench.getProgressService().busyCursorWhile(new IRunnableWithProgress() { - /** - * Run the export. - * @throws InvocationTargetException - * @throws InterruptedException - */ - @Override - public void run(IProgressMonitor monitor) throws InvocationTargetException, - InterruptedException { - try { - result[0] = doExport(monitor); - } finally { - monitor.done(); - } - } - }); - } catch (InvocationTargetException e) { - return false; - } catch (InterruptedException e) { - return false; - } - - return result[0]; - } - - private boolean doExport(IProgressMonitor monitor) { - try { - // if needed, create the keystore and/or key. - if (mKeystoreCreationMode || mKeyCreationMode) { - final ArrayList<String> output = new ArrayList<String>(); - boolean createdStore = KeystoreHelper.createNewStore( - mKeystore, - null /*storeType*/, - mKeystorePassword, - mKeyAlias, - mKeyPassword, - mDName, - mValidity, - new IKeyGenOutput() { - @Override - public void err(String message) { - output.add(message); - } - @Override - public void out(String message) { - output.add(message); - } - }); - - if (createdStore == false) { - // keystore creation error! - displayError(output.toArray(new String[output.size()])); - return false; - } - - // keystore is created, now load the private key and certificate. - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - FileInputStream fis = new FileInputStream(mKeystore); - keyStore.load(fis, mKeystorePassword.toCharArray()); - fis.close(); - PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry( - mKeyAlias, new KeyStore.PasswordProtection(mKeyPassword.toCharArray())); - - if (entry != null) { - mPrivateKey = entry.getPrivateKey(); - mCertificate = (X509Certificate)entry.getCertificate(); - - AdtPlugin.printToConsole(mProject, - String.format("New keystore %s has been created.", - mDestinationFile.getAbsolutePath()), - "Certificate fingerprints:", - String.format(" MD5 : %s", getCertMd5Fingerprint()), - String.format(" SHA1: %s", getCertSha1Fingerprint())); - - } else { - // this really shouldn't happen since we now let the user choose the key - // from a list read from the store. - displayError("Could not find key"); - return false; - } - } - - // check the private key/certificate again since it may have been created just above. - if (mPrivateKey != null && mCertificate != null) { - // check whether we can run zipalign. - boolean runZipAlign = false; - - ProjectState projectState = Sdk.getProjectState(mProject); - BuildToolInfo buildToolInfo = ExportHelper.getBuildTools(projectState); - - String zipAlignPath = buildToolInfo.getPath(PathId.ZIP_ALIGN); - runZipAlign = zipAlignPath != null && new File(zipAlignPath).isFile(); - - File apkExportFile = mDestinationFile; - if (runZipAlign) { - // create a temp file for the original export. - apkExportFile = File.createTempFile("androidExport_", ".apk"); - } - - // export the signed apk. - ExportHelper.exportReleaseApk(mProject, apkExportFile, - mPrivateKey, mCertificate, monitor); - - // align if we can - if (runZipAlign) { - String message = zipAlign(zipAlignPath, apkExportFile, mDestinationFile); - if (message != null) { - displayError(message); - return false; - } - } else { - AdtPlugin.displayWarning("Export Wizard", - "The zipalign tool was not found in the SDK.\n\n" + - "Please update to the latest SDK and re-export your application\n" + - "or run zipalign manually.\n\n" + - "Aligning applications allows Android to use application resources\n" + - "more efficiently."); - } - - return true; - } - } catch (Throwable t) { - displayError(t); - } - - return false; - } - - @Override - public boolean canFinish() { - // check if we have the apk to resign, the destination location, and either - // a private key/certificate or the creation mode. In creation mode, unless - // all the key/keystore info is valid, the user cannot reach the last page, so there's - // no need to check them again here. - return ((mPrivateKey != null && mCertificate != null) - || mKeystoreCreationMode || mKeyCreationMode) && - mDestinationFile != null; - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, - * org.eclipse.jface.viewers.IStructuredSelection) - */ - @Override - public void init(IWorkbench workbench, IStructuredSelection selection) { - // get the project from the selection - Object selected = selection.getFirstElement(); - - if (selected instanceof IProject) { - mProject = (IProject)selected; - } else if (selected instanceof IAdaptable) { - IResource r = (IResource)((IAdaptable)selected).getAdapter(IResource.class); - if (r != null) { - mProject = r.getProject(); - } - } - } - - ExportWizardPage getKeystoreSelectionPage() { - return mKeystoreSelectionPage; - } - - ExportWizardPage getKeyCreationPage() { - return mKeyCreationPage; - } - - ExportWizardPage getKeySelectionPage() { - return mKeySelectionPage; - } - - ExportWizardPage getKeyCheckPage() { - return mKeyCheckPage; - } - - /** - * Returns an image descriptor for the wizard logo. - */ - private void setImageDescriptor() { - ImageDescriptor desc = AdtPlugin.getImageDescriptor(PROJECT_LOGO_LARGE); - setDefaultPageImageDescriptor(desc); - } - - IProject getProject() { - return mProject; - } - - void setProject(IProject project) { - mProject = project; - - updatePageOnChange(ExportWizardPage.DATA_PROJECT); - } - - void setKeystore(String path) { - mKeystore = path; - mPrivateKey = null; - mCertificate = null; - - updatePageOnChange(ExportWizardPage.DATA_KEYSTORE); - } - - String getKeystore() { - return mKeystore; - } - - void setKeystoreCreationMode(boolean createStore) { - mKeystoreCreationMode = createStore; - updatePageOnChange(ExportWizardPage.DATA_KEYSTORE); - } - - boolean getKeystoreCreationMode() { - return mKeystoreCreationMode; - } - - - void setKeystorePassword(String password) { - mKeystorePassword = password; - mPrivateKey = null; - mCertificate = null; - - updatePageOnChange(ExportWizardPage.DATA_KEYSTORE); - } - - String getKeystorePassword() { - return mKeystorePassword; - } - - void setKeyCreationMode(boolean createKey) { - mKeyCreationMode = createKey; - updatePageOnChange(ExportWizardPage.DATA_KEY); - } - - boolean getKeyCreationMode() { - return mKeyCreationMode; - } - - void setExistingAliases(List<String> aliases) { - mExistingAliases = aliases; - } - - List<String> getExistingAliases() { - return mExistingAliases; - } - - void setKeyAlias(String name) { - mKeyAlias = name; - mPrivateKey = null; - mCertificate = null; - - updatePageOnChange(ExportWizardPage.DATA_KEY); - } - - String getKeyAlias() { - return mKeyAlias; - } - - void setKeyPassword(String password) { - mKeyPassword = password; - mPrivateKey = null; - mCertificate = null; - - updatePageOnChange(ExportWizardPage.DATA_KEY); - } - - String getKeyPassword() { - return mKeyPassword; - } - - void setValidity(int validity) { - mValidity = validity; - updatePageOnChange(ExportWizardPage.DATA_KEY); - } - - int getValidity() { - return mValidity; - } - - void setDName(String dName) { - mDName = dName; - updatePageOnChange(ExportWizardPage.DATA_KEY); - } - - String getDName() { - return mDName; - } - - String getCertSha1Fingerprint() { - return FingerprintUtils.getFingerprint(mCertificate, "SHA1"); - } - - String getCertMd5Fingerprint() { - return FingerprintUtils.getFingerprint(mCertificate, "MD5"); - } - - void setSigningInfo(PrivateKey privateKey, X509Certificate certificate) { - mPrivateKey = privateKey; - mCertificate = certificate; - } - - void setDestination(File destinationFile) { - mDestinationFile = destinationFile; - } - - void resetDestination() { - mDestinationFile = null; - } - - void updatePageOnChange(int changeMask) { - for (ExportWizardPage page : mPages) { - page.projectDataChanged(changeMask); - } - } - - private void displayError(String... messages) { - String message = null; - if (messages.length == 1) { - message = messages[0]; - } else { - StringBuilder sb = new StringBuilder(messages[0]); - for (int i = 1; i < messages.length; i++) { - sb.append('\n'); - sb.append(messages[i]); - } - - message = sb.toString(); - } - - AdtPlugin.displayError("Export Wizard", message); - } - - private void displayError(Throwable t) { - String message = getExceptionMessage(t); - displayError(message); - - AdtPlugin.log(t, "Export Wizard Error"); - } - - /** - * Executes zipalign - * @param zipAlignPath location of the zipalign too - * @param source file to zipalign - * @param destination where to write the resulting file - * @return null if success, the error otherwise - * @throws IOException - */ - private String zipAlign(String zipAlignPath, File source, File destination) throws IOException { - // command line: zipaling -f 4 tmp destination - String[] command = new String[5]; - command[0] = zipAlignPath; - command[1] = "-f"; //$NON-NLS-1$ - command[2] = "4"; //$NON-NLS-1$ - command[3] = source.getAbsolutePath(); - command[4] = destination.getAbsolutePath(); - - Process process = Runtime.getRuntime().exec(command); - final ArrayList<String> output = new ArrayList<String>(); - try { - final IProject project = getProject(); - - int status = GrabProcessOutput.grabProcessOutput( - process, - Wait.WAIT_FOR_READERS, - new IProcessOutput() { - @Override - public void out(@Nullable String line) { - if (line != null) { - AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, - project, line); - } - } - - @Override - public void err(@Nullable String line) { - if (line != null) { - output.add(line); - } - } - }); - - if (status != 0) { - // build a single message from the array list - StringBuilder sb = new StringBuilder("Error while running zipalign:"); - for (String msg : output) { - sb.append('\n'); - sb.append(msg); - } - - return sb.toString(); - } - } catch (InterruptedException e) { - // ? - } - return null; - } - - /** - * Returns the {@link Throwable#getMessage()}. If the {@link Throwable#getMessage()} returns - * <code>null</code>, the method is called again on the cause of the Throwable object. - * <p/>If no Throwable in the chain has a valid message, the canonical name of the first - * exception is returned. - */ - static String getExceptionMessage(Throwable t) { - String message = t.getMessage(); - if (message == null) { - // no error info? get the stack call to display it - // At least that'll give us a better bug report. - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - t.printStackTrace(new PrintStream(baos)); - message = baos.toString(); - } - - return message; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCheckPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCheckPage.java deleted file mode 100644 index c17f43e38..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCheckPage.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * 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.swt.SWT; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -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.FileDialog; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.forms.widgets.FormText; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStore.PrivateKeyEntry; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.UnrecoverableEntryException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Calendar; - -/** - * Final page of the wizard that checks the key and ask for the ouput location. - */ -final class KeyCheckPage extends ExportWizardPage { - - private static final int REQUIRED_YEARS = 25; - - private static final String VALIDITY_WARNING = - "<p>Make sure the certificate is valid for the planned lifetime of the product.</p>" - + "<p>If the certificate expires, you will be forced to sign your application with " - + "a different one.</p>" - + "<p>Applications cannot be upgraded if their certificate changes from " - + "one version to another, forcing a full uninstall/install, which will make " - + "the user lose his/her data.</p>" - + "<p>Google Play(Android Market) currently requires certificates to be valid " - + "until 2033.</p>"; - - private final ExportWizard mWizard; - private PrivateKey mPrivateKey; - private X509Certificate mCertificate; - private Text mDestination; - private boolean mFatalSigningError; - private FormText mDetailText; - private ScrolledComposite mScrolledComposite; - - private String mKeyDetails; - private String mDestinationDetails; - - protected KeyCheckPage(ExportWizard wizard, String pageName) { - super(pageName); - mWizard = wizard; - - setTitle("Destination and key/certificate checks"); - setDescription(""); // TODO - } - - @Override - public void createControl(Composite parent) { - setErrorMessage(null); - setMessage(null); - - // build the ui. - Composite composite = new Composite(parent, SWT.NULL); - composite.setLayoutData(new GridData(GridData.FILL_BOTH)); - GridLayout gl = new GridLayout(3, false); - gl.verticalSpacing *= 3; - composite.setLayout(gl); - - GridData gd; - - new Label(composite, SWT.NONE).setText("Destination APK file:"); - mDestination = new Text(composite, SWT.BORDER); - mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - mDestination.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - onDestinationChange(false /*forceDetailUpdate*/); - } - }); - final Button browseButton = new Button(composite, SWT.PUSH); - browseButton.setText("Browse..."); - browseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.SAVE); - - fileDialog.setText("Destination file name"); - // get a default apk name based on the project - String filename = ProjectHelper.getApkFilename(mWizard.getProject(), - null /*config*/); - fileDialog.setFileName(filename); - - String saveLocation = fileDialog.open(); - if (saveLocation != null) { - mDestination.setText(saveLocation); - } - } - }); - - mScrolledComposite = new ScrolledComposite(composite, SWT.V_SCROLL); - mScrolledComposite.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); - gd.horizontalSpan = 3; - mScrolledComposite.setExpandHorizontal(true); - mScrolledComposite.setExpandVertical(true); - - mDetailText = new FormText(mScrolledComposite, SWT.NONE); - mScrolledComposite.setContent(mDetailText); - - mScrolledComposite.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - updateScrolling(); - } - }); - - setControl(composite); - } - - @Override - void onShow() { - // fill the texts with information loaded from the project. - if ((mProjectDataChanged & DATA_PROJECT) != 0) { - // reset the destination from the content of the project - IProject project = mWizard.getProject(); - - String destination = ProjectHelper.loadStringProperty(project, - ExportWizard.PROPERTY_DESTINATION); - if (destination != null) { - mDestination.setText(destination); - } - } - - // if anything change we basically reload the data. - if (mProjectDataChanged != 0) { - mFatalSigningError = false; - - // reset the wizard with no key/cert to make it not finishable, unless a valid - // key/cert is found. - mWizard.setSigningInfo(null, null); - mPrivateKey = null; - mCertificate = null; - mKeyDetails = null; - - if (mWizard.getKeystoreCreationMode() || mWizard.getKeyCreationMode()) { - int validity = mWizard.getValidity(); - StringBuilder sb = new StringBuilder( - String.format("<p>Certificate expires in %d years.</p>", - validity)); - - if (validity < REQUIRED_YEARS) { - sb.append(VALIDITY_WARNING); - } - - mKeyDetails = sb.toString(); - } else { - try { - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - FileInputStream fis = new FileInputStream(mWizard.getKeystore()); - keyStore.load(fis, mWizard.getKeystorePassword().toCharArray()); - fis.close(); - PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry( - mWizard.getKeyAlias(), - new KeyStore.PasswordProtection( - mWizard.getKeyPassword().toCharArray())); - - if (entry != null) { - mPrivateKey = entry.getPrivateKey(); - mCertificate = (X509Certificate)entry.getCertificate(); - } else { - setErrorMessage("Unable to find key."); - - setPageComplete(false); - } - } catch (FileNotFoundException e) { - // this was checked at the first previous step and will not happen here, unless - // the file was removed during the export wizard execution. - onException(e); - } catch (KeyStoreException e) { - onException(e); - } catch (NoSuchAlgorithmException e) { - onException(e); - } catch (UnrecoverableEntryException e) { - onException(e); - } catch (CertificateException e) { - onException(e); - } catch (IOException e) { - onException(e); - } - - if (mPrivateKey != null && mCertificate != null) { - Calendar expirationCalendar = Calendar.getInstance(); - expirationCalendar.setTime(mCertificate.getNotAfter()); - Calendar today = Calendar.getInstance(); - - if (expirationCalendar.before(today)) { - mKeyDetails = String.format( - "<p>Certificate expired on %s</p>", - mCertificate.getNotAfter().toString()); - - // fatal error = nothing can make the page complete. - mFatalSigningError = true; - - setErrorMessage("Certificate is expired."); - setPageComplete(false); - } else { - // valid, key/cert: put it in the wizard so that it can be finished - mWizard.setSigningInfo(mPrivateKey, mCertificate); - - StringBuilder sb = new StringBuilder(String.format( - "<p>Certificate expires on %s.</p>", - mCertificate.getNotAfter().toString())); - - int expirationYear = expirationCalendar.get(Calendar.YEAR); - int thisYear = today.get(Calendar.YEAR); - - if (thisYear + REQUIRED_YEARS < expirationYear) { - // do nothing - } else { - if (expirationYear == thisYear) { - sb.append("<p>The certificate expires this year.</p>"); - } else { - int count = expirationYear-thisYear; - sb.append(String.format( - "<p>The Certificate expires in %1$s %2$s.</p>", - count, count == 1 ? "year" : "years")); - } - sb.append(VALIDITY_WARNING); - } - - // show certificate fingerprints - String sha1 = mWizard.getCertSha1Fingerprint(); - String md5 = mWizard.getCertMd5Fingerprint(); - - sb.append("<p></p>" /*blank line*/); - sb.append("<p>Certificate fingerprints:</p>"); - sb.append(String.format("<li>MD5 : %s</li>", md5)); - sb.append(String.format("<li>SHA1: %s</li>", sha1)); - sb.append("<p></p>" /*blank line*/); - - mKeyDetails = sb.toString(); - } - } else { - // fatal error = nothing can make the page complete. - mFatalSigningError = true; - } - } - } - - onDestinationChange(true /*forceDetailUpdate*/); - } - - /** - * Callback for destination field edition - * @param forceDetailUpdate if true, the detail {@link FormText} is updated even if a fatal - * error has happened in the signing. - */ - private void onDestinationChange(boolean forceDetailUpdate) { - if (mFatalSigningError == false) { - // reset messages for now. - setErrorMessage(null); - setMessage(null); - - String path = mDestination.getText().trim(); - - if (path.length() == 0) { - setErrorMessage("Enter destination for the APK file."); - // reset canFinish in the wizard. - mWizard.resetDestination(); - setPageComplete(false); - return; - } - - File file = new File(path); - if (file.isDirectory()) { - setErrorMessage("Destination is a directory."); - // reset canFinish in the wizard. - mWizard.resetDestination(); - setPageComplete(false); - return; - } - - File parentFolder = file.getParentFile(); - if (parentFolder == null || parentFolder.isDirectory() == false) { - setErrorMessage("Not a valid directory."); - // reset canFinish in the wizard. - mWizard.resetDestination(); - setPageComplete(false); - return; - } - - if (file.isFile()) { - mDestinationDetails = "<li>WARNING: destination file already exists</li>"; - setMessage("Destination file already exists.", WARNING); - } - - // no error, set the destination in the wizard. - mWizard.setDestination(file); - setPageComplete(true); - - updateDetailText(); - } else if (forceDetailUpdate) { - updateDetailText(); - } - } - - /** - * Updates the scrollbar to match the content of the {@link FormText} or the new size - * of the {@link ScrolledComposite}. - */ - private void updateScrolling() { - if (mDetailText != null) { - Rectangle r = mScrolledComposite.getClientArea(); - mScrolledComposite.setMinSize(mDetailText.computeSize(r.width, SWT.DEFAULT)); - mScrolledComposite.layout(); - } - } - - private void updateDetailText() { - StringBuilder sb = new StringBuilder("<form>"); - if (mKeyDetails != null) { - sb.append(mKeyDetails); - } - - if (mDestinationDetails != null && mFatalSigningError == false) { - sb.append(mDestinationDetails); - } - - sb.append("</form>"); - - mDetailText.setText(sb.toString(), true /* parseTags */, - true /* expandURLs */); - - mDetailText.getParent().layout(); - - updateScrolling(); - } - - @Override - protected void onException(Throwable t) { - super.onException(t); - - mKeyDetails = String.format("ERROR: %1$s", ExportWizard.getExceptionMessage(t)); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCreationPage.java deleted file mode 100644 index aea94ad8d..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCreationPage.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeySelectionPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeySelectionPage.java deleted file mode 100644 index 604a208e6..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeySelectionPage.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.util.ArrayList; -import java.util.Enumeration; - -/** - * Key Selection Page. This is used when an existing keystore is used. - */ -final class KeySelectionPage extends ExportWizardPage { - - private final ExportWizard mWizard; - private Label mKeyAliasesLabel; - private Combo mKeyAliases; - private Label mKeyPasswordLabel; - private Text mKeyPassword; - private boolean mDisableOnChange = false; - private Button mUseExistingKey; - private Button mCreateKey; - - protected KeySelectionPage(ExportWizard wizard, String pageName) { - super(pageName); - mWizard = wizard; - - setTitle("Key alias selection"); - 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(3, false); - composite.setLayout(gl); - - GridData gd; - - mUseExistingKey = new Button(composite, SWT.RADIO); - mUseExistingKey.setText("Use existing key"); - mUseExistingKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - mUseExistingKey.setSelection(true); - - new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData()); - gd.heightHint = 0; - gd.widthHint = 50; - mKeyAliasesLabel = new Label(composite, SWT.NONE); - mKeyAliasesLabel.setText("Alias:"); - mKeyAliases = new Combo(composite, SWT.READ_ONLY); - mKeyAliases.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData()); - gd.heightHint = 0; - gd.widthHint = 50; - mKeyPasswordLabel = new Label(composite, SWT.NONE); - mKeyPasswordLabel.setText("Password:"); - mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD); - mKeyPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mCreateKey = new Button(composite, SWT.RADIO); - mCreateKey.setText("Create new key"); - mCreateKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - - // Show description the first time - setErrorMessage(null); - setMessage(null); - setControl(composite); - - mUseExistingKey.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - mWizard.setKeyCreationMode(!mUseExistingKey.getSelection()); - enableWidgets(); - onChange(); - } - }); - - mKeyAliases.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - mWizard.setKeyAlias(mKeyAliases.getItem(mKeyAliases.getSelectionIndex())); - onChange(); - } - }); - - mKeyPassword.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - mWizard.setKeyPassword(mKeyPassword.getText()); - onChange(); - } - }); - } - - @Override - void onShow() { - // fill the texts with information loaded from the project. - if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) { - // disable onChange for now. we'll call it once at the end. - mDisableOnChange = true; - - // reset the alias from the content of the project - try { - // reset to using a key - mWizard.setKeyCreationMode(false); - mUseExistingKey.setSelection(true); - mCreateKey.setSelection(false); - enableWidgets(); - - // remove the content of the alias combo always and first, in case the - // keystore password is wrong - mKeyAliases.removeAll(); - - // get the alias list (also used as a keystore password test) - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - FileInputStream fis = new FileInputStream(mWizard.getKeystore()); - keyStore.load(fis, mWizard.getKeystorePassword().toCharArray()); - fis.close(); - - Enumeration<String> aliases = keyStore.aliases(); - - // get the alias from the project previous export, and look for a match as - // we add the aliases to the combo. - IProject project = mWizard.getProject(); - - String keyAlias = ProjectHelper.loadStringProperty(project, - ExportWizard.PROPERTY_ALIAS); - - ArrayList<String> aliasList = new ArrayList<String>(); - - int selection = -1; - int count = 0; - while (aliases.hasMoreElements()) { - String alias = aliases.nextElement(); - mKeyAliases.add(alias); - aliasList.add(alias); - if (selection == -1 && alias.equalsIgnoreCase(keyAlias)) { - selection = count; - } - count++; - } - - mWizard.setExistingAliases(aliasList); - - if (selection != -1) { - mKeyAliases.select(selection); - - // since a match was found and is selected, we need to give it to - // the wizard as well - mWizard.setKeyAlias(keyAlias); - } else { - mKeyAliases.clearSelection(); - } - - // reset the password - mKeyPassword.setText(""); //$NON-NLS-1$ - - // enable onChange, and call it to display errors and enable/disable pageCompleted. - mDisableOnChange = false; - onChange(); - } catch (KeyStoreException e) { - onException(e); - } catch (FileNotFoundException e) { - onException(e); - } catch (NoSuchAlgorithmException e) { - onException(e); - } catch (CertificateException e) { - onException(e); - } catch (IOException e) { - onException(e); - } finally { - // in case we exit with an exception, we need to reset this - mDisableOnChange = false; - } - } - } - - @Override - public IWizardPage getPreviousPage() { - return mWizard.getKeystoreSelectionPage(); - } - - @Override - public IWizardPage getNextPage() { - if (mWizard.getKeyCreationMode()) { - return mWizard.getKeyCreationPage(); - } - - 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 (mWizard.getKeyCreationMode() == false) { - if (mKeyAliases.getSelectionIndex() == -1) { - setErrorMessage("Select a key alias."); - setPageComplete(false); - return; - } - - if (mKeyPassword.getText().trim().length() == 0) { - setErrorMessage("Enter key password."); - setPageComplete(false); - return; - } - } - - setPageComplete(true); - } - - private void enableWidgets() { - boolean useKey = !mWizard.getKeyCreationMode(); - mKeyAliasesLabel.setEnabled(useKey); - mKeyAliases.setEnabled(useKey); - mKeyPassword.setEnabled(useKey); - mKeyPasswordLabel.setEnabled(useKey); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeystoreSelectionPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeystoreSelectionPage.java deleted file mode 100644 index eabee15a2..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeystoreSelectionPage.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -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.FileDialog; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -import java.io.File; - -/** - * Keystore selection page. This page allows to choose to create a new keystore or use an - * existing one. - */ -final class KeystoreSelectionPage extends ExportWizardPage { - - private final ExportWizard mWizard; - private Button mUseExistingKeystore; - private Button mCreateKeystore; - private Text mKeystore; - private Text mKeystorePassword; - private Label mConfirmLabel; - private Text mKeystorePassword2; - private boolean mDisableOnChange = false; - - protected KeystoreSelectionPage(ExportWizard wizard, String pageName) { - super(pageName); - mWizard = wizard; - - setTitle("Keystore selection"); - 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(3, false); - composite.setLayout(gl); - - GridData gd; - - mUseExistingKeystore = new Button(composite, SWT.RADIO); - mUseExistingKeystore.setText("Use existing keystore"); - mUseExistingKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - mUseExistingKeystore.setSelection(true); - - mCreateKeystore = new Button(composite, SWT.RADIO); - mCreateKeystore.setText("Create new keystore"); - mCreateKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - - new Label(composite, SWT.NONE).setText("Location:"); - mKeystore = new Text(composite, SWT.BORDER); - mKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - final Button browseButton = new Button(composite, SWT.PUSH); - browseButton.setText("Browse..."); - browseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - FileDialog fileDialog; - if (mUseExistingKeystore.getSelection()) { - fileDialog = new FileDialog(browseButton.getShell(),SWT.OPEN); - fileDialog.setText("Load Keystore"); - } else { - fileDialog = new FileDialog(browseButton.getShell(),SWT.SAVE); - fileDialog.setText("Select Keystore Name"); - } - - String fileName = fileDialog.open(); - if (fileName != null) { - mKeystore.setText(fileName); - } - } - }); - - new Label(composite, SWT.NONE).setText("Password:"); - mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD); - mKeystorePassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - mKeystorePassword.addVerifyListener(sPasswordVerifier); - new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData()); - gd.heightHint = gd.widthHint = 0; - - mConfirmLabel = new Label(composite, SWT.NONE); - mConfirmLabel.setText("Confirm:"); - mKeystorePassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD); - mKeystorePassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - mKeystorePassword2.addVerifyListener(sPasswordVerifier); - new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData()); - gd.heightHint = gd.widthHint = 0; - mKeystorePassword2.setEnabled(false); - - // Show description the first time - setErrorMessage(null); - setMessage(null); - setControl(composite); - - mUseExistingKeystore.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - boolean createStore = !mUseExistingKeystore.getSelection(); - mKeystorePassword2.setEnabled(createStore); - mConfirmLabel.setEnabled(createStore); - mWizard.setKeystoreCreationMode(createStore); - onChange(); - } - }); - - mKeystore.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - mWizard.setKeystore(mKeystore.getText().trim()); - onChange(); - } - }); - - mKeystorePassword.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - mWizard.setKeystorePassword(mKeystorePassword.getText()); - onChange(); - } - }); - - mKeystorePassword2.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - onChange(); - } - }); - } - - @Override - public IWizardPage getNextPage() { - if (mUseExistingKeystore.getSelection()) { - return mWizard.getKeySelectionPage(); - } - - return mWizard.getKeyCreationPage(); - } - - @Override - void onShow() { - // fill the texts with information loaded from the project. - if ((mProjectDataChanged & DATA_PROJECT) != 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 keystore = ProjectHelper.loadStringProperty(project, - ExportWizard.PROPERTY_KEYSTORE); - if (keystore != null) { - mKeystore.setText(keystore); - } - - // reset the passwords - mKeystorePassword.setText(""); //$NON-NLS-1$ - mKeystorePassword2.setText(""); //$NON-NLS-1$ - - // enable onChange, and call it to display errors and enable/disable pageCompleted. - mDisableOnChange = false; - onChange(); - } - } - - /** - * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}. - */ - private void onChange() { - if (mDisableOnChange) { - return; - } - - setErrorMessage(null); - setMessage(null); - - boolean createStore = !mUseExistingKeystore.getSelection(); - - // checks the keystore path is non null. - String keystore = mKeystore.getText().trim(); - if (keystore.length() == 0) { - setErrorMessage("Enter path to keystore."); - setPageComplete(false); - return; - } else { - File f = new File(keystore); - if (f.exists() == false) { - if (createStore == false) { - setErrorMessage("Keystore does not exist."); - setPageComplete(false); - return; - } - } else if (f.isDirectory()) { - setErrorMessage("Keystore path is a directory."); - setPageComplete(false); - return; - } else if (f.isFile()) { - if (createStore) { - setErrorMessage("File already exists."); - setPageComplete(false); - return; - } - } - } - - String value = mKeystorePassword.getText(); - if (value.length() == 0) { - setErrorMessage("Enter keystore password."); - setPageComplete(false); - return; - } else if (createStore && value.length() < 6) { - setErrorMessage("Keystore password is too short - must be at least 6 characters."); - setPageComplete(false); - return; - } - - if (createStore) { - if (mKeystorePassword2.getText().length() == 0) { - setErrorMessage("Confirm keystore password."); - setPageComplete(false); - return; - } - - if (mKeystorePassword.getText().equals(mKeystorePassword2.getText()) == false) { - setErrorMessage("Keystore passwords do not match."); - setPageComplete(false); - return; - } - } - - setPageComplete(true); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java deleted file mode 100644 index b8a7043da..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * 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.common.xml.ManifestData; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.NonLibraryProjectOnlyFilter; -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.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -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.Label; -import org.eclipse.swt.widgets.Text; - -/** - * First Export Wizard Page. Display warning/errors. - */ -final class ProjectCheckPage extends ExportWizardPage { - private final static String IMG_ERROR = "error.png"; //$NON-NLS-1$ - private final static String IMG_WARNING = "warning.png"; //$NON-NLS-1$ - - private final ExportWizard mWizard; - private Image mError; - private Image mWarning; - private boolean mHasMessage = false; - private Composite mTopComposite; - private Composite mErrorComposite; - private Text mProjectText; - private ProjectChooserHelper mProjectChooserHelper; - private boolean mFirstOnShow = true; - - protected ProjectCheckPage(ExportWizard wizard, String pageName) { - super(pageName); - mWizard = wizard; - - setTitle("Project Checks"); - setDescription("Performs a set of checks to make sure the application can be exported."); - } - - @Override - public void createControl(Composite parent) { - mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(), - new NonLibraryProjectOnlyFilter()); - - GridLayout gl = null; - GridData gd = null; - - mTopComposite = new Composite(parent, SWT.NONE); - mTopComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); - mTopComposite.setLayout(new GridLayout(1, false)); - - // composite for the project selection. - Composite projectComposite = new Composite(mTopComposite, SWT.NONE); - projectComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - projectComposite.setLayout(gl = new GridLayout(3, false)); - gl.marginHeight = gl.marginWidth = 0; - - Label label = new Label(projectComposite, SWT.NONE); - label.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - label.setText("Select the project to export:"); - - new Label(projectComposite, SWT.NONE).setText("Project:"); - mProjectText = new Text(projectComposite, SWT.BORDER); - mProjectText.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - mProjectText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - handleProjectNameChange(); - } - }); - - Button browseButton = new Button(projectComposite, SWT.PUSH); - browseButton.setText("Browse..."); - browseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - IJavaProject javaProject = mProjectChooserHelper.chooseJavaProject( - mProjectText.getText().trim(), - "Please select a project to export"); - - if (javaProject != null) { - IProject project = javaProject.getProject(); - - // set the new name in the text field. The modify listener will take - // care of updating the status and the ExportWizard object. - mProjectText.setText(project.getName()); - } - } - }); - - setControl(mTopComposite); - } - - @Override - void onShow() { - if (mFirstOnShow) { - // get the project and init the ui - IProject project = mWizard.getProject(); - if (project != null) { - mProjectText.setText(project.getName()); - } - - mFirstOnShow = false; - } - } - - private void buildErrorUi(IProject project) { - // Show description the first time - setErrorMessage(null); - setMessage(null); - setPageComplete(true); - mHasMessage = false; - - // composite parent for the warning/error - GridLayout gl = null; - mErrorComposite = new Composite(mTopComposite, SWT.NONE); - mErrorComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - gl = new GridLayout(2, false); - gl.marginHeight = gl.marginWidth = 0; - gl.verticalSpacing *= 3; // more spacing than normal. - mErrorComposite.setLayout(gl); - - if (project == null) { - setErrorMessage("Select project to export."); - mHasMessage = true; - } else { - try { - if (project.hasNature(AdtConstants.NATURE_DEFAULT) == false) { - addError(mErrorComposite, "Project is not an Android project."); - } else { - // check for errors - if (ProjectHelper.hasError(project, true)) { - addError(mErrorComposite, "Project has compilation error(s)"); - } - - // check the project output - IFolder outputIFolder = BaseProjectHelper.getJavaOutputFolder(project); - if (outputIFolder == null) { - addError(mErrorComposite, - "Unable to get the output folder of the project!"); - } - - // project is an android project, we check the debuggable attribute. - ManifestData manifestData = AndroidManifestHelper.parseForData(project); - Boolean debuggable = null; - if (manifestData != null) { - debuggable = manifestData.getDebuggable(); - } - - if (debuggable != null && debuggable == Boolean.TRUE) { - addWarning(mErrorComposite, - "The manifest 'debuggable' attribute is set to true.\n" + - "You should set it to false for applications that you release to the public.\n\n" + - "Applications with debuggable=true are compiled in debug mode always."); - } - - // check for mapview stuff - } - } catch (CoreException e) { - // unable to access nature - addError(mErrorComposite, "Unable to get project nature"); - } - } - - if (mHasMessage == false) { - Label label = new Label(mErrorComposite, SWT.NONE); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - label.setLayoutData(gd); - label.setText("No errors found. Click Next."); - } - - mTopComposite.layout(); - } - - /** - * Adds an error label to a {@link Composite} object. - * @param parent the Composite parent. - * @param message the error message. - */ - private void addError(Composite parent, String message) { - if (mError == null) { - mError = IconFactory.getInstance().getIcon(IMG_ERROR); - } - - new Label(parent, SWT.NONE).setImage(mError); - Label label = new Label(parent, SWT.NONE); - label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - label.setText(message); - - setErrorMessage("Application cannot be exported due to the error(s) below."); - setPageComplete(false); - mHasMessage = true; - } - - /** - * Adds a warning label to a {@link Composite} object. - * @param parent the Composite parent. - * @param message the warning message. - */ - private void addWarning(Composite parent, String message) { - if (mWarning == null) { - mWarning = IconFactory.getInstance().getIcon(IMG_WARNING); - } - - new Label(parent, SWT.NONE).setImage(mWarning); - Label label = new Label(parent, SWT.NONE); - label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - label.setText(message); - - mHasMessage = true; - } - - /** - * Checks the parameters for correctness, and update the error message and buttons. - */ - private void handleProjectNameChange() { - setPageComplete(false); - - if (mErrorComposite != null) { - mErrorComposite.dispose(); - mErrorComposite = null; - } - - // update the wizard with the new project - mWizard.setProject(null); - - //test the project name first! - String text = mProjectText.getText().trim(); - if (text.length() == 0) { - setErrorMessage("Select project to export."); - } else if (text.matches("[a-zA-Z0-9_ \\.-]+") == false) { - setErrorMessage("Project name contains unsupported characters!"); - } else { - IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null); - IProject found = null; - for (IJavaProject javaProject : projects) { - if (javaProject.getProject().getName().equals(text)) { - found = javaProject.getProject(); - break; - } - - } - - if (found != null) { - setErrorMessage(null); - - // update the wizard with the new project - mWizard.setProject(found); - - // now rebuild the error ui. - buildErrorUi(found); - } else { - setErrorMessage(String.format("There is no android project named '%1$s'", - text)); - } - } - } -} |