org.eclipse.common_prefs.exportWizard.CommonPrefsExportPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.common_prefs.exportWizard.CommonPrefsExportPage.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Ericsson and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Ericsson - initial API and implementation
 *******************************************************************************/

package org.eclipse.common_prefs.exportWizard;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;

import org.eclipse.common_prefs.StartupPlugin;
import org.eclipse.common_prefs.core.CommonPrefEPFResources;
import org.eclipse.common_prefs.core.CommonPrefsHelper;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferenceFilter;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
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.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.osgi.service.prefs.BackingStoreException;

/**
 * Wizard page appearing when selecting File->Export...:Common Preferences
 * 
 * @author Domenic Alessi
 *
 */
public class CommonPrefsExportPage extends WizardPage {

    private Tree imPrefTree;
    private Map<String, TreeItem> imNodeMap;
    private TreeMap<String, IEclipsePreferences> nodeMap;

    private Button imSelectAllButton;
    private Button imDeselectAllButton;

    private Button imFilterCommonButton;
    private Button imFilterDefaultButton;

    private Button addToCommonPrefsButton;

    private Label prefFileLabel;
    private Combo prefFileCombo;
    private Button prefBrowseButton;

    public CommonPrefsExportPage(String pageName, String title, ImageDescriptor titleImage) {
        super(pageName, title, titleImage);
        setDescription("Select Preferences to Export."); //NON-NLS-1
    }

    public void createControl(Composite parent) {
        // ======================================
        // Create new composite

        // Set F1 help
        // PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.IMPORT_PROJECT_SET_PAGE);

        Composite inner = new Composite(/*composite*/parent, SWT.NULL);
        inner.setLayoutData(new GridData(SWT.FILL));
        GridLayout layoutInner = new GridLayout(3, false);
        layoutInner.marginHeight = 0;
        layoutInner.marginWidth = 0;
        inner.setLayout(layoutInner);

        initializeDialogUnits(parent); // Not needed if including composite above
        int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);

        // ======================================
        // Pref tree group

        Group treeGroup = new Group(inner, SWT.NULL);
        treeGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
        GridLayout layoutTreeComp = new GridLayout(3, false);
        treeGroup.setLayout(layoutTreeComp);

        // ======================================
        // Filter common preferences

        imFilterCommonButton = new Button(treeGroup, SWT.CHECK);
        imFilterCommonButton.setText("Filter out preferences with value same as in Common Preferences files");
        imFilterCommonButton.setSelection(true);
        GridData gdfcb = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gdfcb.horizontalSpan = 3;
        imFilterCommonButton.setLayoutData(gdfcb);
        imFilterCommonButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                updatePrefTree();
            }
        });

        imFilterDefaultButton = new Button(treeGroup, SWT.CHECK);
        imFilterDefaultButton.setText("Filter out preferences with value same as default value");
        imFilterDefaultButton.setSelection(true);
        GridData gdfdb = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gdfdb.horizontalSpan = 3;
        imFilterDefaultButton.setLayoutData(gdfdb);
        imFilterDefaultButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                updatePrefTree();
            }
        });

        imPrefTree = new Tree(treeGroup, SWT.MULTI | SWT.BORDER | SWT.CHECK);
        GridData gdibst = new GridData(SWT.FILL, SWT.FILL, true, true);
        gdibst.horizontalSpan = 3;
        imPrefTree.setLayoutData(gdibst);
        imPrefTree.setHeaderVisible(true);
        imPrefTree.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                TreeItem item = (TreeItem) event.item;
                boolean isChecked = item.getChecked();

                TreeItem projectNode = CommonPrefsHelper.getPluginNode(item);
                projectNode.setChecked(isChecked);
                updateCheckAllState(isChecked, projectNode);
            }
        });
        imPrefTree.addControlListener(new ControlAdapter() {
            public void controlResized(ControlEvent e) {
                updateTreeSize();
            }
        });

        TreeColumn tc = new TreeColumn(imPrefTree, SWT.LEFT);
        tc.setText("Preference");
        String toolTip = "The preference key. A green icon indicates that value is same as default value or as\n";
        toolTip += "defined in an existing preference file, a red icon indicates the value is different.";
        tc.setToolTipText(toolTip);
        tc.setResizable(true);

        tc = new TreeColumn(imPrefTree, SWT.LEFT);
        tc.setText("Value");
        tc.setToolTipText("The value for the preference.");
        tc.setResizable(true);

        imSelectAllButton = new Button(treeGroup, SWT.PUSH);
        imSelectAllButton.setText("Select All");
        GridData gdsab = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        gdsab.widthHint = Math.max(widthHint, imSelectAllButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
        imSelectAllButton.setLayoutData(gdsab);
        imSelectAllButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                updateCheckAllState(true, null);
            }
        });

        imDeselectAllButton = new Button(treeGroup, SWT.PUSH);
        imDeselectAllButton.setText("Deselect All");
        GridData gddsab = new GridData(SWT.LEFT, SWT.CENTER, true, false);
        gddsab.horizontalSpan = 2;
        gddsab.widthHint = Math.max(widthHint, imDeselectAllButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
        imDeselectAllButton.setLayoutData(gddsab);
        imDeselectAllButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                updateCheckAllState(false, null);
            }
        });

        // ======================================
        // Browse for save location   

        prefFileLabel = new Label(inner, SWT.LEFT);
        prefFileLabel.setText("To preference file:");
        prefFileLabel.setToolTipText("Specify a file where the selected preferences will be saved.");
        GridData gdpfl = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        prefFileLabel.setLayoutData(gdpfl);

        prefFileCombo = new Combo(inner, SWT.DROP_DOWN);
        GridData gdfc = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gdfc.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
        prefFileCombo.setLayoutData(gdfc);
        prefFileCombo.setItems(CommonPrefsFileHistory.getHistory());
        prefFileCombo.setText(CommonPrefsFileHistory.getSuggestedDefault());
        prefFileCombo.addListener(SWT.Modify, new Listener() {
            public void handleEvent(Event event) {
                updateFinishEnablement();
            }
        });

        prefBrowseButton = new Button(inner, SWT.PUSH);
        prefBrowseButton.setText("Browse..." /*TeamUIMessages.ImportProjectSetMainPage_Browse_3*/);
        GridData gdbb = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        gdbb.widthHint = Math.max(widthHint, prefBrowseButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
        prefBrowseButton.setLayoutData(gdbb);
        prefBrowseButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {

                FileDialog fd = new FileDialog(getShell(), SWT.SAVE);
                fd.setText("Please provide a filename for saving the preferences");
                fd.setFilterExtensions(new String[] { "*.epf", "*" }); //$NON-NLS-1$
                fd.setFilterNames(new String[] { "Preference Files (*.epf)", "All Files (*.*)" });

                String fileName = prefFileCombo.getText();
                if (fileName != null && fileName.length() > 0) {
                    int separator = fileName.lastIndexOf(File.separatorChar); //$NON-NLS-1$
                    if (separator != -1) {
                        fileName = fileName.substring(0, separator);
                    }
                } else {
                    fileName = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
                }
                fd.setFilterPath(fileName);

                String f = fd.open();
                if (f != null) {
                    // Add suffix if missing
                    if (!f.endsWith(".epf"))
                        f += ".epf";

                    prefFileCombo.setText(f);
                    updateFinishEnablement();
                }
            }
        });

        addToCommonPrefsButton = new Button(inner, SWT.CHECK);
        addToCommonPrefsButton.setText("Include the preference file in the Common Preferences list");
        String cpToolTip = "Add the preference file to the list of preferences read at startup.\n";
        cpToolTip += "See also dialog in Windows:Preferences...:General:Common Preferences.";
        addToCommonPrefsButton.setToolTipText(cpToolTip);
        addToCommonPrefsButton.setSelection(false);
        GridData gdfb = new GridData(SWT.LEFT, SWT.CENTER, true, false);
        gdfb.horizontalSpan = 3;
        addToCommonPrefsButton.setLayoutData(gdfb);

        setControl(inner);

        // Initialize the page
        updatePreferencePage();

        Dialog.applyDialogFont(parent);
    }

    private void updatePreferencePage() {
        // Reset the status message in top of wizard page
        setMessage(null);

        updateFinishEnablement();
        updatePrefTree();
    }

    private void updatePrefTree() {
        imPrefTree.removeAll();
        imNodeMap = new HashMap<String, TreeItem>();

        boolean filterCommon = imFilterCommonButton.getSelection();
        boolean filterDefault = imFilterDefaultButton.getSelection();

        // Temporary comment this code for testing with eclipse 3.5
        /*Preferences commonPrefs = null;*/
        // End

        // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
        Properties commonProperties = null;
        // END

        if (filterCommon || filterDefault) {
            // Temporary comment this code for testing with eclipse 3.5
            /*commonPrefs = CommonPrefsHelper.readPreferences(filterCommon, filterDefault);*/
            // End

            // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
            commonProperties = CommonPrefsHelper.readPreferences(filterCommon, filterDefault);
            // END

        }

        nodeMap = new TreeMap<String, IEclipsePreferences>();
        CommonPrefsHelper.sortPreferences(nodeMap);

        Collection<IEclipsePreferences> nodes = nodeMap.values();
        for (IEclipsePreferences node : nodes) {
            // Temporary comment this code for testing with eclipse 3.5
            /*addNode(node, commonPrefs);*/
            // End

            // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
            addNode(node, commonProperties);
            // END
        }

        /*      
               // TODO: To get more information on a plug-in and possible group in features
               // tried to look up info. Not yet completed.
             
              IExtensionRegistry extReg = Platform.getExtensionRegistry();
              String[] names = extReg.getNamespaces();
              int i = 0;
              for (String name : names) {
                 TreeItem bsItem = new TreeItem(imBuildSpecTree, SWT.NONE);
                 bsItem.setText(name + "  " + (new Integer(i)).toString());
                 i++;
              }      
              Bundle[] bundles = Platform.getBundles("*", "");
              int i = 0;
              for (Bundle name : bundles) {
                 TreeItem bsItem = new TreeItem(imBuildSpecTree, SWT.NONE);
                 bsItem.setText(name.getSymbolicName() + "  " + (new Integer(i)).toString());
                 i++;
              }
        */
    }

    /**
     * Add a node and it's keys. If the commonPrefs are defined filter values.
     * 
     * @param node
     * @param nodeName
     * @param commonPrefs
     */
    /*private void addNode(IEclipsePreferences node, Preferences commonPrefs) {*/
    private void addNode(IEclipsePreferences node, Properties commonPrefsProperties) {

        // Get the actual preference key/value pairs
        String[] keys = null;
        try {
            keys = node.keys();
        } catch (BackingStoreException e) {
            e.printStackTrace();
        }

        // If not any keys skip adding the entry. Note that the node
        // might have sub-nodes as well, and if needed we will re-add
        // any missing parent nodes
        if (keys == null || keys.length == 0)
            return;

        // Add keys to TreeSet to order (and filter) them. NOTE: Since we don't want to
        // save individual keys, but rather a consistent set for the whole node - if one
        // is changed, include all. BUT give visual cue (icons) that not all are changed.
        String nodeName = node.absolutePath();

        TreeSet<String> keySetAll = new TreeSet<String>();
        TreeSet<String> keySetDiff = new TreeSet<String>();
        TreeSet<String> keySetDiffFile = new TreeSet<String>();
        for (String key : keys) {
            keySetAll.add(key);
            // Temporary comment this code for testing with eclipse 3.5
            /*if (commonPrefs != null){
               if (commonPrefs.contains(nodeName + "/" + key)) {
                  String valueStr = node.get(key, "");
                  String commStr = commonPrefs.getString(nodeName + "/" + key);
                  if (commStr.compareTo(valueStr) != 0)
              keySetDiffFile.add(key); // Diff value than in file
                  continue;
               }
            }   */
            // End

            // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
            if (commonPrefsProperties != null) {
                if (commonPrefsProperties.containsKey(nodeName + "/" + key)) {
                    String valueStr = node.get(key, "");
                    String commStr = commonPrefsProperties.getProperty(nodeName + "/" + key);
                    if (commStr.compareTo(valueStr) != 0)
                        keySetDiffFile.add(key); // Diff value than in file
                    continue;
                }
            }
            // END
            keySetDiff.add(key);
        }

        // If not any keys has changed value skip adding the node
        if (keySetDiff.size() == 0 && keySetDiffFile.size() == 0)
            return;

        // Get parent node from map 
        TreeItem pNode = CommonPrefsHelper.addNodeInternal(node, imNodeMap, imPrefTree);
        if (pNode == null)
            return; // Error

        ImageRegistry reg = StartupPlugin.getDefault().getImageRegistry();

        // Add key/value pairs to the tree
        for (String key : keySetAll) {
            TreeItem pdItem = new TreeItem(pNode, SWT.NONE);
            pdItem.setGrayed(true);
            pdItem.setText(key);
            pdItem.setText(1, node.get(key, "<default>"));

            // Indicate if the value is changed compared to what is defined in the Common Preferences
            // and the default values as saved on first init of workspace
            if (keySetDiff.contains(key))
                pdItem.setImage(reg.get(StartupPlugin.EXP_TREE_DIFF_VAL_IMG));
            else if (keySetDiffFile.contains(key))
                pdItem.setImage(reg.get(StartupPlugin.EXP_TREE_DIFF_FILE_VAL_IMG));
            else
                pdItem.setImage(reg.get(StartupPlugin.EXP_TREE_SAME_VAL_IMG));
        }
    }

    /**
     * The method will toggle the check state for all elements in the tree
     * Note that this method will not trigger events, so also need to set 
     * the item state.
     * 
     * @param isChecked
     */
    private void updateCheckAllState(boolean isChecked, TreeItem parentItem) {
        TreeItem[] bsItems = null;
        if (parentItem == null)
            bsItems = imPrefTree.getItems();
        else
            bsItems = parentItem.getItems();
        for (TreeItem bsItem : bsItems) {
            bsItem.setChecked(isChecked);
            updateCheckAllState(isChecked, bsItem);
        }
    }

    /**
     * Compute size of table relative its bounds.
     * TODO: Handle also resize within table.
     */
    private void updateTreeSize() {
        TreeColumn[] columns = imPrefTree.getColumns();
        int w = imPrefTree.getSize().x;
        int width = (w * 60) / 100;
        columns[0].setWidth(width);

        // NOTE: Make sum width - 4 since avoids the scroll bar
        columns[1].setWidth(w - width - 4);
    }

    private void updateFinishEnablement() {
        setMessage(null);

        if (prefFileCombo.getText().length() == 0) {
            setPageComplete(false);
            return;
        }

        File file = new File(prefFileCombo.getText());
        if (!file.isAbsolute()) {
            setMessage("Filename is not correct", ERROR);
            setPageComplete(false);
            return;
        } else if (file.isDirectory()) {
            setMessage("Filename is a directory", ERROR);
            setPageComplete(false);
            return;
        }

        setPageComplete(true);
    }

    /**
     * Export all selected entries to selected file. Note that each plug-in node
     * is exported separately, so gives some overhead - i.e. multiple time stamps
     * etc. Added a delimiter line to make file easier for human reading ...
     * 
     * @return boolean
     */
    public boolean performFinish() {
        File file = getPreferenceFileName();
        if (file == null)
            return false;

        IPreferencesService service = Platform.getPreferencesService();
        OutputStream output = null;
        FileOutputStream fos = null;
        IStatus s = null;
        try {
            // Comment this code for testing with eclipse 3.5
            /*fos = new FileOutputStream(file);
            output = new BufferedOutputStream(fos);*/
            // End

            // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
            IPreferenceFilter[] filters = getPreferenceFilters();
            fos = new FileOutputStream(file);
            // END

            List<TreeItem> items = CommonPrefsHelper.getPluginNodes(imPrefTree);
            for (TreeItem treeItem : items) {
                if (treeItem.getChecked()) {
                    IEclipsePreferences node = (IEclipsePreferences) treeItem.getData();
                    try {
                        // Comment this code for testing with eclipse 3.5
                        /*service.exportPreferences(node, output, (String[]) null);
                        output.write("#===================================\n".getBytes());*/
                        // End

                        // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
                        service.exportPreferences(node, filters, fos);
                        fos.write("#===================================\n".getBytes());
                        // END
                    } catch (CoreException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    }
                }
            }

            // Comment this code for testing with eclipse 3.5
            /*output.flush();
            fos.getFD().sync();*/
            // End

            // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
            fos.flush();
            fos.getFD().sync();
            // 
        } catch (IOException e) {
            e.printStackTrace();
            s = new Status(IStatus.ERROR, StartupPlugin.PLUGIN_ID, "Error when exporting preferences.", e);
        } finally {
            // Comment this code for testing with eclipse 3.5
            /*if (output != null)
               try {
                  output.close();
               } catch (IOException e) {
               }*/
            // End

            // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
            if (fos != null)
                try {
                    fos.close();
                } catch (IOException e) {
                }
            // END
        }

        if (s != null && !s.isOK()) {
            ErrorDialog.openError(getShell(), "Export Wizard Failed",
                    "One or more errors ocurred when trying to export the selected preferences.", s);
        } else {
            // Remember the location of the latest successful import
            CommonPrefsFileHistory.remember(file.getPath());

            if (addToCommonPrefsButton.getSelection()) {
                // Add to the Common Preferences list as "init" entry
                CommonPrefEPFResources cpFiles = StartupPlugin.getDefault().getCommonPrefFiles(null);
                try {
                    cpFiles.addPrefFile(null, file.getPath(), false, false);
                } catch (Exception e) {
                    // Will throw Exception if not valid. Never mind here
                }
                cpFiles.save();
            }
        }

        return true;
    }

    private File getPreferenceFileName() {
        String fileName = prefFileCombo.getText();

        // ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
        //System.out.println("EXPORT PAGE file name: " + fileName + "\n");
        // END

        File file = new File(fileName);
        if (file.exists()) {
            boolean okToOverwrite = MessageDialog.openConfirm(getShell(), "OK to overwrite file?",
                    "The file " + fileName + " already exists. OK to overwrite?");
            if (okToOverwrite)
                file.delete();
            else
                return null;
        }

        File parFile = file.getParentFile();
        if (parFile == null)
            return null;
        parFile.mkdirs();

        return file;
    }

    /**
     * ADD THIS CODE FOR TESTING WITH ECLIPSE 3.5
     * 
     * @return  IPreferenceFilter
     */
    private IPreferenceFilter[] getPreferenceFilters() {

        IPreferenceFilter[] transfers = new IPreferenceFilter[1];
        transfers[0] = new IPreferenceFilter() {
            public String[] getScopes() {
                return new String[] { InstanceScope.SCOPE, ConfigurationScope.SCOPE };
            }

            @SuppressWarnings("unchecked")
            public Map getMapping(String scope) {
                return null;
            }
        };
        return transfers;
    }

}