org.eclipse.andmore.android.wizards.installapp.DeployWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.andmore.android.wizards.installapp.DeployWizardPage.java

Source

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.eclipse.andmore.android.wizards.installapp;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.eclipse.andmore.android.AndroidPlugin;
import org.eclipse.andmore.android.common.log.AndmoreLogger;
import org.eclipse.andmore.android.i18n.AndroidNLS;
import org.eclipse.andmore.android.wizards.elements.FileChooser;
import org.eclipse.andmore.android.wizards.installapp.DeployWizard.INSTALL_TYPE;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
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.Group;
import org.eclipse.ui.PlatformUI;

/**
 * Wizard Page used by Deploy Wizard
 */
public class DeployWizardPage extends WizardPage {
    private FileChooser fileChooser = null;

    private String initialPackagePath = null;

    private String packageSelectionMessage = null;

    private String packagetext = null;

    private final String packageExtension = "apk";

    private Button overwiteRadio = null;

    private Button uninstallRadio = null;

    private Button doNothingRadio = null;

    private static final String contextId = AndroidPlugin.PLUGIN_ID + ".install_app";

    private static INSTALL_TYPE installType;

    private final String DSA_FILE_EXTENSION = ".DSA";

    private final String RSA_FILE_EXTENSION = ".RSA";

    private final String SF_FILE_EXTENSION = ".SF";

    private static String lastUsedPackage = null;

    /**
     * Constructor
     * 
     * @param initialPackagePath
     * @param selectPCKMessage
     *            Message asking for package selection
     */
    public DeployWizardPage(String initialPackagePath, String selectPCKMessage, String browseButtonText,
            String packagetext) {
        super("");

        if ((browseButtonText == null) || (packagetext == null) || (selectPCKMessage == null)) {
            throw new IllegalArgumentException("Could not create Deploy Wizard: null argument");
        }

        if (initialPackagePath == null) {
            this.initialPackagePath = lastUsedPackage != null ? lastUsedPackage : "";
        } else {
            this.initialPackagePath = initialPackagePath;
        }

        this.packagetext = packagetext;
        packageSelectionMessage = selectPCKMessage;

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
     * .Composite)
     */
    @Override
    public void createControl(Composite parent) {
        // Main composite for the UI
        Composite mainComposite = new Composite(parent, SWT.FILL);

        PlatformUI.getWorkbench().getHelpSystem().setHelp(mainComposite, contextId);

        mainComposite.setLayout(new GridLayout());
        mainComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL, GridData.FILL_VERTICAL, true, true));

        // Package group
        Group packageGroup = new Group(mainComposite, SWT.NONE);
        packageGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        packageGroup.setLayout(new GridLayout(3, false));
        packageGroup.setText(packagetext);

        fileChooser = new FileChooser(packageGroup, SWT.NONE, null);
        fileChooser.setFilterExtensions(new String[] { "*." + packageExtension });
        fileChooser.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
        fileChooser.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                validateSelection();
            }
        });
        createOptionButtons(mainComposite);

        mainComposite.pack();

        setPageComplete(false);
        loadInitialValues();

        setControl(mainComposite);
    }

    private void createOptionButtons(Composite mainComposite) {

        GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1);
        overwiteRadio = new Button(mainComposite, SWT.RADIO);
        overwiteRadio.setText(AndroidNLS.UI_DeployWizardPage_ReplaceApp);
        overwiteRadio.setSelection(true);
        overwiteRadio.setLayoutData(data);
        overwiteRadio.setData(INSTALL_TYPE.OVERWRITE);
        overwiteRadio.addSelectionListener(new SelectionAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
             * .swt.events.SelectionEvent)
             */
            @Override
            public void widgetSelected(SelectionEvent e) {
                installType = (INSTALL_TYPE) overwiteRadio.getData();
            }

        });

        uninstallRadio = new Button(mainComposite, SWT.RADIO);
        uninstallRadio.setText(AndroidNLS.UI_DeployWizardPage_UninstallApp);
        uninstallRadio.setSelection(true);
        uninstallRadio.setLayoutData(data);
        uninstallRadio.setData(INSTALL_TYPE.UNINSTALL);
        uninstallRadio.addSelectionListener(new SelectionAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
             * .swt.events.SelectionEvent)
             */
            @Override
            public void widgetSelected(SelectionEvent e) {
                installType = (INSTALL_TYPE) uninstallRadio.getData();
            }

        });

        doNothingRadio = new Button(mainComposite, SWT.RADIO);
        doNothingRadio.setText(AndroidNLS.UI_DeployWizardPage_DoNothingApp);
        doNothingRadio.setSelection(true);
        doNothingRadio.setLayoutData(data);
        doNothingRadio.setData(INSTALL_TYPE.DO_NOTHING);
        doNothingRadio.addSelectionListener(new SelectionAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
             * .swt.events.SelectionEvent)
             */
            @Override
            public void widgetSelected(SelectionEvent e) {
                installType = (INSTALL_TYPE) doNothingRadio.getData();
            }

        });
        overwiteRadio.setSelection(true);
        uninstallRadio.setSelection(false);
        doNothingRadio.setSelection(false);
        installType = (INSTALL_TYPE.OVERWRITE);

    }

    /**
     * Load the initial values to be filled in the wizard
     */
    private void loadInitialValues() {
        if ((initialPackagePath != null) && (initialPackagePath.length() != 0)) {
            fileChooser.setText(initialPackagePath);
            validateSelection();
        } else {
            setMessage(packageSelectionMessage, IMessageProvider.NONE);
        }
    }

    /**
     * Validates the selected package and device instance setting the
     * appropriated messages and errors
     */
    private synchronized void validateSelection() {
        String packagePath = fileChooser.getText();

        if (isValidPackage(packagePath)) {
            setErrorMessage(null);
            setPageComplete(true);
        } else {
            setPageComplete(false);
        }
    }

    /**
     * Verify if a package is valid MPKG
     * 
     * @param packagePath
     * @return TRUE if the package is valid or FALSE otherwise
     */
    private boolean isValidPackage(String packagePath) {
        boolean result = false;
        Path path = new Path(packagePath);
        String extension = path.getFileExtension();

        // testing if the entered path is a folder
        result = path.toFile().isFile();
        if (!result) {
            setErrorMessage(AndroidNLS.UI_DeployWizardPage_PackageIsAFolder);
        } else {
            result = ((extension != null) && extension.equals(packageExtension)
                    && path.isValidPath(path.toString()));

            if (!result) {
                setErrorMessage(AndroidNLS.UI_DeployWizardPage_InvalidPath);
            } else {
                // Test if file exists
                result = path.toFile().exists();
                if (!result) {
                    setErrorMessage(AndroidNLS.UI_DeployWizardPage_FileDoesNotExist);
                }
            }
        }

        if (result) {
            setMessage("", IMessageProvider.NONE);

            // Test if the package is valid
            result = isPackageSigned(packagePath);
            if (!result) {
                setErrorMessage(AndroidNLS.UI_DeployWizardPage_NotSignedMessage);
            }
        }

        return result;
    }

    /**
     * Verify if the package is signed based on the existence of an .SF file and
     * a corresponding DSA or RSA file.
     * 
     * @param packagePath
     * @return TRUE if the package is signed
     */
    private synchronized boolean isPackageSigned(String packagePath) {
        // Temporary placeholders for the package entries
        List<String> SFFiles = new ArrayList<String>();
        List<String> RSAFiles = new ArrayList<String>();
        List<String> DSAFiles = new ArrayList<String>();

        // Temporary result
        boolean result = false;
        JarFile jar = null;
        try {
            jar = new JarFile(packagePath, false);
            Enumeration<JarEntry> enu = jar.entries();

            // interact over the elements of the package
            while (enu.hasMoreElements()) {
                JarEntry entry = enu.nextElement();
                if (entry.getName().toUpperCase().endsWith(SF_FILE_EXTENSION)) {
                    // Mounts the list of SF files
                    SFFiles.add(entry.getName().toUpperCase());
                } else if (entry.getName().toUpperCase().endsWith(RSA_FILE_EXTENSION)) {
                    // Mounts the list of RSA files
                    RSAFiles.add(entry.getName().toUpperCase());
                } else if (entry.getName().toUpperCase().endsWith(DSA_FILE_EXTENSION)) {
                    // Mounts the list of DSA files
                    DSAFiles.add(entry.getName().toUpperCase());
                }
            }

            if (!SFFiles.isEmpty()) {
                for (String sfFile : SFFiles) {
                    // Interacts over the list of SF files until it ends or
                    // until a correspondent DSA or RSA is found
                    Path p = new Path(sfFile);
                    sfFile = p.removeFileExtension().toString();
                    result = (DSAFiles.contains(sfFile + DSA_FILE_EXTENSION)
                            || RSAFiles.contains(sfFile + RSA_FILE_EXTENSION));
                }
            }

        } catch (Exception e) {
            // Could not read the jar file
            AndmoreLogger.error(DeployWizardPage.class, "Deploy: Could not verify file " + packagePath, e);
        } finally {
            if (jar != null) {
                try {
                    jar.close();
                } catch (IOException e) {
                    AndmoreLogger.error(DeployWizardPage.class, "Error closing package after verification", e);
                }
            }
        }

        return result;

    }

    /**
     * Gets the selected package path
     * 
     * @return the package Path
     */
    public String getPackagePath() {
        String packagePath = fileChooser.getText();
        if (isValidPackage(packagePath)) {
            lastUsedPackage = packagePath;
        }
        return packagePath;
    }

    /**
     * Return true if the application should be replaced in the case it is
     * already installed on the device
     * 
     */
    public INSTALL_TYPE canOverwrite() {
        return installType;
    }
}