From 750fc538f67a55693b623621fbc8e37b189406f4 Mon Sep 17 00:00:00 2001 From: Tobias Schwarz Date: Fri, 25 Apr 2014 11:32:45 +0200 Subject: Target Explorer: fix slow folder selection dialog and not working refresh --- .../callbacks/RefreshStateDoneOpenChannel.java | 176 ++++++++++----------- .../filesystem/core/model/AbstractTreeNode.java | 45 ++++-- .../te/tcf/filesystem/core/model/FSTreeNode.java | 46 +++--- .../ui/dialogs/FSFolderSelectionDialog.java | 50 +++--- 4 files changed, 160 insertions(+), 157 deletions(-) diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/callbacks/RefreshStateDoneOpenChannel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/callbacks/RefreshStateDoneOpenChannel.java index 825f5760d..d194fb97e 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/callbacks/RefreshStateDoneOpenChannel.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/callbacks/RefreshStateDoneOpenChannel.java @@ -1,88 +1,88 @@ -/******************************************************************************* - * Copyright (c) 2012 Wind River Systems, Inc. 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: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.tcf.te.tcf.filesystem.core.internal.callbacks; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.Status; -import org.eclipse.osgi.util.NLS; -import org.eclipse.tcf.protocol.IChannel; -import org.eclipse.tcf.protocol.IPeer; -import org.eclipse.tcf.services.IFileSystem; -import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; -import org.eclipse.tcf.te.tcf.core.Tcf; -import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; -import org.eclipse.tcf.te.tcf.filesystem.core.activator.CorePlugin; -import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFFileSystemException; -import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; -import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages; - -/** - * The callback to process the channel opened event for refreshing the state of a - * file system node. - */ -public class RefreshStateDoneOpenChannel extends CallbackBase implements IChannelManager.DoneOpenChannel{ - // The node to be refreshed. - FSTreeNode node; - // The callback after the refreshing is done. - ICallback callback; - - /** - * Create an instance. - */ - public RefreshStateDoneOpenChannel(FSTreeNode node, ICallback callback) { - this.node = node; - this.callback = callback; - } - - /* - * (non-Javadoc) - * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel#doneOpenChannel(java.lang.Throwable, org.eclipse.tcf.protocol.IChannel) - */ - @Override - public void doneOpenChannel(Throwable error, IChannel channel) { - IPeer peer = node.peerNode.getPeer(); - if (error != null) { - if(channel != null) { - Tcf.getChannelManager().closeChannel(channel); - } - if (!(error instanceof OperationCanceledException)) { - String message = getErrorMessage(error); - IStatus status = new Status(IStatus.ERROR, CorePlugin.getUniqueIdentifier(), message, error); - invokeCallback(status); - } - } - else { - IFileSystem service = channel.getRemoteService(IFileSystem.class); - if (service != null) { - String path = node.getLocation(true); - service.stat(path, new RefreshStateDoneStat(node, channel, callback)); - } - else { - Tcf.getChannelManager().closeChannel(channel); - String message = NLS.bind(Messages.Operation_NoFileSystemError, peer.getID()); - IStatus status = new Status(IStatus.ERROR, CorePlugin.getUniqueIdentifier(), message, new TCFFileSystemException(IStatus.ERROR, message)); - invokeCallback(status); - } - } - } - - /** - * Invoke the callback using the specified status, if the callback - * is not null. - * - * @param status The processing result. - */ - private void invokeCallback(IStatus status) { - if(callback != null) { - callback.done(this, status); - } - } -} +/******************************************************************************* + * Copyright (c) 2012 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.core.internal.callbacks; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.services.IFileSystem; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.tcf.core.Tcf; +import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; +import org.eclipse.tcf.te.tcf.filesystem.core.activator.CorePlugin; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFFileSystemException; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages; + +/** + * The callback to process the channel opened event for refreshing the state of a + * file system node. + */ +public class RefreshStateDoneOpenChannel extends CallbackBase implements IChannelManager.DoneOpenChannel{ + // The node to be refreshed. + FSTreeNode node; + // The callback after the refreshing is done. + ICallback callback; + + /** + * Create an instance. + */ + public RefreshStateDoneOpenChannel(FSTreeNode node, ICallback callback) { + this.node = node; + this.callback = callback; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel#doneOpenChannel(java.lang.Throwable, org.eclipse.tcf.protocol.IChannel) + */ + @Override + public void doneOpenChannel(Throwable error, IChannel channel) { + IPeer peer = node.peerNode.getPeer(); + if (error != null) { + if(channel != null) { + Tcf.getChannelManager().closeChannel(channel); + } + if (!(error instanceof OperationCanceledException)) { + String message = getErrorMessage(error); + IStatus status = new Status(IStatus.ERROR, CorePlugin.getUniqueIdentifier(), message, error); + invokeCallback(status); + } + } + else { + IFileSystem service = channel.getRemoteService(IFileSystem.class); + if (service != null) { + String path = node.getLocation(true); + service.stat(path, new RefreshStateDoneStat(node, channel, callback)); + } + else { + Tcf.getChannelManager().closeChannel(channel); + String message = NLS.bind(Messages.Operation_NoFileSystemError, peer.getID()); + IStatus status = new Status(IStatus.ERROR, CorePlugin.getUniqueIdentifier(), message, new TCFFileSystemException(IStatus.ERROR, message)); + invokeCallback(status); + } + } + } + + /** + * Invoke the callback using the specified status, if the callback + * is not null. + * + * @param status The processing result. + */ + private void invokeCallback(IStatus status) { + if(callback != null) { + callback.done(this, status); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/AbstractTreeNode.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/AbstractTreeNode.java index 01fd7a72a..103ef6293 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/AbstractTreeNode.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/AbstractTreeNode.java @@ -17,9 +17,11 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.tcf.te.core.interfaces.IPropertyChangeProvider; import org.eclipse.tcf.te.core.interfaces.IViewerInput; +import org.eclipse.tcf.te.runtime.callback.Callback; import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; import org.eclipse.tcf.te.tcf.core.Tcf; import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; @@ -118,14 +120,14 @@ public abstract class AbstractTreeNode extends PlatformObject { firePropertyChange(event); } - /** - * Called when the children query is started. - */ - public void queryStarted() { - childrenQueryRunning = true; - PropertyChangeEvent event = new PropertyChangeEvent(this, "query_started", Boolean.FALSE, Boolean.TRUE); //$NON-NLS-1$ - firePropertyChange(event); - } + /** + * Called when the children query is started. + */ + public void queryStarted() { + childrenQueryRunning = true; + PropertyChangeEvent event = new PropertyChangeEvent(this, "query_started", Boolean.FALSE, Boolean.TRUE); //$NON-NLS-1$ + firePropertyChange(event); + } /** * Get the user account of the specified TCF peer. @@ -265,14 +267,18 @@ public abstract class AbstractTreeNode extends PlatformObject { * * @param callback The callback object, or null when callback is not needed. */ - public void refresh(ICallback callback) { - if (childrenQueryRunning) { - return; - } - queryStarted(); + public void refresh(final ICallback callback) { Map flags = new HashMap(); flags.put(IChannelManager.FLAG_NO_PATH_MAP, Boolean.TRUE); - Tcf.getChannelManager().openChannel(peerNode.getPeer(), flags, doCreateRefreshDoneOpenChannel(callback)); + Tcf.getChannelManager().openChannel(peerNode.getPeer(), flags, doCreateRefreshDoneOpenChannel(new Callback() { + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.callback.Callback#internalDone(java.lang.Object, org.eclipse.core.runtime.IStatus) + */ + @Override + protected void internalDone(Object caller, IStatus status) { + refreshChildren(callback); + } + })); } /** @@ -286,7 +292,7 @@ public abstract class AbstractTreeNode extends PlatformObject { /** * Query the children of this file system node. */ - public void queryChildren() { + public final void queryChildren() { queryChildren(null); } /** @@ -325,5 +331,12 @@ public abstract class AbstractTreeNode extends PlatformObject { /** * Refresh the children's children. */ - public abstract void refreshChildren(); + public final void refreshChildren() { + refreshChildren(null); + } + + /** + * Refresh the children's children. + */ + public abstract void refreshChildren(ICallback callback); } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/FSTreeNode.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/FSTreeNode.java index 16265e42c..10ef8b887 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/FSTreeNode.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/model/FSTreeNode.java @@ -30,6 +30,7 @@ import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.tcf.protocol.Protocol; import org.eclipse.tcf.services.IFileSystem; @@ -70,7 +71,7 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi /** * Create a folder node using the specified parent node, the directory entry * and the flag to indicate if it is a root node. - * + * * @param parentNode The parent node. * @param entry The directory entry. * @param entryIsRootNode If this folder is root folder. @@ -161,7 +162,7 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi /** * Returns the children outside of TCF thread. - * + * * @return The children list. */ @SuppressWarnings("unchecked") @@ -203,7 +204,7 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi /** * If this node has OS information. - * + * * @return true if it has. */ private boolean hasOSInfo() { @@ -395,7 +396,7 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi /** * Encode each segment of the path to a URI compatible name, * and get the URI encoded path. - * + * * @return The encoded path which is URI compatible. */ private String getEncodedURIPath() { @@ -549,7 +550,7 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi /** * Set the file's attributes and trigger property change event. - * + * * @param attrs The new attributes. */ public void setAttributes(FileAttrs attrs) { @@ -578,7 +579,7 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi /** * Set the file's new name and trigger property change event. - * + * * @param name The new name. */ public void setName(String name) { @@ -619,18 +620,18 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi return new QueryDoneOpenChannel(this, callback); } - /** - * Override the queryChildren to refresh the second level children upon expanding. - */ - @Override - public void queryChildren() { - queryChildren(new Callback(){ - @Override - protected void internalDone(Object caller, IStatus status) { - refreshChildren(); - } - }); - } +// /** +// * Override the queryChildren to refresh the second level children upon expanding. +// */ +// @Override +// public void queryChildren() { +// queryChildren(new Callback(){ +// @Override +// protected void internalDone(Object caller, IStatus status) { +// refreshChildren(); +// } +// }); +// } /* * (non-Javadoc) @@ -646,16 +647,16 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi * @see org.eclipse.tcf.te.tcf.filesystem.core.model.AbstractTreeNode#refreshChildren() */ @Override - public void refreshChildren() { + public void refreshChildren(ICallback callback) { List children = getChildren(); if(!children.isEmpty()) { - ICallback callback = new Callback(){ + ICallback proxy = new Callback(callback){ @Override protected void internalDone(Object caller, IStatus status) { queryDone(); } }; - final CallbackMonitor monitor = new CallbackMonitor(callback); + final CallbackMonitor monitor = new CallbackMonitor(proxy); for(FSTreeNode child : children) { if((child.isRoot() || child.isDirectory()) && !child.childrenQueried && !child.childrenQueryRunning) { monitor.lock(child.uniqueId); @@ -673,5 +674,8 @@ public final class FSTreeNode extends AbstractTreeNode implements Cloneable, IFi } } } + else { + callback.done(this, Status.OK_STATUS); + } } } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/dialogs/FSFolderSelectionDialog.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/dialogs/FSFolderSelectionDialog.java index 74b68f8ff..753e3bf31 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/dialogs/FSFolderSelectionDialog.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/dialogs/FSFolderSelectionDialog.java @@ -26,7 +26,6 @@ import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; @@ -112,20 +111,9 @@ public class FSFolderSelectionDialog extends ElementTreeSelectionDialog { this.addFilter(new DirectoryFilter()); this.setStatusLineAboveButtons(false); this.setValidator(new ISelectionStatusValidator() { - @Override public IStatus validate(final Object[] selection) { - getShell().getDisplay().asyncExec(new Runnable() { - @SuppressWarnings("synthetic-access") - @Override - public void run() { - IStatus status = isValidFolder(selection); - if (getTreeViewer().getSelection().equals(new StructuredSelection(selection))) { - updateStatus(status); - } - } - }); - return new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), Messages.FSFolderSelectionDialog_validate_message); + return isValidFolder(selection); } }); } @@ -254,29 +242,17 @@ public class FSFolderSelectionDialog extends ElementTreeSelectionDialog { } protected void refreshNode(final FSTreeNode treeNode) { - treeNode.refresh(new Callback() { - @Override - protected void internalDone(Object caller, IStatus status) { - getShell().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - getTreeViewer().refresh(treeNode, true); - } - }); - } - }); - } - - protected void refreshModel() { - Object input = getTreeViewer().getInput(); - if (input instanceof IPeerNode) { - ModelManager.getRuntimeModel((IPeerNode)input).getRoot().refresh(new Callback() { + if (!treeNode.childrenQueryRunning) { + treeNode.childrenQueried = false; + treeNode.clearChildren(); + treeNode.refresh(new Callback() { @Override - protected void internalDone(Object caller, IStatus status) { + protected void internalDone(Object caller, IStatus status) { getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { - getTreeViewer().refresh(true); + getTreeViewer().refresh(treeNode, true); + getTreeViewer().setSelection(getTreeViewer().getSelection()); } }); } @@ -284,6 +260,13 @@ public class FSFolderSelectionDialog extends ElementTreeSelectionDialog { } } + protected void refreshModel() { + Object input = getTreeViewer().getInput(); + if (input instanceof IPeerNode) { + refreshNode(ModelManager.getRuntimeModel((IPeerNode)input).getRoot()); + } + } + /** * If the specified selection is a valid folder to be selected. @@ -309,6 +292,9 @@ public class FSFolderSelectionDialog extends ElementTreeSelectionDialog { } } if(!target.isWritable()) { + if (target.attr == null) { + refreshNode(target); + } return error; } return new Status(IStatus.OK, pluginId, null); -- cgit v1.2.3