FileDocCategorySizeDatePackage
ExportWizard.javaAPI DocAndroid 1.5 API20115Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.adt.project.export

ExportWizard

public final class ExportWizard extends org.eclipse.jface.wizard.Wizard implements org.eclipse.ui.IExportWizard
Export wizard to export an apk signed with a release key/certificate.

Fields Summary
private static final String
PROJECT_LOGO_LARGE
private static final String
PAGE_PROJECT_CHECK
private static final String
PAGE_KEYSTORE_SELECTION
private static final String
PAGE_KEY_CREATION
private static final String
PAGE_KEY_SELECTION
private static final String
PAGE_KEY_CHECK
static final String
PROPERTY_KEYSTORE
static final String
PROPERTY_ALIAS
static final String
PROPERTY_DESTINATION
static final String
PROPERTY_FILENAME
static final int
APK_FILE_SOURCE
static final int
APK_FILE_DEST
static final int
APK_COUNT
private ExportWizardPage[]
mPages
private org.eclipse.core.resources.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
mDestinationParentFolder
private ExportWizardPage
mKeystoreSelectionPage
private ExportWizardPage
mKeyCreationPage
private ExportWizardPage
mKeySelectionPage
private ExportWizardPage
mKeyCheckPage
private boolean
mKeyCreationMode
private List
mExistingAliases
private Map
mApkMap
Constructors Summary
public ExportWizard()


      
        setHelpAvailable(false); // TODO have help
        setWindowTitle("Export Android Application");
        setImageDescriptor();
    
Methods Summary
public voidaddPages()

        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));
    
public booleancanFinish()

        // 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 mApkMap != null && mApkMap.size() > 0 &&
                ((mPrivateKey != null && mCertificate != null)
                        || mKeystoreCreationMode || mKeyCreationMode) &&
                mDestinationParentFolder != null;
    
private voiddisplayError(java.lang.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 voiddisplayError(java.lang.Exception e)

        String message = getExceptionMessage(e);
        displayError(message);
        
        AdtPlugin.log(e, "Export Wizard Error");
    
private booleandoExport(org.eclipse.core.runtime.IProgressMonitor monitor)

        try {
            // first we make sure the project is built
            mProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);

            // 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() {
                            public void err(String message) {
                                output.add(message);
                            }
                            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();
                } 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) {
                // get the output folder of the project to export.
                // this is where we'll find the built apks to resign and export.
                IFolder outputIFolder = BaseProjectHelper.getOutputFolder(mProject);
                if (outputIFolder == null) {
                    return false;
                }
                String outputOsPath =  outputIFolder.getLocation().toOSString();
                
                // now generate the packages.
                Set<Entry<String, String[]>> set = mApkMap.entrySet();
                for (Entry<String, String[]> entry : set) {
                    String[] defaultApk = entry.getValue();
                    String srcFilename = defaultApk[APK_FILE_SOURCE];
                    String destFilename = defaultApk[APK_FILE_DEST];

                    FileOutputStream fos = new FileOutputStream(
                            new File(mDestinationParentFolder, destFilename));
                    SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
                    
                    // get the input file.
                    FileInputStream fis = new FileInputStream(new File(outputOsPath, srcFilename));
                    
                    // add the content of the source file to the output file, and sign it at
                    // the same time.
                    try {
                        builder.writeZip(fis, null /* filter */);
                        // close the builder: write the final signature files, and close the archive.
                        builder.close();
                    } finally {
                        try {
                            fis.close();
                        } finally {
                            fos.close();
                        }
                    }
                }
                return true;
            }
        } catch (FileNotFoundException e) {
            displayError(e);
        } catch (NoSuchAlgorithmException e) {
            displayError(e);
        } catch (IOException e) {
            displayError(e);
        } catch (GeneralSecurityException e) {
            displayError(e);
        } catch (KeytoolException e) {
            displayError(e);
        } catch (CoreException e) {
            displayError(e);
        }

        return false;
    
java.lang.StringgetDName()

        return mDName;
    
static java.lang.StringgetExceptionMessage(java.lang.Throwable t)
Returns the {@link Throwable#getMessage()}. If the {@link Throwable#getMessage()} returns null, the method is called again on the cause of the Throwable object.

If no Throwable in the chain has a valid message, the canonical name of the first exception is returned.

        String message = t.getMessage();
        if (message == null) {
            Throwable cause = t.getCause();
            if (cause != null) {
                return getExceptionMessage(cause);
            }

            // no more cause and still no message. display the first exception.
            return t.getClass().getCanonicalName();
        }
        
        return message;
    
java.util.ListgetExistingAliases()

        return mExistingAliases;
    
java.lang.StringgetKeyAlias()

        return mKeyAlias;
    
com.android.ide.eclipse.adt.project.export.ExportWizard$ExportWizardPagegetKeyCheckPage()

        return mKeyCheckPage;
    
booleangetKeyCreationMode()

        return mKeyCreationMode;
    
com.android.ide.eclipse.adt.project.export.ExportWizard$ExportWizardPagegetKeyCreationPage()

        return mKeyCreationPage;
    
java.lang.StringgetKeyPassword()

        return mKeyPassword;
    
com.android.ide.eclipse.adt.project.export.ExportWizard$ExportWizardPagegetKeySelectionPage()

        return mKeySelectionPage;
    
java.lang.StringgetKeystore()

        return mKeystore;
    
booleangetKeystoreCreationMode()

        return mKeystoreCreationMode;
    
java.lang.StringgetKeystorePassword()

        return mKeystorePassword;
    
com.android.ide.eclipse.adt.project.export.ExportWizard$ExportWizardPagegetKeystoreSelectionPage()

        return mKeystoreSelectionPage;
    
org.eclipse.core.resources.IProjectgetProject()

        return mProject;
    
intgetValidity()

        return mValidity;
    
public voidinit(org.eclipse.ui.IWorkbench workbench, org.eclipse.jface.viewers.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();
            }
        }
    
public booleanperformFinish()

        // save the properties
        ProjectHelper.saveStringProperty(mProject, PROPERTY_KEYSTORE, mKeystore);
        ProjectHelper.saveStringProperty(mProject, PROPERTY_ALIAS, mKeyAlias);
        ProjectHelper.saveStringProperty(mProject, PROPERTY_DESTINATION,
                mDestinationParentFolder.getAbsolutePath());
        ProjectHelper.saveStringProperty(mProject, PROPERTY_FILENAME,
                mApkMap.get(null)[APK_FILE_DEST]);
        
        // 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
                 */
                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];
    
voidresetDestination()

        mDestinationParentFolder = null;
        mApkMap = null;
    
voidsetDName(java.lang.String dName)

        mDName = dName;
        updatePageOnChange(ExportWizardPage.DATA_KEY);
    
voidsetDestination(java.io.File parentFolder, java.util.Map apkMap)

        mDestinationParentFolder = parentFolder;
        mApkMap = apkMap;
    
voidsetExistingAliases(java.util.List aliases)

        mExistingAliases = aliases;
    
private voidsetImageDescriptor()
Returns an image descriptor for the wizard logo.

        ImageDescriptor desc = AdtPlugin.getImageDescriptor(PROJECT_LOGO_LARGE);
        setDefaultPageImageDescriptor(desc);
    
voidsetKeyAlias(java.lang.String name)

        mKeyAlias = name;
        mPrivateKey = null;
        mCertificate = null;

        updatePageOnChange(ExportWizardPage.DATA_KEY);
    
voidsetKeyCreationMode(boolean createKey)

        mKeyCreationMode = createKey;
        updatePageOnChange(ExportWizardPage.DATA_KEY);
    
voidsetKeyPassword(java.lang.String password)

        mKeyPassword = password;
        mPrivateKey = null;
        mCertificate = null;

        updatePageOnChange(ExportWizardPage.DATA_KEY);
    
voidsetKeystore(java.lang.String path)

        mKeystore = path;
        mPrivateKey = null;
        mCertificate = null;
        
        updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
    
voidsetKeystoreCreationMode(boolean createStore)

        mKeystoreCreationMode = createStore;
        updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
    
voidsetKeystorePassword(java.lang.String password)

        mKeystorePassword = password;
        mPrivateKey = null;
        mCertificate = null;

        updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
    
voidsetProject(org.eclipse.core.resources.IProject project)

        mProject = project;
        
        updatePageOnChange(ExportWizardPage.DATA_PROJECT);
    
voidsetSigningInfo(java.security.PrivateKey privateKey, java.security.cert.X509Certificate certificate)

        mPrivateKey = privateKey;
        mCertificate = certificate;
    
voidsetValidity(int validity)

        mValidity = validity;
        updatePageOnChange(ExportWizardPage.DATA_KEY);
    
voidupdatePageOnChange(int changeMask)

        for (ExportWizardPage page : mPages) {
            page.projectDataChanged(changeMask);
        }