com.aptana.preview.PreviewManager.java Source code

Java tutorial

Introduction

Here is the source code for com.aptana.preview.PreviewManager.java

Source

/**
 * Aptana Studio
 * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
 * Please see the license.html included with this distribution for details.
 * Any modifications to this file must keep this entire header intact.
 */

package com.aptana.preview;

import java.io.File;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import net.contentobjects.jnotify.IJNotify;
import net.contentobjects.jnotify.JNotifyAdapter;
import net.contentobjects.jnotify.JNotifyException;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.IDocumentProvider;

import com.aptana.editor.common.IEditorLinkedResources;
import com.aptana.filewatcher.FileWatcher;
import com.aptana.preview.internal.DefaultPreviewHandler;
import com.aptana.preview.internal.EditorUtils;
import com.aptana.preview.internal.PreviewEditorInput;
import com.aptana.preview.internal.PreviewEditorPart;
import com.aptana.preview.internal.PreviewHandlers;
import com.aptana.ui.util.UIUtils;

/**
 * @author Max Stepanov
 * 
 */
public final class PreviewManager {

    private static PreviewManager instance;
    private IPropertyListener editorPropertyListener;
    private Map<IEditorPart, PreviewEditorInput> trackedEditors = new WeakHashMap<IEditorPart, PreviewEditorInput>();
    private Map<IEditorPart, Integer> filewatchIds = new HashMap<IEditorPart, Integer>();
    private Set<URI> trackedURIs = new HashSet<URI>();

    private IPartListener editorPartListener = new IPartListener() {

        public void partActivated(IWorkbenchPart part) {
        }

        public void partBroughtToTop(IWorkbenchPart part) {
        }

        public void partClosed(IWorkbenchPart part) {
            if (part instanceof IEditorPart) {
                part.removePropertyListener(editorPropertyListener);
                IEditorInput editorInput = ((IEditorPart) part).getEditorInput();
                if (editorInput instanceof IURIEditorInput) {
                    trackedURIs.remove(((IURIEditorInput) editorInput).getURI());
                }
            }
            if (trackedEditors.containsKey(part)) {
                trackedEditors.remove(part);
                // if it's in trackedEditors, it's guaranteed to be an IEditorPart
                removeFilewatchListener((IEditorPart) part);
            }
        }

        public void partDeactivated(IWorkbenchPart part) {
        }

        public void partOpened(IWorkbenchPart part) {
            if (part instanceof IEditorPart) {
                part.addPropertyListener(editorPropertyListener);
                IEditorInput editorInput = ((IEditorPart) part).getEditorInput();
                if (editorInput instanceof IURIEditorInput) {
                    trackedURIs.add(((IURIEditorInput) editorInput).getURI());
                }
            }
        }
    };

    private final IWindowListener windowListener = new IWindowListener() {

        public void windowActivated(IWorkbenchWindow window) {
        }

        public void windowClosed(IWorkbenchWindow window) {
            IPartService partService = window.getPartService();
            if (partService != null) {
                partService.removePartListener(editorPartListener);
            }
        }

        public void windowDeactivated(IWorkbenchWindow window) {
        }

        public void windowOpened(IWorkbenchWindow window) {
            IPartService partService = window.getPartService();
            if (partService != null) {
                partService.addPartListener(editorPartListener);
            }
        }
    };

    /**
     * 
     */
    private PreviewManager() {
        editorPropertyListener = new IPropertyListener() {

            public void propertyChanged(Object source, int propId) {
                if (source instanceof IEditorPart && EditorPart.PROP_DIRTY == propId
                        && !((EditorPart) source).isDirty()) {
                    if (trackedEditors.containsKey(source)) {
                        IEditorPart editorPart = (IEditorPart) source;
                        try {
                            openPreview(editorPart, editorPart.getEditorInput(), null, false);
                        } catch (CoreException e) {
                            PreviewPlugin.log(e);
                        }
                    } else {
                        IEditorInput editorInput = ((IEditorPart) source).getEditorInput();
                        if (editorInput instanceof IURIEditorInput) {
                            checkLinkedEditor(((IURIEditorInput) editorInput).getURI());
                        }
                    }
                }
            }
        };
    }

    public static PreviewManager getInstance() {
        if (instance == null) {
            instance = new PreviewManager();
        }
        return instance;
    }

    public void init() {
        addPartListener();
        // attaches property listener to all opened editors
        IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
        IWorkbenchPage[] pages;
        IEditorReference[] editors;
        IEditorPart editorPart;
        IEditorInput editorInput;
        for (IWorkbenchWindow window : windows) {
            pages = window.getPages();
            for (IWorkbenchPage page : pages) {
                editors = page.getEditorReferences();
                for (IEditorReference editor : editors) {
                    editorPart = editor.getEditor(false);
                    if (editorPart != null) {
                        editorPart.addPropertyListener(editorPropertyListener);
                        editorInput = ((IEditorPart) editorPart).getEditorInput();
                        if (editorInput instanceof IURIEditorInput) {
                            trackedURIs.add(((IURIEditorInput) editorInput).getURI());
                        }
                    }
                }
            }
        }
    }

    public void dispose() {
        removePartListener();
    }

    public void openPreviewForEditor(final IEditorPart editorPart) {
        try {
            final IEditorInput editorInput = editorPart.getEditorInput();
            if (!editorPart.isDirty()) {
                openPreview(editorPart, editorInput, null);
            } else if (editorPart instanceof AbstractTextEditor) {
                IDocumentProvider documentProvider = ((AbstractTextEditor) editorPart).getDocumentProvider();
                if (documentProvider != null) {
                    if (documentProvider.canSaveDocument(editorInput)) {
                        IDocument document = documentProvider.getDocument(editorInput);
                        if (document != null) {
                            try {
                                if (!openPreview(editorPart, editorInput, document.get())) {
                                    final boolean[] openPreview = new boolean[1];
                                    UIUtils.getDisplay().syncExec(new Runnable() {
                                        public void run() {
                                            openPreview[0] = MessageDialog.openQuestion(
                                                    editorPart.getSite().getShell(),
                                                    Messages.PreviewManager_UnsavedPrompt_Title,
                                                    Messages.PreviewManager_UnsavedPrompt_Message);
                                        }
                                    });
                                    if (openPreview[0]) {
                                        openPreview(editorPart, editorInput, null);
                                    }

                                }
                            } catch (CoreException e) {
                                PreviewPlugin.log(e);
                            }
                        }
                    } else {
                        openPreview(editorPart, editorInput, null);
                    }
                }
            }
        } catch (CoreException e) {
            PreviewPlugin.log(e);
        }
    }

    public void openPreviewForEditorInput(IEditorInput editorInput) {
        IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        IWorkbenchPage workbenchPage = null;
        if (workbenchWindow != null) {
            workbenchPage = workbenchWindow.getActivePage();
        }
        IEditorPart editorPart = null;
        if (workbenchPage != null) {
            editorPart = workbenchPage.findEditor(editorInput);
        }
        try {
            openPreview(editorPart, editorInput, null);
        } catch (CoreException e) {
            PreviewPlugin.log(e);
        }
    }

    public boolean testEditorInputForPreview(IEditorInput editorInput) {
        try {
            SourceConfig sourceConfig = getSourceConfig(editorInput, null);
            if (sourceConfig != null) {
                IPreviewHandler handler = PreviewHandlers.getInstance().getHandler(sourceConfig.getContentType());
                if (handler == null) {
                    handler = DefaultPreviewHandler.getInstance();
                }

                PreviewConfig previewConfig = handler.handle(sourceConfig);
                if (previewConfig == null && !(handler instanceof DefaultPreviewHandler)) {
                    previewConfig = DefaultPreviewHandler.getInstance().handle(sourceConfig);
                }
                return previewConfig != null;
            }
        } catch (CoreException e) {
            PreviewPlugin.log(e);
        }
        return false;
    }

    private boolean openPreview(IEditorPart editorPart, IEditorInput editorInput, String content)
            throws CoreException {
        return openPreview(editorPart, editorInput, content, true);
    }

    private SourceConfig getSourceConfig(IEditorInput editorInput, String content) throws CoreException {
        String fileName = null;
        IProject project = null;
        IPath path = null;
        IPath workspacePath = null;
        if (editorInput instanceof IPathEditorInput) {
            try {
                path = ((IPathEditorInput) editorInput).getPath();
                if (path != null) {
                    fileName = path.lastSegment();
                    IFile[] files = ResourcesPlugin.getWorkspace().getRoot()
                            .findFilesForLocationURI(path.toFile().toURI());
                    if (files.length > 0) {
                        project = files[0].getProject();
                        workspacePath = files[0].getFullPath();
                    }
                }
            } catch (Exception e) {
                return null;
            }
        } else if (editorInput instanceof IStorageEditorInput) {
            // TODO
        } else if (editorInput instanceof IURIEditorInput) {
            IFileStore fileStore = EFS.getStore(((IURIEditorInput) editorInput).getURI());
            if (fileStore != null) {
                File file = fileStore.toLocalFile(EFS.NONE, null);
                if (file != null) {
                    fileName = file.getName();
                    path = Path.fromOSString(file.getAbsolutePath());
                    IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.toURI());
                    if (files.length > 0) {
                        project = files[0].getProject();
                        workspacePath = files[0].getFullPath();
                    }
                }
            }
        } else if (editorInput instanceof PreviewEditorInput) {
            return null;
        }
        if (fileName == null) {
            return null;
        }
        IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(fileName);
        return new SourceConfig(editorInput, project, project != null ? workspacePath : path, content, contentType);
    }

    private boolean openPreview(final IEditorPart editorPart, IEditorInput editorInput, String content,
            boolean forceOpen) throws CoreException {
        SourceConfig sourceConfig = getSourceConfig(editorInput, content);
        PreviewConfig previewConfig = null;
        if (sourceConfig != null) {
            IPreviewHandler handler = PreviewHandlers.getInstance().getHandler(sourceConfig.getContentType());
            if (handler == null) {
                handler = DefaultPreviewHandler.getInstance();
            }
            previewConfig = handler.handle(sourceConfig);
            if (previewConfig == null && !(handler instanceof DefaultPreviewHandler)) {
                previewConfig = DefaultPreviewHandler.getInstance().handle(sourceConfig);
            }
        }
        if (previewConfig != null) {
            showEditor(editorPart, sourceConfig, previewConfig, forceOpen);
            return true;
        }
        return false;
    }

    private void showEditor(IEditorPart editorPart, SourceConfig sourceConfig, PreviewConfig previewConfig,
            boolean forceOpen) throws CoreException {
        IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        IWorkbenchPage workbenchPage = null;
        if (workbenchWindow != null) {
            workbenchPage = workbenchWindow.getActivePage();
        }
        if (workbenchPage == null) {
            throw new PartInitException("Cannot get Workbench page"); //$NON-NLS-1$
        }
        IEditorPart[] openedPreviewEditors = new IEditorPart[0];
        if (editorPart != null) {
            PreviewEditorInput previewEditorInput = trackedEditors.get(editorPart);
            if (previewEditorInput != null) {
                openedPreviewEditors = EditorUtils.findEditors(previewEditorInput, PreviewEditorPart.EDITOR_ID);
            }
        }
        PreviewEditorInput input = new PreviewEditorInput(previewConfig.getURL(),
                sourceConfig.getEditorInput().getName(), sourceConfig.getEditorInput().getToolTipText());
        if (openedPreviewEditors.length > 0) {
            for (IEditorPart previewEditorPart : openedPreviewEditors) {
                previewEditorPart.getSite().getPage().reuseEditor((IReusableEditor) previewEditorPart, input);
            }
            if (forceOpen) {
                workbenchPage.activate(openedPreviewEditors[0]);
            }
        } else {
            openedPreviewEditors = EditorUtils.findEditors(input, PreviewEditorPart.EDITOR_ID);
            if (openedPreviewEditors.length > 0) {
                for (IEditorPart previewEditorPart : openedPreviewEditors) {
                    previewEditorPart.getSite().getPage().reuseEditor((IReusableEditor) previewEditorPart, input);
                }
                if (forceOpen) {
                    workbenchPage.activate(openedPreviewEditors[0]);
                }
            } else if (forceOpen) {
                workbenchPage.openEditor(input, PreviewEditorPart.EDITOR_ID, true, IWorkbenchPage.MATCH_INPUT);
            }
        }
        if (editorPart != null && !trackedEditors.containsKey(editorPart)) {
            editorPart.addPropertyListener(editorPropertyListener);
            trackedEditors.put(editorPart, input);
            addFilewatchListener(editorPart);
        }
    }

    private void checkLinkedEditor(URI uri) {
        IEditorPart editorPart = null;
        for (IEditorPart editor : trackedEditors.keySet()) {
            IEditorLinkedResources editorLinkedResources = (IEditorLinkedResources) editor
                    .getAdapter(IEditorLinkedResources.class);
            if (editorLinkedResources != null) {
                if (editorLinkedResources.hasReference(uri)) {
                    editorPart = editor;
                    // TODO: what if multiple editors in the tracked list
                    // need to update?
                    // Need a way to know which editor the Preview editor is
                    // currently
                    // previewing against
                    break;
                }
            }
        }
        if (editorPart != null) {
            final IEditorPart finalEditorPart = editorPart;
            UIUtils.getDisplay().asyncExec(new Runnable() {

                public void run() {
                    try {
                        openPreview(finalEditorPart, finalEditorPart.getEditorInput(), null, false);
                    } catch (CoreException e) {
                        PreviewPlugin.log(e);
                    }
                }
            });
        }
    }

    private void addFilewatchListener(IEditorPart editorPart) {
        IEditorInput editorInput = editorPart.getEditorInput();
        String watchPath = null;
        if (editorInput instanceof IFileEditorInput) {
            watchPath = ((IFileEditorInput) editorInput).getFile().getProject().getLocation().toOSString();
        } else if (editorInput instanceof IPathEditorInput) {
            watchPath = ((IPathEditorInput) editorInput).getPath().toFile().getParentFile().getAbsolutePath();
        } else if (editorInput instanceof IURIEditorInput) {
            try {
                IFileStore fileStore = EFS.getStore(((IURIEditorInput) editorInput).getURI());
                if (fileStore != null) {
                    File file = fileStore.toLocalFile(EFS.NONE, null);
                    if (file != null) {
                        watchPath = file.getParentFile().getAbsolutePath();
                    }
                }
            } catch (CoreException e) {
                PreviewPlugin.log(e);
            }
        }
        if (watchPath != null) {
            try {
                int watchId = FileWatcher.addWatch(watchPath, IJNotify.FILE_ANY, true, new JNotifyAdapter() {

                    @Override
                    public void fileCreated(int wd, String rootPath, String name) {
                        fileModified(wd, rootPath, name);
                    }

                    @Override
                    public void fileModified(int wd, String rootPath, String name) {
                        URI fileURI = URIUtil.toURI(new Path(rootPath).append(name));
                        if (!trackedURIs.contains(fileURI)) {
                            checkLinkedEditor(fileURI);
                        }
                    }
                });
                filewatchIds.put(editorPart, watchId);
            } catch (JNotifyException e) {
                PreviewPlugin.log(e);
            }
        }
    }

    private void removeFilewatchListener(IEditorPart editorPart) {
        try {
            Integer id = filewatchIds.get(editorPart);
            if (id != null) {
                FileWatcher.removeWatch(id);
            }
        } catch (JNotifyException e) {
            PreviewPlugin.log(e);
        }
        filewatchIds.remove(editorPart);
    }

    private void addPartListener() {
        IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
        IPartService partService;
        for (IWorkbenchWindow window : windows) {
            partService = window.getPartService();
            if (partService != null) {
                partService.addPartListener(editorPartListener);
            }
        }
        // Listen on any future windows
        PlatformUI.getWorkbench().addWindowListener(windowListener);
    }

    private void removePartListener() {
        IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
        IPartService partService;
        for (IWorkbenchWindow window : windows) {
            partService = window.getPartService();
            if (partService != null) {
                partService.removePartListener(editorPartListener);
            }
        }
        PlatformUI.getWorkbench().removeWindowListener(windowListener);
    }
}