net.sf.eclipsensis.startup.FileAssociationChecker.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.eclipsensis.startup.FileAssociationChecker.java

Source

/*******************************************************************************
 * Copyright (c) 2004-2010 Sunil Kamath (IcemanK).
 * All rights reserved.
 * This program is made available under the terms of the Common Public License
 * v1.0 which is available at http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 *     Sunil Kamath (IcemanK) - initial API and implementation
 *******************************************************************************/
package net.sf.eclipsensis.startup;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.registry.EditorRegistry;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.eclipse.ui.progress.UIJob;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;

@SuppressWarnings("restriction")
public class FileAssociationChecker implements IStartup, IExtensionChangeHandler {
    private static final IPreferenceStore PREFERENCES = EclipseNSISStartup.getDefault().getPreferenceStore();
    private static final String EXTENSION_POINT = "fileAssociations"; //$NON-NLS-1$
    private static final String ELEM_ASSOCIATION = "association"; //$NON-NLS-1$
    private static final String ELEM_ENABLEMENT = "enablement"; //$NON-NLS-1$
    private static final String ELEM_FILETYPES = "fileTypes"; //$NON-NLS-1$
    private static final String ELEM_FILETYPE = "fileType"; //$NON-NLS-1$
    private static final String ELEM_EDITORS = "editors"; //$NON-NLS-1$
    private static final String ELEM_EDITOR = "editor"; //$NON-NLS-1$
    private static final String ATTR_DEFAULT_VALUE = "defaultValue"; //$NON-NLS-1$
    private static final String ATTR_INIT_PREFERENCE = "initPreference"; //$NON-NLS-1$
    private static final String ATTR_NAME = "name"; //$NON-NLS-1$
    private static final String ATTR_ID = "id"; //$NON-NLS-1$

    private static FileAssociationChecker cInstance = null;
    private static Collection<String> cCheckedAssociations = new HashSet<String>();

    private static final Object JOB_FAMILY = new Object();

    private Map<String, FileAssociationDef> mFileAssociationMap = new LinkedHashMap<String, FileAssociationDef>();
    private IEditorRegistry mEditorRegistry;
    private String mJobName;
    private MessageFormat mDialogTitleFormat;
    private MessageFormat mDialogMessageFormat;
    private MessageFormat mDialogToggleMessageFormat;
    private static final ISchedulingRule cSchedulingRule = new ISchedulingRule() {
        public boolean contains(ISchedulingRule rule) {
            return rule == this;
        }

        public boolean isConflicting(ISchedulingRule rule) {
            return rule == this;
        }
    };

    public FileAssociationChecker() {
        mEditorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
        mJobName = EclipseNSISStartup.getResourceString("job.name"); //$NON-NLS-1$
        mDialogTitleFormat = new MessageFormat(EclipseNSISStartup.getResourceString("dialog.title.format")); //$NON-NLS-1$
        mDialogMessageFormat = new MessageFormat(EclipseNSISStartup.getResourceString("dialog.message.format")); //$NON-NLS-1$
        mDialogToggleMessageFormat = new MessageFormat(
                EclipseNSISStartup.getResourceString("dialog.toggle.message.format")); //$NON-NLS-1$
        final IExtensionTracker tracker = PlatformUI.getWorkbench().getExtensionTracker();
        loadExtensions(tracker);
        tracker.registerHandler(this, ExtensionTracker.createExtensionPointFilter(getExtensionPointFilter()));
        final BundleContext bundleContext = EclipseNSISStartup.getDefault().getBundleContext();
        bundleContext.addBundleListener(new BundleListener() {
            public void bundleChanged(BundleEvent event) {
                if (event.getType() == BundleEvent.STOPPED) {
                    bundleContext.removeBundleListener(this);
                }
                tracker.unregisterHandler(FileAssociationChecker.this);
                Job.getJobManager().cancel(JOB_FAMILY);
            }
        });
    }

    public void earlyStartup() {
        cInstance = this;
        for (Iterator<FileAssociationDef> iter = mFileAssociationMap.values().iterator(); iter.hasNext();) {
            scheduleJob(iter.next());
        }
    }

    private void loadExtensions(IExtensionTracker tracker) {
        IExtensionPoint point = getExtensionPointFilter();
        if (point != null) {
            IExtension[] extensions = point.getExtensions();
            for (int i = 0; i < extensions.length; i++) {
                addExtension(tracker, extensions[i]);
            }
            EclipseNSISStartup.getDefault().savePreferences();
        }
    }

    private IExtensionPoint getExtensionPointFilter() {
        return Platform.getExtensionRegistry().getExtensionPoint(EclipseNSISStartup.PLUGIN_ID, EXTENSION_POINT);
    }

    public void addExtension(IExtensionTracker tracker, IExtension extension) {
        IConfigurationElement[] associations = extension.getConfigurationElements();
        String bundleId = extension.getNamespaceIdentifier();
        for (int i = 0; i < associations.length; i++) {
            if (ELEM_ASSOCIATION.equals(associations[i].getName())) {
                List<String> fileTypesList = null;
                List<String> editorIdsList = null;
                String id = associations[i].getAttribute(ATTR_ID);
                String fileTypesName = ""; //$NON-NLS-1$
                String editorsName = ""; //$NON-NLS-1$
                IConfigurationElement[] children = associations[i].getChildren();
                boolean enablement = true;
                String enablementPref = null;
                for (int j = 0; j < children.length; j++) {
                    String name = children[j].getName();
                    if (fileTypesList == null && ELEM_FILETYPES.equals(name)) {
                        fileTypesName = children[j].getAttribute(ATTR_NAME);
                        fileTypesList = new ArrayList<String>();
                        IConfigurationElement[] fileTypes = children[j].getChildren();
                        for (int k = 0; k < fileTypes.length; k++) {
                            if (ELEM_FILETYPE.equals(fileTypes[k].getName())) {
                                fileTypesList.add(fileTypes[k].getAttribute(ATTR_NAME));
                            }
                        }
                    } else if (editorIdsList == null && ELEM_EDITORS.equals(name)) {
                        editorsName = children[j].getAttribute(ATTR_NAME);
                        editorIdsList = new ArrayList<String>();
                        IConfigurationElement[] editors = children[j].getChildren();
                        for (int k = 0; k < editors.length; k++) {
                            if (ELEM_EDITOR.equals(editors[k].getName())) {
                                editorIdsList.add(editors[k].getAttribute(ATTR_ID));
                            }
                        }
                    } else if (ELEM_ENABLEMENT.equals(name)) {
                        String value = children[j].getAttribute(ATTR_DEFAULT_VALUE);
                        if (value != null) {
                            enablement = Boolean.valueOf(value).booleanValue();
                        }
                        enablementPref = children[j].getAttribute(ATTR_INIT_PREFERENCE);
                    }
                }
                if (fileTypesList != null && editorIdsList != null) {
                    initializePreference(id, enablement, bundleId, enablementPref);
                    mFileAssociationMap.put(id,
                            new FileAssociationDef(id, fileTypesName,
                                    fileTypesList.toArray(new String[fileTypesList.size()]), editorsName,
                                    editorIdsList.toArray(new String[editorIdsList.size()])));
                }
            }
        }
    }

    private void initializePreference(String associationId, boolean enablement, String bundleId,
            String enablementPref) {
        if (!PREFERENCES.contains(associationId)) {
            boolean enablement2 = enablement;
            if (enablementPref != null) {
                Bundle bundle = Platform.getBundle(bundleId);
                if (bundle != null) {
                    IPreferenceStore prefs = new ScopedPreferenceStore(new InstanceScope(),
                            bundle.getSymbolicName());
                    if (prefs.contains(enablementPref)) {
                        enablement2 = prefs.getBoolean(enablementPref);
                    }
                }
            }
            PREFERENCES.setValue(associationId, Boolean.toString(enablement2));
        }
    }

    private void scheduleJob(final FileAssociationDef def) {
        if (def != null) {
            Job job = new UIJob(mJobName) {
                private boolean isValidEditor(String[] editorIds, IEditorDescriptor descriptor) {
                    if (descriptor != null) {
                        String id = descriptor.getId();
                        for (int i = 0; i < editorIds.length; i++) {
                            if (editorIds[i].equals(id)) {
                                return true;
                            }
                        }
                    }
                    return false;
                }

                @Override
                public IStatus runInUIThread(final IProgressMonitor monitor) {
                    if (monitor.isCanceled()) {
                        return Status.CANCEL_STATUS;
                    }
                    if (!cCheckedAssociations.contains(def.getAssociationId())) {
                        final boolean toggleState = getFileAssociationChecking(def.getAssociationId());
                        if (toggleState) {
                            cCheckedAssociations.add(def.getAssociationId());
                            final String[] fileTypes = def.getFileTypes();
                            for (int i = 0; i < fileTypes.length; i++) {
                                if (monitor.isCanceled()) {
                                    return Status.CANCEL_STATUS;
                                }
                                if (!isValidEditor(def.getEditorIds(),
                                        mEditorRegistry.getDefaultEditor(fileTypes[i]))) {
                                    if (!monitor.isCanceled()) {
                                        String[] args = new String[] { def.getFileTypesName(),
                                                def.getEditorsName() };
                                        MessageDialogWithToggle dialog = MessageDialogWithToggle
                                                .openYesNoCancelQuestion(
                                                        PlatformUI.getWorkbench().getActiveWorkbenchWindow()
                                                                .getShell(),
                                                        mDialogTitleFormat.format(args),
                                                        mDialogMessageFormat.format(args),
                                                        mDialogToggleMessageFormat.format(args), !toggleState, null,
                                                        null);
                                        int rc = dialog.getReturnCode();
                                        switch (rc) {
                                        case IDialogConstants.YES_ID: {
                                            for (int j = 0; j < fileTypes.length; j++) {
                                                mEditorRegistry.setDefaultEditor(fileTypes[j],
                                                        def.getEditorIds()[0]);
                                            }
                                            //Cast to inner class because otherwise it cannot be saved.
                                            ((EditorRegistry) mEditorRegistry).saveAssociations();
                                            //Fall through to next case to save the toggle state
                                        }
                                        //$FALL-THROUGH$
                                        case IDialogConstants.NO_ID: {
                                            boolean newToggleState = !dialog.getToggleState();
                                            if (toggleState != newToggleState) {
                                                setFileAssociationChecking(def.getAssociationId(), newToggleState);
                                            }
                                            break;
                                        }
                                        case IDialogConstants.CANCEL_ID:
                                            return Status.CANCEL_STATUS;
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    if (monitor.isCanceled()) {
                        return Status.CANCEL_STATUS;
                    } else {
                        return Status.OK_STATUS;
                    }
                }
            };
            job.setRule(cSchedulingRule);
            job.schedule(5000);
        }
    }

    public void removeExtension(IExtension extension, Object[] objects) {
    }

    public static final boolean getFileAssociationChecking(String associationId) {
        String value = PREFERENCES.getString(associationId);
        if (value != null) {
            return Boolean.valueOf(value).booleanValue();
        }
        return false;
    }

    public static final void setFileAssociationChecking(String associationId, boolean flag) {
        if (getFileAssociationChecking(associationId) != flag) {
            PREFERENCES.setValue(associationId, Boolean.toString(flag));
            EclipseNSISStartup.getDefault().savePreferences();
        }
    }

    public static final void checkFileAssociation(String associationId) {
        if (cInstance == null) {
            cInstance = new FileAssociationChecker();
        }
        if (!cCheckedAssociations.contains(associationId)) {
            cInstance.scheduleJob(cInstance.mFileAssociationMap.get(associationId));
        }
    }

    private class FileAssociationDef {
        String mAssociationId;
        String mFileTypesName;
        String[] mFileTypes;
        String mEditorsName;
        String[] mEditorIds;

        public FileAssociationDef(String associationId, String fileTypesName, String[] fileTypes,
                String editorsName, String[] editorIds) {
            mAssociationId = associationId;
            mFileTypesName = fileTypesName;
            mFileTypes = fileTypes;
            mEditorsName = editorsName;
            mEditorIds = editorIds;
        }

        public String getAssociationId() {
            return mAssociationId;
        }

        public String[] getEditorIds() {
            return mEditorIds;
        }

        public String getEditorsName() {
            return mEditorsName;
        }

        public String[] getFileTypes() {
            return mFileTypes;
        }

        public String getFileTypesName() {
            return mFileTypesName;
        }
    }
}