Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/FSTreeNode.java')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/FSTreeNode.java637
1 files changed, 637 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/FSTreeNode.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/FSTreeNode.java
new file mode 100644
index 000000000..62310a511
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/FSTreeNode.java
@@ -0,0 +1,637 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2015 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
+ * William Chen (Wind River) - [345384] Provide property pages for remote file system nodes
+ * William Chen (Wind River) - [352302]Opening a file in an editor depending on
+ * the client's permissions.
+ *******************************************************************************/
+package org.eclipse.tcf.te.tcf.filesystem.core.internal;
+
+import static java.util.Collections.singletonList;
+
+import java.beans.PropertyChangeEvent;
+import java.io.File;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.IFileSystem;
+import org.eclipse.tcf.services.IFileSystem.FileAttrs;
+import org.eclipse.tcf.te.core.interfaces.IFilterable;
+import org.eclipse.tcf.te.core.interfaces.IPropertyChangeProvider;
+import org.eclipse.tcf.te.core.interfaces.IViewerInput;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IResultOperation;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IFSTreeNode;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IFSTreeNodeWorkingCopy;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCopy;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreateFile;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreateFolder;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpDelete;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpDownload;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpMove;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefresh;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRename;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.testers.TargetPropertyTester;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.url.TcfURLConnection;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.url.TcfURLStreamHandlerService;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.ContentTypeHelper;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.FileState;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.PersistenceManager;
+import org.eclipse.tcf.te.tcf.filesystem.core.model.CacheState;
+import org.eclipse.tcf.te.tcf.filesystem.core.model.RuntimeModel;
+import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode;
+
+/**
+ * Representation of a file system tree node.
+ * <p>
+ * <b>Note:</b> Node construction and child list access is limited to the TCF
+ * event dispatch thread.
+ */
+@SuppressWarnings("deprecation")
+public final class FSTreeNode extends FSTreeNodeBase implements IFilterable, IFSTreeNode, org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode {
+ private static final QualifiedName EDITOR_KEY = new QualifiedName("org.eclipse.ui.internal.registry.ResourceEditorRegistry", "EditorProperty");//$NON-NLS-2$//$NON-NLS-1$
+ static final String KEY_WIN32_ATTRS = "Win32Attrs"; //$NON-NLS-1$
+ private static final Comparator<FSTreeNode> CMP_WIN = new Comparator<FSTreeNode>() {
+ @Override
+ public int compare(FSTreeNode o1, FSTreeNode o2) {
+ return o1.getName().compareToIgnoreCase(o2.getName());
+ }
+ };
+ private static final Comparator<FSTreeNode> CMP_UNIX = new Comparator<FSTreeNode>() {
+ @Override
+ public int compare(FSTreeNode o1, FSTreeNode o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ };
+
+
+ private FSTreeNode fParent;
+ private String fName;
+
+ private Type fType;
+ private IFileSystem.FileAttrs fAttributes;
+
+ private FSTreeNode[] fChildren = null;
+
+ private final RuntimeModel fRuntimeModel;
+ private final boolean fWindowsNode;
+ private long fRefreshTime;
+
+
+ public FSTreeNode(RuntimeModel runtimeModel, String name) {
+ fRuntimeModel = runtimeModel;
+ fParent = null;
+ fName = name;
+ fAttributes = null;
+ fType = Type.FILE_SYSTEM;
+ fWindowsNode = isWindowsNode(getPeerNode());
+ Assert.isTrue(Protocol.isDispatchThread());
+ }
+
+ private boolean isWindowsNode(IPeerNode peerNode) {
+ String osname = TargetPropertyTester.getOSName(peerNode);
+ if (osname != null){
+ return osname.startsWith("Windows"); //$NON-NLS-1$
+ }
+ return false;
+ }
+
+ public FSTreeNode(FSTreeNode parent, String name, boolean isRootDir, IFileSystem.FileAttrs attribs) {
+ fRuntimeModel = parent.getRuntimeModel();
+ fWindowsNode = parent.isWindowsNode() || (isRootDir && name.endsWith("\\")); //$NON-NLS-1$
+ fParent = parent;
+ fName = name;
+ fAttributes = attribs;
+ if (isRootDir) {
+ fType = Type.ROOT;
+ } else {
+ fType = Type.DIRECTORY_OR_FILE;
+ }
+ Assert.isTrue(Protocol.isDispatchThread());
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + ": name=" + fName; //$NON-NLS-1$
+ }
+
+ @Override
+ public Object getAdapter(Class adapter) {
+ if(IViewerInput.class.equals(adapter)) {
+ return getPeerNode().getAdapter(IViewerInput.class);
+ }
+ if(IPropertyChangeProvider.class.equals(adapter)) {
+ return getPeerNode().getAdapter(adapter);
+ }
+ return super.getAdapter(adapter);
+ }
+
+ @Override
+ public RuntimeModel getRuntimeModel() {
+ return fRuntimeModel;
+ }
+
+ @Override
+ public IPeerNode getPeerNode() {
+ return fRuntimeModel.getPeerNode();
+ }
+
+ @Override
+ public UserAccount getUserAccount() {
+ return fRuntimeModel.getUserAccount();
+ }
+
+ @Override
+ public Type getType() {
+ return fType;
+ }
+
+ @Override
+ public boolean isWindowsNode() {
+ return fWindowsNode;
+ }
+
+ @Override
+ public boolean isFile() {
+ return fAttributes != null && fAttributes.isFile();
+ }
+
+ @Override
+ public boolean isDirectory() {
+ switch(fType) {
+ case FILE_SYSTEM:
+ return false;
+ case ROOT:
+ return true;
+ case DIRECTORY_OR_FILE:
+ return fAttributes == null || fAttributes.isDirectory();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isRootDirectory() {
+ return fType == Type.ROOT;
+ }
+
+ public FileAttrs getAttributes() {
+ return fAttributes;
+ }
+
+ @Override
+ protected int getWin32Attrs() {
+ final FileAttrs attribs = fAttributes;
+ if (attribs != null && attribs.attributes != null) {
+ Object val = attribs.attributes.get(KEY_WIN32_ATTRS);
+ if (val instanceof Integer) {
+ return ((Integer) val).intValue();
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ protected int getPermissions() {
+ final FileAttrs attribs = fAttributes;
+ if (attribs != null) {
+ return attribs.permissions;
+ }
+ return 0;
+ }
+
+ @Override
+ public String getLocation() {
+ return getLocation(false);
+ }
+
+ public String getLocation(boolean forceSlashes) {
+ return getLocation(isWindowsNode() && !forceSlashes ? '\\' : '/', false);
+ }
+
+ private String getLocation(char separator, boolean encodeName) {
+ String name = getName();
+ if (fType == Type.ROOT) {
+ if (isWindowsNode() && name.charAt(name.length()-1) != separator) {
+ return name.substring(0, name.length()-1) + separator;
+ }
+ return name;
+ }
+ if (fParent == null)
+ return name;
+
+
+ String pLoc = fParent.getLocation(separator, encodeName);
+ if (pLoc.length() == 0)
+ return name;
+
+ if (encodeName) {
+ try {
+ name = URLEncoder.encode(getName(), "UTF-8"); //$NON-NLS-1$
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ char lastChar = pLoc.charAt(pLoc.length()-1);
+ if (lastChar != separator)
+ return pLoc + separator + name;
+
+ return pLoc + name;
+ }
+
+ /**
+ * Get the URL of the file or folder. The URL's format is created in the
+ * following way: tcf:/<TCF_AGENT_ID>/remote/path/to/the/resource... See
+ * {@link TcfURLConnection#TcfURLConnection(URL)}
+ *
+ * @see TcfURLStreamHandlerService#parseURL(URL, String, int, int)
+ * @see #getLocationURI()
+ * @return The URL of the file/folder.
+ */
+ @Override
+ public URL getLocationURL() {
+ try {
+ String id = getPeerNode().getPeerId();
+ String path = getLocation(true);
+ String location = TcfURLConnection.PROTOCOL_SCHEMA + ":/" + id + (path.startsWith("/") ? path : "/" + path); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return new URL(location);
+ } catch (MalformedURLException e) {
+ assert false;
+ return null;
+ }
+ }
+
+ /**
+ * Get the URI of the file or folder. The URI's format is created in the
+ * following way: tcf:/<TCF_AGENT_ID>/remote/path/to/the/resource...
+ *
+ * @return The URI of the file/folder.
+ */
+ @Override
+ public URI getLocationURI() {
+ try {
+ String id = getPeerNode().getPeerId();
+ String path = getLocation('/', true);
+ String location = TcfURLConnection.PROTOCOL_SCHEMA + ":/" + id + (path.startsWith("/") ? path : "/" + path); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return new URI(location);
+ }
+ catch (URISyntaxException e) {
+ assert false;
+ return null;
+ }
+ }
+
+ /**
+ * Get the type label of the file for displaying purpose.
+ *
+ * @return The type label text.
+ */
+ @Override
+ public String getFileTypeLabel() {
+ switch (fType) {
+ case FILE_SYSTEM:
+ return Messages.FSTreeNodeContentProvider_rootNodeLabel;
+ case ROOT:
+ return Messages.FSTreeNode_TypeLocalDisk;
+ case DIRECTORY_OR_FILE:
+ break;
+ }
+
+ if (isDirectory())
+ return Messages.FSTreeNode_TypeFileFolder;
+
+ if (isSystemFile()) {
+ return Messages.FSTreeNode_TypeSystemFile;
+ }
+ IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(getName());
+ if (contentType != null) {
+ return contentType.getName();
+ }
+ int lastDot = getName().lastIndexOf("."); //$NON-NLS-1$
+ if (lastDot == -1) {
+ return Messages.FSTreeNode_TypeUnknownFile;
+ }
+ return getName().substring(lastDot + 1).toUpperCase() + " " + Messages.FSTreeNode_TypeFile; //$NON-NLS-1$
+ }
+
+
+ /**
+ * Get the local file's state of the specified tree node. The local file must exist
+ * before calling this method to get its state.
+ *
+ * @return The tree node's latest cache state.
+ */
+ @Override
+ public CacheState getCacheState() {
+ File file = CacheManager.getCacheFile(this);
+ if (!file.exists()) {
+ return CacheState.consistent;
+ }
+ FileState digest = PersistenceManager.getInstance().getFileDigest(this);
+ return digest.getCacheState();
+ }
+
+ @Override
+ public FSTreeNode getParent() {
+ return fParent;
+ }
+
+ @Override
+ public String getName() {
+ return fName;
+ }
+
+ @Override
+ public IFSTreeNodeWorkingCopy createWorkingCopy() {
+ return new FSTreeNodeWorkingCopy(this);
+ }
+
+ @Override
+ public boolean isFileSystem() {
+ return fType == Type.FILE_SYSTEM;
+ }
+
+ @Override
+ public long getAccessTime() {
+ if (fAttributes != null)
+ return fAttributes.atime;
+ return 0;
+ }
+
+ @Override
+ public long getModificationTime() {
+ if (fAttributes != null)
+ return fAttributes.mtime;
+ return 0;
+ }
+
+ @Override
+ public long getSize() {
+ if (fAttributes != null)
+ return fAttributes.size;
+ return 0;
+ }
+
+ @Override
+ public int getUID() {
+ if (fAttributes != null)
+ return fAttributes.uid;
+ return 0;
+ }
+
+ @Override
+ public int getGID() {
+ if (fAttributes != null)
+ return fAttributes.gid;
+ return 0;
+ }
+
+ @Override
+ public boolean isAncestorOf(IFSTreeNode node) {
+ while (node != null) {
+ if ((node = node.getParent()) == this)
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public File getCacheFile() {
+ return CacheManager.getCacheFile(this);
+ }
+
+ @Override
+ public String getPreferredEditorID() {
+ return PersistenceManager.getInstance().getPersistentProperties(this).get(EDITOR_KEY);
+ }
+
+ @Override
+ public void setPreferredEditorID(String editorID) {
+ PersistenceManager.getInstance().getPersistentProperties(this).put(EDITOR_KEY, editorID);
+ }
+
+ @Override
+ public IContentType getContentType() {
+ return ContentTypeHelper.getContentType(this);
+ }
+
+ @Override
+ public boolean isBinaryFile() {
+ return ContentTypeHelper.isBinaryFile(this);
+ }
+
+ @Override
+ public FSTreeNode[] getChildren() {
+ return fChildren;
+ }
+
+ @Override
+ public IOperation operationRefresh(boolean recursive) {
+ return new OpRefresh(this, recursive);
+ }
+
+
+ @Override
+ public IOperation operationRename(String newName) {
+ return new OpRename(this, newName);
+ }
+
+ @Override
+ public IOperation operationUploadContent(File srcFile) {
+ if (srcFile == null)
+ srcFile = getCacheFile();
+
+ OpUpload upload = new OpUpload(null);
+ upload.addUpload(srcFile, this);
+ return upload;
+ }
+
+ @Override
+ public IOperation operationDelete(IConfirmCallback readonlyCallback) {
+ return new OpDelete(singletonList(this), readonlyCallback);
+ }
+
+ @Override
+ public IOperation operationDownload(OutputStream output) {
+ return new OpDownload(this, output);
+ }
+
+ @Override
+ public IOperation operationDropFiles(List<String> files, IConfirmCallback confirmCallback) {
+ OpUpload upload = new OpUpload(confirmCallback);
+ for (String file : files) {
+ upload.addDrop(new File(file), this);
+ }
+ return upload;
+ }
+
+ @Override
+ public IOperation operationDropMove(List<IFSTreeNode> nodes, IConfirmCallback confirmCallback) {
+ return new OpMove(nodes, this, confirmCallback);
+ }
+
+ @Override
+ public IOperation operationDropCopy(List<IFSTreeNode> nodes, boolean cpPerm, boolean cpOwn,
+ IConfirmCallback moveCopyCallback) {
+ return new OpCopy(nodes, this, cpPerm, cpOwn, moveCopyCallback);
+ }
+
+ @Override
+ public IResultOperation<IFSTreeNode> operationNewFile(String name) {
+ return new OpCreateFile(this, name);
+ }
+
+ @Override
+ public IResultOperation<IFSTreeNode> operationNewFolder(String name) {
+ return new OpCreateFolder(this, name);
+ }
+
+ public void changeParent(FSTreeNode newParent) {
+ fParent = newParent;
+ }
+
+ public void changeName(String newName) {
+ fName = newName;
+ }
+
+ public FSTreeNode findChild(String name) {
+ return binarySearch(fChildren, name);
+ }
+
+ public void addNode(FSTreeNode newNode, boolean notify) {
+ final FSTreeNode[] children = fChildren;
+ if (children == null) {
+ setChildren(new FSTreeNode[] {newNode}, notify);
+ } else {
+ int ip = Arrays.binarySearch(children, newNode, getComparator());
+ if (ip >= 0) {
+ children[ip] = newNode;
+ } else {
+ ip = -ip - 1;
+ FSTreeNode[] newChildren = new FSTreeNode[children.length+1];
+ System.arraycopy(children, 0, newChildren, 0, ip);
+ newChildren[ip] = newNode;
+ System.arraycopy(children, ip, newChildren, ip+1, children.length-ip);
+ setChildren(newChildren, notify);
+ }
+ }
+ }
+
+ public void removeNode(FSTreeNode node, boolean notify) {
+ final FSTreeNode[] children = fChildren;
+ if (children == null)
+ return;
+
+ int ip = Arrays.binarySearch(children, node, getComparator());
+ if (ip < 0 || children[ip] != node)
+ return;
+
+ FSTreeNode[] newChildren = new FSTreeNode[children.length-1];
+ System.arraycopy(children, 0, newChildren, 0, ip);
+ System.arraycopy(children, ip+1, newChildren, ip, children.length-ip-1);
+ setChildren(newChildren, notify);
+ }
+
+ public void setContent(FSTreeNode[] children, boolean notify) {
+ final Comparator<FSTreeNode> comparator = getComparator();
+ Arrays.sort(children, comparator);
+ if (fChildren != null) {
+ int j = 0;
+ for (int i=0; i<children.length; i++) {
+ FSTreeNode node = children[i];
+ for (; j<fChildren.length; j++) {
+ FSTreeNode old = fChildren[j];
+ int cmp = comparator.compare(old, node);
+ if (cmp == 0) {
+ old.setAttributes(node.fAttributes, false);
+ children[i] = old;
+ j++;
+ break;
+ } else if (cmp > 0) {
+ break;
+ }
+ }
+ }
+ }
+ fRefreshTime = System.currentTimeMillis();
+ setChildren(children, notify);
+ }
+
+ private Comparator<FSTreeNode> getComparator() {
+ return isWindowsNode() ? CMP_WIN : CMP_UNIX;
+ }
+
+ private void setChildren(FSTreeNode[] children, boolean notify) {
+ Assert.isTrue(Protocol.isDispatchThread());
+ FSTreeNode[] oldChildren = fChildren;
+ fChildren = children;
+ if (notify) {
+ notifyChange("children", oldChildren, children); //$NON-NLS-1$
+ }
+ }
+
+ public void setAttributes(FileAttrs attrs, boolean notify) {
+ FileAttrs oldAttrs = fAttributes;
+ fAttributes = attrs;
+ if (attrs.isFile())
+ fRefreshTime = System.currentTimeMillis();
+ if (notify) {
+ notifyChange("attributes", oldAttrs, attrs); //$NON-NLS-1$
+ }
+ }
+
+ public void notifyChange() {
+ notifyChange("children", null, null); //$NON-NLS-1$
+ }
+
+ private void notifyChange(String prop, Object oldValue, Object newValue) {
+ fRuntimeModel.firePropertyChanged(new PropertyChangeEvent(this, prop, oldValue, newValue));
+ }
+
+ @Override
+ public long getLastRefresh() {
+ return fRefreshTime;
+ }
+
+ private FSTreeNode binarySearch(final FSTreeNode[] children, String name) {
+ if (children == null)
+ return null;
+
+ boolean caseSensitive = !isWindowsNode();
+ int low = 0;
+ int high = children.length - 1;
+
+ while (low <= high) {
+ int mid = (low + high) >>> 1;
+ FSTreeNode midVal = children[mid];
+ int cmp = caseSensitive ? midVal.getName().compareTo(name) : midVal.getName().compareToIgnoreCase(name);
+ if (cmp < 0)
+ low = mid + 1;
+ else if (cmp > 0)
+ high = mid - 1;
+ else
+ return midVal;
+ }
+ return null;
+ }
+}

Back to the top