/******************************************************************************* * Copyright (c) 2011 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.tm.te.tcf.filesystem.model; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IFileSystem; import org.eclipse.tm.te.tcf.filesystem.interfaces.IWindowsFileAttributes; import org.eclipse.tm.te.tcf.filesystem.internal.UserAccount; import org.eclipse.tm.te.tcf.filesystem.internal.handlers.UserManager; import org.eclipse.tm.te.tcf.filesystem.internal.url.TcfURLConnection; import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; /** * 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. */ public final class FSTreeNode extends PlatformObject implements Cloneable{ private static final String KEY_WIN32_ATTRS = "Win32Attrs"; //$NON-NLS-1$ private final UUID uniqueId = UUID.randomUUID(); /** * The tree node name. */ public String name = null; /** * The tree node type. */ public String type = null; /** * The tree node file system attributes */ public IFileSystem.FileAttrs attr = null; /** * The peer node the file system tree node is associated with. */ public IPeerModel peerNode = null; /** * The tree node parent. */ public FSTreeNode parent = null; /** * The tree node children. */ private List<FSTreeNode> children; /** * Flag to mark once the children of the node got queried */ public boolean childrenQueried = false; /** * Flag to mark once the children query is running */ public boolean childrenQueryRunning = false; /** * Constructor. */ public FSTreeNode() { super(); children = Collections.synchronizedList(new ArrayList<FSTreeNode>()); Assert.isTrue(Protocol.isDispatchThread()); } /* * (non-Javadoc) * @see java.lang.Object#clone() */ @Override public Object clone() { FSTreeNode clone; try { clone = (FSTreeNode) super.clone(); } catch (CloneNotSupportedException e) { clone = new FSTreeNode(); clone.children = children; clone.childrenQueried = childrenQueried; clone.childrenQueryRunning = childrenQueryRunning; clone.name = name; clone.parent = parent; clone.peerNode = peerNode; clone.type = type; } Map<String, Object> attributes = new HashMap<String, Object>(attr.attributes); clone.attr = new IFileSystem.FileAttrs(attr.flags, attr.size, attr.uid, attr.gid, attr.permissions, attr.atime, attr.mtime, attributes); return clone; } /** * Set the file's permissions. * @param permissions The new permissions. */ public void setPermissions(int permissions) { attr = new IFileSystem.FileAttrs(attr.flags, attr.size, attr.uid, attr.gid, permissions, attr.atime, attr.mtime, attr.attributes); } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public final int hashCode() { return uniqueId.hashCode(); } /** * Returns the children list storage object. * <p> * <b>Note:</b> This method must be called from within the TCF event * dispatch thread only! * * @return The children list storage object. */ public final List<FSTreeNode> getChildren() { Assert.isTrue(Protocol.isDispatchThread()); return children; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public final boolean equals(Object obj) { if(this == obj) return true; if (obj instanceof FSTreeNode) { return uniqueId.equals(((FSTreeNode) obj).uniqueId); } return super.equals(obj); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder buffer = new StringBuilder(getClass().getSimpleName()); buffer.append(": name=" + (name != null ? name : super.toString())); //$NON-NLS-1$ buffer.append(", UUID=" + uniqueId.toString()); //$NON-NLS-1$ return buffer.toString(); } /** * Return if the node is a Windows file/folder node. * * @return true if it is a Windows node, or else false. */ public boolean isWindowsNode() { return attr != null && attr.attributes != null && attr.attributes.containsKey(KEY_WIN32_ATTRS); } /** * Return if the node is a file. * * @return true if it is a file, or else false. */ public boolean isFile() { return attr != null && attr.isFile(); } /** * Return if the node is a directory. * * @return true if it is a directory, or else false. */ public boolean isDirectory() { return attr != null && attr.isDirectory(); } /** * Return if the attribute specified by the mask bit is turned on. * * @param bit * The attribute's mask bit. * @return true if it is on, or else false. */ public boolean isWin32AttrOn(int bit) { if (attr != null && attr.attributes.get(KEY_WIN32_ATTRS) instanceof Integer) { Integer win32Attrs = (Integer) attr.attributes.get(KEY_WIN32_ATTRS); return (win32Attrs.intValue() & bit) != 0; } return false; } /** * Set the attribute specified by the mask bit to on or off. * @param bit The attribute's mask bit. * @param on The flag if the bit should be turned on or off. */ public void setWin32Attr(int bit, boolean on) { if (attr != null && attr.attributes.get(KEY_WIN32_ATTRS) instanceof Integer) { int win32attr = ((Integer) attr.attributes.get(KEY_WIN32_ATTRS)).intValue(); win32attr = on ? (win32attr | bit) : (win32attr & ~bit); attr.attributes.put(KEY_WIN32_ATTRS, Integer.valueOf(win32attr)); } } /** * Get the file's win32 attributes. * @return The file's win32 attributes. */ public int getWin32Attrs() { if (attr != null && attr.attributes.get(KEY_WIN32_ATTRS) instanceof Integer) { return ((Integer) attr.attributes.get(KEY_WIN32_ATTRS)).intValue(); } return 0; } /** * Return if this file/folder is hidden. * * @return true if it is hidden, or else false. */ public boolean isHidden() { return isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_HIDDEN); } /** * Set the file/folder hidden attribute's value. * @param hidden The new value. */ public void setHidden(boolean hidden) { setWin32Attr(IWindowsFileAttributes.FILE_ATTRIBUTE_HIDDEN, hidden); } /** * Return if this file/folder is read-only. * * @return true if it is read-only, or else false. */ public boolean isReadOnly() { return isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_READONLY); } /** * Set the file/folder read-only attribute's value. * @param readOnly The new value. */ public void setReadOnly(boolean readOnly) { setWin32Attr(IWindowsFileAttributes.FILE_ATTRIBUTE_READONLY, readOnly); } /** * Get the location of a file/folder node using the format of the file * system's platform. * * @param node * The file/folder node. * @return The location of the file/folder. */ public String getLocation() { if (parent == null) return null; String location = parent.getLocation(false); if (parent.isRoot()) { return location + (isWindowsNode() ? "\\" : "/"); //$NON-NLS-1$ //$NON-NLS-2$ } return location; } /** * Get the location of a file/folder. * * @param cross * If the format is cross-platform. * @return The path to the file/folder. */ public String getLocation(boolean cross) { if (parent == null) return null; String pLoc = parent.getLocation(cross); if (pLoc == null) { return name.substring(0, name.length() - 1); } String pathSep = (!cross && isWindowsNode()) ? "\\" : "/"; //$NON-NLS-1$ //$NON-NLS-2$ return pLoc + pathSep + 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)} * * @return The URL of the file/folder. * @throws MalformedURLException */ public URL getLocationURL() { try { String id = peerNode.getPeer().getID(); String path = getLocation(true); String location = TcfURLConnection.PROTOCOL_SCHEMA + ":/" + id + (isWindowsNode() ? "/" + path : path); //$NON-NLS-1$ //$NON-NLS-2$ return new URL(location); } catch (MalformedURLException e) { assert false; return null; } } /** * If this node is a root node. * * @return true if this node is a root node. */ public boolean isRoot() { return type.endsWith("FSRootDirNode"); //$NON-NLS-1$ } /** * If this file is readable. * * @return true if it is readable. */ public boolean isReadable() { UserAccount account = UserManager.getInstance().getUserAccount(peerNode); if (account != null && attr != null) { if (attr.uid == account.getEUID()) { return (attr.permissions & IFileSystem.S_IRUSR) != 0; } else if (attr.gid == account.getEGID()) { return (attr.permissions & IFileSystem.S_IRGRP) != 0; } else { return (attr.permissions & IFileSystem.S_IROTH) != 0; } } return false; } /** * If this file is writable. * * @return true if it is writable. */ public boolean isWritable() { UserAccount account = UserManager.getInstance().getUserAccount(peerNode); if (account != null && attr != null) { if (attr.uid == account.getEUID()) { return (attr.permissions & IFileSystem.S_IWUSR) != 0; } else if (attr.gid == account.getEGID()) { return (attr.permissions & IFileSystem.S_IWGRP) != 0; } else { return (attr.permissions & IFileSystem.S_IWOTH) != 0; } } return false; } /** * If this file is executable. * * @return true if it is executable. */ public boolean isExecutable() { UserAccount account = UserManager.getInstance().getUserAccount(peerNode); if (account != null && attr != null) { if (attr.uid == account.getEUID()) { return (attr.permissions & IFileSystem.S_IXUSR) != 0; } else if (attr.gid == account.getEGID()) { return (attr.permissions & IFileSystem.S_IXGRP) != 0; } else { return (attr.permissions & IFileSystem.S_IXOTH) != 0; } } return false; } }