diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCheckPage.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/KeyCheckPage.java | 378 |
1 files changed, 0 insertions, 378 deletions
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)); - } -} |