From 4488f6ff378feaa19364b16425dc646e24d0fd00 Mon Sep 17 00:00:00 2001 From: Martin Oberhuber Date: Sun, 31 May 2015 02:12:30 +0200 Subject: [PATCH] Bug 468889 - Support Eclipse older than Mars (tested on Kepler) Change-Id: I660efe3602e74c3d724707d597a620eda286589c Signed-off-by: Martin Oberhuber --- .../META-INF/MANIFEST.MF | 9 +- .../remote/core/RemoteServicesUtils.java | 34 +- .../remote/internal/core/RemotePath.java | 1211 +++++++++++++++++ .../META-INF/MANIFEST.MF | 4 +- .../internal/jsch/core/JSchConnection.java | 5 +- .../internal/jsch/core/JSchFileManager.java | 11 +- .../internal/jsch/core/JschFileStore.java | 7 +- .../core/commands/AbstractRemoteCommand.java | 8 +- .../META-INF/MANIFEST.MF | 4 +- .../META-INF/MANIFEST.MF | 4 +- .../widgets/RemoteResourceBrowserWidget.java | 13 +- .../META-INF/MANIFEST.MF | 2 +- .../org.eclipse.remote.jsch.tests/.classpath | 2 +- .../.settings/org.eclipse.jdt.core.prefs | 6 +- .../META-INF/MANIFEST.MF | 4 +- 15 files changed, 1286 insertions(+), 38 deletions(-) create mode 100644 bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemotePath.java diff --git a/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF index 0dacec9ee70..9b672162cb7 100644 --- a/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF @@ -5,12 +5,11 @@ Bundle-SymbolicName: org.eclipse.remote.core;singleton:=true Bundle-Version: 2.0.0.qualifier Bundle-Activator: org.eclipse.remote.internal.core.RemoteCorePlugin Bundle-Vendor: %pluginProvider -Require-Bundle: org.eclipse.core.runtime;bundle-version="3.11.0", +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.9.100", org.eclipse.core.filesystem, org.eclipse.core.resources, org.eclipse.core.variables, - org.eclipse.debug.core, - org.eclipse.cdt.core.native;bundle-version="5.8.0" + org.eclipse.debug.core Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.remote.core, org.eclipse.remote.core.exception, @@ -19,4 +18,6 @@ Export-Package: org.eclipse.remote.core, org.eclipse.remote.internal.core.preferences;x-friends:="org.eclipse.remote.ui" Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Import-Package: org.eclipse.equinox.security.storage +Import-Package: org.eclipse.equinox.security.storage, + org.eclipse.cdt.utils.pty, + org.eclipse.cdt.utils.spawner diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/RemoteServicesUtils.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/RemoteServicesUtils.java index efe3a8fabbe..84138f0f504 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/RemoteServicesUtils.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/RemoteServicesUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 IBM Corporation and others. + * Copyright (c) 2013, 2015 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - Initial API and implementation + * Martin Oberhuber - [468889] Support Eclipse older than Mars *******************************************************************************/ package org.eclipse.remote.core; @@ -14,13 +15,44 @@ import java.net.URI; import java.net.URISyntaxException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.remote.internal.core.RemoteCorePlugin; +import org.eclipse.remote.internal.core.RemotePath; import org.eclipse.remote.internal.core.preferences.Preferences; /** * Remote services utility methods. */ public class RemoteServicesUtils { + /** + * Constructs a new POSIX path from the given string path. The string path + * must represent a valid file system path on a POSIX file system. The path + * is canonicalized and double slashes are removed except at the beginning + * (to handle UNC paths). All forward slashes ('/') are treated as segment + * delimiters. This factory method should be used if the string path is for + * a POSIX file system. + * + * @param path the string path + * @see org.eclipse.core.runtime.Path#forPosix(String) + * @since 2.0 + */ + public static IPath posixPath(String path) { + try { + //Use the Mars implementation of Path, see bug 454959 + return Path.forPosix(path); + } catch(NoSuchMethodError e) { + //TODO For older Eclipse, use the fallback below. That code should be + //removed when support for Eclipse older than Mars is no longer needed. + } + /** Constant value indicating if the current platform is Windows */ + boolean RUNNING_ON_WINDOWS = java.io.File.separatorChar == '\\'; + if (! RUNNING_ON_WINDOWS) { + return new Path(path); + } else { + return new RemotePath(path); + } + } + /** * Convert a UNC path to a URI * diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemotePath.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemotePath.java new file mode 100644 index 00000000000..822156d5cc1 --- /dev/null +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/RemotePath.java @@ -0,0 +1,1211 @@ +/******************************************************************************* + * Copyright (c) 2000, 2015 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Patrick Tasse - Add extra constructor to Path class (bug 454959) + * Martin Oberhuber - [468889] Copy from equinox.common/org.eclipse.core.runtime + *******************************************************************************/ +package org.eclipse.remote.internal.core; + +import java.io.File; +import java.util.Arrays; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; + +/** + * The Eclipse Mars implementation of org.eclipse.core.runtime.Path. + * + * Cloned from org.eclipse.equinox.common. This class should be removed when + * Eclipse older than Mars no longer needs to be supported. + * + * @see org.eclipse.core.runtime.Path + * @noextend This class is not intended to be subclassed by clients. + */ +public class RemotePath implements IPath, Cloneable { + /** masks for flag values */ + private static final int HAS_LEADING = 1; + private static final int IS_UNC = 2; + private static final int HAS_TRAILING = 4; + private static final int IS_FOR_WINDOWS = 8; + + private static final int ALL_SEPARATORS = HAS_LEADING | IS_UNC | HAS_TRAILING; + private static final int ALL_FLAGS = HAS_LEADING | IS_UNC | HAS_TRAILING | IS_FOR_WINDOWS; + + /** Constant value indicating if the current platform is Windows */ + private static final boolean RUNNING_ON_WINDOWS = java.io.File.separatorChar == '\\'; + + /** Constant empty string value. */ + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + /** Constant value indicating no segments */ + private static final String[] NO_SEGMENTS = new String[0]; + + /** Constant value containing the empty path with no device on the local file system. */ + public static final RemotePath EMPTY = new RemotePath(EMPTY_STRING); + + /** Mask for all bits that are involved in the hash code */ + private static final int HASH_MASK = ~(HAS_TRAILING | IS_FOR_WINDOWS); + + /** Constant root path string ("/"). */ + private static final String ROOT_STRING = "/"; //$NON-NLS-1$ + + /** Constant value containing the root path with no device on the local file system. */ + public static final RemotePath ROOT = new RemotePath(ROOT_STRING); + + /** The device id string. May be null if there is no device. */ + private String device = null; + + //Private implementation note: the segments array and flag bitmap + //are never modified, so that they can be shared between path instances + + /** The path segments */ + private String[] segments; + + /** flags indicating separators (has leading, is UNC, has trailing, is for Windows) */ + private int flags; + + /** + * Constructs a new path from the given string path. + * The string path must represent a valid file system path + * on the local file system. + * The path is canonicalized and double slashes are removed + * except at the beginning. (to handle UNC paths). All forward + * slashes ('/') are treated as segment delimiters, and any + * segment and device delimiters for the local file system are + * also respected. + * + * @param pathString the portable string path + * @see IPath#toPortableString() + * @since 3.1 + */ + public static IPath fromOSString(String pathString) { + return new RemotePath(pathString); + } + + /** + * Constructs a new path from the given path string. + * The path string must have been produced by a previous + * call to IPath.toPortableString. + * + * @param pathString the portable path string + * @see IPath#toPortableString() + * @since 3.1 + */ + public static IPath fromPortableString(String pathString) { + int firstMatch = pathString.indexOf(DEVICE_SEPARATOR) + 1; + //no extra work required if no device characters + if (firstMatch <= 0) + return new RemotePath().initialize(null, pathString, RUNNING_ON_WINDOWS); + //if we find a single colon, then the path has a device + String devicePart = null; + int pathLength = pathString.length(); + if (firstMatch == pathLength || pathString.charAt(firstMatch) != DEVICE_SEPARATOR) { + devicePart = pathString.substring(0, firstMatch); + pathString = pathString.substring(firstMatch, pathLength); + } + //optimize for no colon literals + if (pathString.indexOf(DEVICE_SEPARATOR) == -1) + return new RemotePath().initialize(devicePart, pathString, RUNNING_ON_WINDOWS); + //contract colon literals + char[] chars = pathString.toCharArray(); + int readOffset = 0, writeOffset = 0, length = chars.length; + while (readOffset < length) { + if (chars[readOffset] == DEVICE_SEPARATOR) + if (++readOffset >= length) + break; + chars[writeOffset++] = chars[readOffset++]; + } + return new RemotePath().initialize(devicePart, new String(chars, 0, writeOffset), RUNNING_ON_WINDOWS); + } + + /** + * Constructs a new POSIX path from the given string path. The string path + * must represent a valid file system path on a POSIX file system. The path + * is canonicalized and double slashes are removed except at the beginning + * (to handle UNC paths). All forward slashes ('/') are treated as segment + * delimiters. This factory method should be used if the string path is for + * a POSIX file system. + * + * @param fullPath the string path + * @see #isValidPosixPath(String) + * @since 3.7 + */ + public static RemotePath forPosix(String fullPath) { + return new RemotePath(fullPath, false); + } + + /** + * Constructs a new Windows path from the given string path. The string path + * must represent a valid file system path on the Windows file system. The + * path is canonicalized and double slashes are removed except at the + * beginning (to handle UNC paths). All forward slashes ('/') are treated as + * segment delimiters, and any segment ('\') and device (':') delimiters for + * the Windows file system are also respected. This factory method should be + * used if the string path is for the Windows file system. + * + * @param fullPath the string path + * @see #isValidWindowsPath(String) + * @since 3.7 + */ + public static RemotePath forWindows(String fullPath) { + return new RemotePath(fullPath, true); + } + + /* (Intentionally not included in javadoc) + * Private constructor. + */ + private RemotePath() { + // not allowed + } + + /** + * Constructs a new path from the given string path. + * The string path must represent a valid file system path + * on the local file system. + * The path is canonicalized and double slashes are removed + * except at the beginning. (to handle UNC paths). All forward + * slashes ('/') are treated as segment delimiters, and any + * segment and device delimiters for the local file system are + * also respected (such as colon (':') and backslash ('\') on some file systems). + * This constructor should be used if the string path if for the local file system. + * + * @param fullPath the string path + * @see #isValidPath(String) + */ + public RemotePath(String fullPath) { + this(fullPath, RUNNING_ON_WINDOWS); + } + + /** + * Constructs a new path from the given device id and string path. + * The given string path must be valid. + * The path is canonicalized and double slashes are removed except + * at the beginning (to handle UNC paths). All forward + * slashes ('/') are treated as segment delimiters, and any + * segment delimiters for the local file system are + * also respected (such as backslash ('\') on some file systems). + * + * @param device the device id + * @param path the string path + * @see #isValidPath(String) + * @see #setDevice(String) + */ + public RemotePath(String device, String path) { + if (RUNNING_ON_WINDOWS) { + //convert backslash to forward slash + path = path.indexOf('\\') == -1 ? path : path.replace('\\', SEPARATOR); + } + initialize(device, path, RUNNING_ON_WINDOWS); + } + + /** + * Constructs a new path from the given string path. The string path must + * represent a valid file system path on the specified file system. The path + * is canonicalized and double slashes are removed except at the beginning + * (to handle UNC paths). All forward slashes ('/') are treated as segment + * delimiters, and any segment and device delimiters for the specified file + * system are also respected (such as colon (':') and backslash ('\') on + * Windows). + * + * @param fullPath the string path + * @param forWindows true if the string path is for the Windows file system + * @since 3.7 + */ + private RemotePath(String fullPath, boolean forWindows) { + String devicePart = null; + if (forWindows) { + //convert backslash to forward slash + fullPath = fullPath.indexOf('\\') == -1 ? fullPath : fullPath.replace('\\', SEPARATOR); + //extract device + int i = fullPath.indexOf(DEVICE_SEPARATOR); + if (i != -1) { + //remove leading slash from device part to handle output of URL.getFile() + int start = fullPath.charAt(0) == SEPARATOR ? 1 : 0; + devicePart = fullPath.substring(start, i + 1); + fullPath = fullPath.substring(i + 1, fullPath.length()); + } + } + initialize(devicePart, fullPath, forWindows); + } + + /* (Intentionally not included in javadoc) + * Private constructor. + */ + private RemotePath(String device, String[] segments, int flags) { + // no segment validations are done for performance reasons + this.segments = segments; + this.device = device; + //hash code is cached in all but the bottom four bits of the flags field + this.flags = (computeHashCode() << 4) | (flags & ALL_FLAGS); + } + + /* (Intentionally not included in javadoc) + * @see IPath#addFileExtension + */ + @Override + public IPath addFileExtension(String extension) { + if (isRoot() || isEmpty() || hasTrailingSeparator()) + return this; + int len = segments.length; + String[] newSegments = new String[len]; + System.arraycopy(segments, 0, newSegments, 0, len - 1); + newSegments[len - 1] = segments[len - 1] + '.' + extension; + return new RemotePath(device, newSegments, flags); + } + + /* (Intentionally not included in javadoc) + * @see IPath#addTrailingSeparator + */ + @Override + public IPath addTrailingSeparator() { + if (hasTrailingSeparator() || isRoot()) { + return this; + } + //XXX workaround, see 1GIGQ9V + if (isEmpty()) { + return new RemotePath(device, segments, (flags & IS_FOR_WINDOWS) | HAS_LEADING); + } + return new RemotePath(device, segments, flags | HAS_TRAILING); + } + + /* (Intentionally not included in javadoc) + * @see IPath#append(IPath) + */ + @Override + public IPath append(IPath tail) { + //optimize some easy cases + if (tail == null || tail.segmentCount() == 0) + return this; + //these call chains look expensive, but in most cases they are no-ops + //the tail must be for the same platform as this instance + if (this.isEmpty() && ((flags & IS_FOR_WINDOWS) == 0) == tail.isValidSegment(":")) //$NON-NLS-1$ + return tail.setDevice(device).makeRelative().makeUNC(isUNC()); + if (this.isRoot() && ((flags & IS_FOR_WINDOWS) == 0) == tail.isValidSegment(":")) //$NON-NLS-1$ + return tail.setDevice(device).makeAbsolute().makeUNC(isUNC()); + + //concatenate the two segment arrays + int myLen = segments.length; + int tailLen = tail.segmentCount(); + String[] newSegments = new String[myLen + tailLen]; + System.arraycopy(segments, 0, newSegments, 0, myLen); + for (int i = 0; i < tailLen; i++) { + newSegments[myLen + i] = tail.segment(i); + } + //use my leading separators and the tail's trailing separator + RemotePath result = new RemotePath(device, newSegments, (flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS)) | (tail.hasTrailingSeparator() ? HAS_TRAILING : 0)); + String tailFirstSegment = newSegments[myLen]; + if (tailFirstSegment.equals("..") || tailFirstSegment.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$ + result.canonicalize(); + } + return result; + } + + /* (Intentionally not included in javadoc) + * @see IPath#append(java.lang.String) + */ + @Override + public IPath append(String tail) { + //optimize addition of a single segment + if (tail.indexOf(SEPARATOR) == -1 && tail.indexOf("\\") == -1 && tail.indexOf(DEVICE_SEPARATOR) == -1) { //$NON-NLS-1$ + int tailLength = tail.length(); + if (tailLength < 3) { + //some special cases + if (tailLength == 0 || ".".equals(tail)) { //$NON-NLS-1$ + return this; + } + if ("..".equals(tail)) //$NON-NLS-1$ + return removeLastSegments(1); + } + //just add the segment + int myLen = segments.length; + String[] newSegments = new String[myLen + 1]; + System.arraycopy(segments, 0, newSegments, 0, myLen); + newSegments[myLen] = tail; + return new RemotePath(device, newSegments, flags & ~HAS_TRAILING); + } + //go with easy implementation + return append(new RemotePath(tail, (flags & IS_FOR_WINDOWS) != 0)); + } + + /** + * Destructively converts this path to its canonical form. + *

+ * In its canonical form, a path does not have any + * "." segments, and parent references ("..") are collapsed + * where possible. + *

+ * @return true if the path was modified, and false otherwise. + */ + private boolean canonicalize() { + //look for segments that need canonicalizing + for (int i = 0, max = segments.length; i < max; i++) { + String segment = segments[i]; + if (segment.charAt(0) == '.' && (segment.equals("..") || segment.equals("."))) { //$NON-NLS-1$ //$NON-NLS-2$ + //path needs to be canonicalized + collapseParentReferences(); + //paths of length 0 have no trailing separator + if (segments.length == 0) + flags &= (HAS_LEADING | IS_UNC); + //recompute hash because canonicalize affects hash + flags = (flags & ALL_FLAGS) | (computeHashCode() << 4); + return true; + } + } + return false; + } + + /* (Intentionally not included in javadoc) + * Clones this object. + */ + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + + /** + * Destructively removes all occurrences of ".." segments from this path. + */ + private void collapseParentReferences() { + int segmentCount = segments.length; + String[] stack = new String[segmentCount]; + int stackPointer = 0; + for (int i = 0; i < segmentCount; i++) { + String segment = segments[i]; + if (segment.equals("..")) { //$NON-NLS-1$ + if (stackPointer == 0) { + // if the stack is empty we are going out of our scope + // so we need to accumulate segments. But only if the original + // path is relative. If it is absolute then we can't go any higher than + // root so simply toss the .. references. + if (!isAbsolute()) + stack[stackPointer++] = segment; //stack push + } else { + // if the top is '..' then we are accumulating segments so don't pop + if ("..".equals(stack[stackPointer - 1])) //$NON-NLS-1$ + stack[stackPointer++] = ".."; //$NON-NLS-1$ + else + stackPointer--; + //stack pop + } + //collapse current references + } else if (!segment.equals(".") || segmentCount == 1) //$NON-NLS-1$ + stack[stackPointer++] = segment; //stack push + } + //if the number of segments hasn't changed, then no modification needed + if (stackPointer == segmentCount) + return; + //build the new segment array backwards by popping the stack + String[] newSegments = new String[stackPointer]; + System.arraycopy(stack, 0, newSegments, 0, stackPointer); + this.segments = newSegments; + } + + /** + * Removes duplicate slashes from the given path, with the exception + * of leading double slash which represents a UNC path. + */ + private String collapseSlashes(String path) { + int length = path.length(); + // if the path is only 0, 1 or 2 chars long then it could not possibly have illegal + // duplicate slashes. + if (length < 3) + return path; + // check for an occurrence of // in the path. Start at index 1 to ensure we skip leading UNC // + // If there are no // then there is nothing to collapse so just return. + if (path.indexOf("//", 1) == -1) //$NON-NLS-1$ + return path; + // We found an occurrence of // in the path so do the slow collapse. + char[] result = new char[path.length()]; + int count = 0; + boolean hasPrevious = false; + char[] characters = path.toCharArray(); + for (int index = 0; index < characters.length; index++) { + char c = characters[index]; + if (c == SEPARATOR) { + if (hasPrevious) { + // skip double slashes, except for beginning of UNC. + // note that a UNC path can't have a device. + if (device == null && index == 1) { + result[count] = c; + count++; + } + } else { + hasPrevious = true; + result[count] = c; + count++; + } + } else { + hasPrevious = false; + result[count] = c; + count++; + } + } + return new String(result, 0, count); + } + + /* (Intentionally not included in javadoc) + * Computes the hash code for this object. + */ + private int computeHashCode() { + int hash = device == null ? 17 : device.hashCode(); + int segmentCount = segments.length; + for (int i = 0; i < segmentCount; i++) { + //this function tends to given a fairly even distribution + hash = hash * 37 + segments[i].hashCode(); + } + return hash; + } + + /* (Intentionally not included in javadoc) + * Returns the size of the string that will be created by toString or toOSString. + */ + private int computeLength() { + int length = 0; + if (device != null) + length += device.length(); + if ((flags & HAS_LEADING) != 0) + length++; + if ((flags & IS_UNC) != 0) + length++; + //add the segment lengths + int max = segments.length; + if (max > 0) { + for (int i = 0; i < max; i++) { + length += segments[i].length(); + } + //add the separator lengths + length += max - 1; + } + if ((flags & HAS_TRAILING) != 0) + length++; + return length; + } + + /* (Intentionally not included in javadoc) + * Returns the number of segments in the given path + */ + private int computeSegmentCount(String path) { + int len = path.length(); + if (len == 0 || (len == 1 && path.charAt(0) == SEPARATOR)) { + return 0; + } + int count = 1; + int prev = -1; + int i; + while ((i = path.indexOf(SEPARATOR, prev + 1)) != -1) { + if (i != prev + 1 && i != len) { + ++count; + } + prev = i; + } + if (path.charAt(len - 1) == SEPARATOR) { + --count; + } + return count; + } + + /** + * Computes the segment array for the given canonicalized path. + */ + private String[] computeSegments(String path) { + // performance sensitive --- avoid creating garbage + int segmentCount = computeSegmentCount(path); + if (segmentCount == 0) + return NO_SEGMENTS; + String[] newSegments = new String[segmentCount]; + int len = path.length(); + // check for initial slash + int firstPosition = (path.charAt(0) == SEPARATOR) ? 1 : 0; + // check for UNC + if (firstPosition == 1 && len > 1 && (path.charAt(1) == SEPARATOR)) + firstPosition = 2; + int lastPosition = (path.charAt(len - 1) != SEPARATOR) ? len - 1 : len - 2; + // for non-empty paths, the number of segments is + // the number of slashes plus 1, ignoring any leading + // and trailing slashes + int next = firstPosition; + for (int i = 0; i < segmentCount; i++) { + int start = next; + int end = path.indexOf(SEPARATOR, next); + if (end == -1) { + newSegments[i] = path.substring(start, lastPosition + 1); + } else { + newSegments[i] = path.substring(start, end); + } + next = end + 1; + } + return newSegments; + } + + /** + * Returns the platform-neutral encoding of the given segment onto + * the given string buffer. This escapes literal colon characters with double colons. + */ + private void encodeSegment(String string, StringBuffer buf) { + int len = string.length(); + for (int i = 0; i < len; i++) { + char c = string.charAt(i); + buf.append(c); + if (c == DEVICE_SEPARATOR) + buf.append(DEVICE_SEPARATOR); + } + } + + /* (Intentionally not included in javadoc) + * Compares objects for equality. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof RemotePath)) + return false; + RemotePath target = (RemotePath) obj; + //check leading separators and hash code + if ((flags & HASH_MASK) != (target.flags & HASH_MASK)) + return false; + String[] targetSegments = target.segments; + int i = segments.length; + //check segment count + if (i != targetSegments.length) + return false; + //check segments in reverse order - later segments more likely to differ + while (--i >= 0) + if (!segments[i].equals(targetSegments[i])) + return false; + //check device last (least likely to differ) + return device == target.device || (device != null && device.equals(target.device)); + } + + /* (Intentionally not included in javadoc) + * @see IPath#getDevice + */ + @Override + public String getDevice() { + return device; + } + + /* (Intentionally not included in javadoc) + * @see IPath#getFileExtension + */ + @Override + public String getFileExtension() { + if (hasTrailingSeparator()) { + return null; + } + String lastSegment = lastSegment(); + if (lastSegment == null) { + return null; + } + int index = lastSegment.lastIndexOf('.'); + if (index == -1) { + return null; + } + return lastSegment.substring(index + 1); + } + + /* (Intentionally not included in javadoc) + * Computes the hash code for this object. + */ + @Override + public int hashCode() { + return flags & HASH_MASK; + } + + /* (Intentionally not included in javadoc) + * @see IPath#hasTrailingSeparator2 + */ + @Override + public boolean hasTrailingSeparator() { + return (flags & HAS_TRAILING) != 0; + } + + /* + * Initialize the current path with the given string. + */ + private IPath initialize(String deviceString, String path, boolean forWindows) { + Assert.isNotNull(path); + this.device = deviceString; + + path = collapseSlashes(path); + int len = path.length(); + + //compute the flags bitmap + if (len < 2) { + if (len == 1 && path.charAt(0) == SEPARATOR) { + this.flags = HAS_LEADING; + } else { + this.flags = 0; + } + } else { + boolean hasLeading = path.charAt(0) == SEPARATOR; + boolean isUNC = hasLeading && path.charAt(1) == SEPARATOR; + //UNC path of length two has no trailing separator + boolean hasTrailing = !(isUNC && len == 2) && path.charAt(len - 1) == SEPARATOR; + flags = hasLeading ? HAS_LEADING : 0; + if (isUNC) + flags |= IS_UNC; + if (hasTrailing) + flags |= HAS_TRAILING; + } + if (forWindows) { + flags |= IS_FOR_WINDOWS; + } + //compute segments and ensure canonical form + segments = computeSegments(path); + if (!canonicalize()) { + //compute hash now because canonicalize didn't need to do it + flags = (flags & ALL_FLAGS) | (computeHashCode() << 4); + } + return this; + } + + /* (Intentionally not included in javadoc) + * @see IPath#isAbsolute + */ + @Override + public boolean isAbsolute() { + //it's absolute if it has a leading separator + return (flags & HAS_LEADING) != 0; + } + + /* (Intentionally not included in javadoc) + * @see IPath#isEmpty + */ + @Override + public boolean isEmpty() { + //true if no segments and no leading prefix + return segments.length == 0 && ((flags & ALL_SEPARATORS) != HAS_LEADING); + } + + /* (Intentionally not included in javadoc) + * @see IPath#isPrefixOf + */ + @Override + public boolean isPrefixOf(IPath anotherPath) { + if (device == null) { + if (anotherPath.getDevice() != null) { + return false; + } + } else { + if (!device.equalsIgnoreCase(anotherPath.getDevice())) { + return false; + } + } + if (isEmpty() || (isRoot() && anotherPath.isAbsolute())) { + return true; + } + int len = segments.length; + if (len > anotherPath.segmentCount()) { + return false; + } + for (int i = 0; i < len; i++) { + if (!segments[i].equals(anotherPath.segment(i))) + return false; + } + return true; + } + + /* (Intentionally not included in javadoc) + * @see IPath#isRoot + */ + @Override + public boolean isRoot() { + //must have no segments, a leading separator, and not be a UNC path. + return this == ROOT || (segments.length == 0 && ((flags & ALL_SEPARATORS) == HAS_LEADING)); + } + + /* (Intentionally not included in javadoc) + * @see IPath#isUNC + */ + @Override + public boolean isUNC() { + if (device != null) + return false; + return (flags & IS_UNC) != 0; + } + + /* (Intentionally not included in javadoc) + * @see IPath#isValidPath(String) + */ + @Override + public boolean isValidPath(String path) { + return isValidPath(path, (flags & IS_FOR_WINDOWS) != 0); + } + + /** + * Returns whether the given string is syntactically correct as a path on a + * POSIX file system. The path is correct if each of the segments in its + * canonicalized form is valid. + * + * @param path the path to check + * @return true if the given string is a valid path, + * and false otherwise + * @see #isValidPosixSegment(String) + * @since 3.7 + */ + public static boolean isValidPosixPath(String path) { + return isValidPath(path, false); + } + + /** + * Returns whether the given string is syntactically correct as a path on + * the Windows file system. The device id is the prefix up to and including + * the device separator (':'); the path proper is everything to the right of + * it, or the entire string if there is no device separator. The device id + * is not checked for validity; the path proper is correct if each of the + * segments in its canonicalized form is valid. + * + * @param path the path to check + * @return true if the given string is a valid path, + * and false otherwise + * @see #isValidWindowsSegment(String) + * @since 3.7 + */ + public static boolean isValidWindowsPath(String path) { + return isValidPath(path, true); + } + + /** + * Returns whether the given string is syntactically correct as a path on + * the specified file system. The device id is the prefix up to and + * including the device separator for the specified file system; the path + * proper is everything to the right of it, or the entire string if there is + * no device separator. When the specified platform is a file system with no + * meaningful device separator, the entire string is treated as the path + * proper. The device id is not checked for validity; the path proper is + * correct if each of the segments in its canonicalized form is valid. + * + * @param path the path to check + * @param forWindows true if the path is for the Windows file system + * @return true if the given string is a valid path, + * and false otherwise + * @see #isValidSegment(String, boolean) + * @since 3.7 + */ + private static boolean isValidPath(String path, boolean forWindows) { + RemotePath test = new RemotePath(path, forWindows); + for (int i = 0, max = test.segmentCount(); i < max; i++) + if (!RemotePath.isValidSegment(test.segment(i), forWindows)) + return false; + return true; + } + + /* (Intentionally not included in javadoc) + * @see IPath#isValidSegment(String) + */ + @Override + public boolean isValidSegment(String segment) { + return isValidSegment(segment, (flags & IS_FOR_WINDOWS) != 0); + } + + /** + * Returns whether the given string is valid as a segment in a path on a + * POSIX file system. The rules for valid segments are as follows: + * + * + * @param segment the path segment to check + * @return true if the given path segment is valid, + * and false otherwise + * @since 3.7 + */ + public static boolean isValidPosixSegment(String segment) { + return isValidSegment(segment, false); + } + + /** + * Returns whether the given string is valid as a segment in a path on the + * Windows file system. The rules for valid segments are as follows: + * + * + * @param segment the path segment to check + * @return true if the given path segment is valid, + * and false otherwise + * @since 3.7 + */ + public static boolean isValidWindowsSegment(String segment) { + return isValidSegment(segment, true); + } + + /** + * Returns whether the given string is valid as a segment in a path on the + * specified file system. The rules for valid segments are as follows: + * + * + * @param segment the path segment to check + * @param forWindows true if the path is for the Windows file system + * @return true if the given path segment is valid, + * and false otherwise + * @since 3.7 + */ + private static boolean isValidSegment(String segment, boolean forWindows) { + int size = segment.length(); + if (size == 0) + return false; + for (int i = 0; i < size; i++) { + char c = segment.charAt(i); + if (c == '/') + return false; + if (forWindows && (c == '\\' || c == ':')) + return false; + } + return true; + } + + /* (Intentionally not included in javadoc) + * @see IPath#lastSegment() + */ + @Override + public String lastSegment() { + int len = segments.length; + return len == 0 ? null : segments[len - 1]; + } + + /* (Intentionally not included in javadoc) + * @see IPath#makeAbsolute() + */ + @Override + public IPath makeAbsolute() { + if (isAbsolute()) { + return this; + } + RemotePath result = new RemotePath(device, segments, flags | HAS_LEADING); + //may need canonicalizing if it has leading ".." or "." segments + if (result.segmentCount() > 0) { + String first = result.segment(0); + if (first.equals("..") || first.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$ + result.canonicalize(); + } + } + return result; + } + + /* (Intentionally not included in javadoc) + * @see IPath#makeRelative() + */ + @Override + public IPath makeRelative() { + if (!isAbsolute()) { + return this; + } + return new RemotePath(device, segments, flags & (HAS_TRAILING | IS_FOR_WINDOWS)); + } + + /** + * {@inheritDoc} + * @since org.eclipse.equinox.common 3.5 + */ + @Override + public IPath makeRelativeTo(IPath base) { + //can't make relative if devices are not equal + if (device != base.getDevice() && (device == null || !device.equalsIgnoreCase(base.getDevice()))) + return this; + int commonLength = matchingFirstSegments(base); + final int differenceLength = base.segmentCount() - commonLength; + final int newSegmentLength = differenceLength + segmentCount() - commonLength; + if (newSegmentLength == 0) + return RemotePath.EMPTY; + String[] newSegments = new String[newSegmentLength]; + //add parent references for each segment different from the base + Arrays.fill(newSegments, 0, differenceLength, ".."); //$NON-NLS-1$ + //append the segments of this path not in common with the base + System.arraycopy(segments, commonLength, newSegments, differenceLength, newSegmentLength - differenceLength); + return new RemotePath(null, newSegments, flags & (HAS_TRAILING | IS_FOR_WINDOWS)); + } + + /* (Intentionally not included in javadoc) + * @see IPath#makeUNC(boolean) + */ + @Override + public IPath makeUNC(boolean toUNC) { + // if we are already in the right form then just return + if (!(toUNC ^ isUNC())) + return this; + + int newSeparators = this.flags; + if (toUNC) { + newSeparators |= HAS_LEADING | IS_UNC; + } else { + //mask out the UNC bit + newSeparators &= HAS_LEADING | HAS_TRAILING | IS_FOR_WINDOWS; + } + return new RemotePath(toUNC ? null : device, segments, newSeparators); + } + + /* (Intentionally not included in javadoc) + * @see IPath#matchingFirstSegments(IPath) + */ + @Override + public int matchingFirstSegments(IPath anotherPath) { + Assert.isNotNull(anotherPath); + int anotherPathLen = anotherPath.segmentCount(); + int max = Math.min(segments.length, anotherPathLen); + int count = 0; + for (int i = 0; i < max; i++) { + if (!segments[i].equals(anotherPath.segment(i))) { + return count; + } + count++; + } + return count; + } + + /* (Intentionally not included in javadoc) + * @see IPath#removeFileExtension() + */ + @Override + public IPath removeFileExtension() { + String extension = getFileExtension(); + if (extension == null || extension.equals("")) { //$NON-NLS-1$ + return this; + } + String lastSegment = lastSegment(); + int index = lastSegment.lastIndexOf(extension) - 1; + return removeLastSegments(1).append(lastSegment.substring(0, index)); + } + + /* (Intentionally not included in javadoc) + * @see IPath#removeFirstSegments(int) + */ + @Override + public IPath removeFirstSegments(int count) { + if (count == 0) + return this; + if (count >= segments.length) { + return new RemotePath(device, NO_SEGMENTS, flags & IS_FOR_WINDOWS); + } + Assert.isLegal(count > 0); + int newSize = segments.length - count; + String[] newSegments = new String[newSize]; + System.arraycopy(this.segments, count, newSegments, 0, newSize); + + //result is always a relative path + return new RemotePath(device, newSegments, flags & (HAS_TRAILING | IS_FOR_WINDOWS)); + } + + /* (Intentionally not included in javadoc) + * @see IPath#removeLastSegments(int) + */ + @Override + public IPath removeLastSegments(int count) { + if (count == 0) + return this; + if (count >= segments.length) { + //result will have no trailing separator + return new RemotePath(device, NO_SEGMENTS, flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS)); + } + Assert.isLegal(count > 0); + int newSize = segments.length - count; + String[] newSegments = new String[newSize]; + System.arraycopy(this.segments, 0, newSegments, 0, newSize); + return new RemotePath(device, newSegments, flags); + } + + /* (Intentionally not included in javadoc) + * @see IPath#removeTrailingSeparator() + */ + @Override + public IPath removeTrailingSeparator() { + if (!hasTrailingSeparator()) { + return this; + } + return new RemotePath(device, segments, flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS)); + } + + /* (Intentionally not included in javadoc) + * @see IPath#segment(int) + */ + @Override + public String segment(int index) { + if (index >= segments.length) + return null; + return segments[index]; + } + + /* (Intentionally not included in javadoc) + * @see IPath#segmentCount() + */ + @Override + public int segmentCount() { + return segments.length; + } + + /* (Intentionally not included in javadoc) + * @see IPath#segments() + */ + @Override + public String[] segments() { + String[] segmentCopy = new String[segments.length]; + System.arraycopy(segments, 0, segmentCopy, 0, segments.length); + return segmentCopy; + } + + /* (Intentionally not included in javadoc) + * @see IPath#setDevice(String) + */ + @Override + public IPath setDevice(String value) { + if (value != null) { + Assert.isTrue(value.indexOf(IPath.DEVICE_SEPARATOR) == (value.length() - 1), "Last character should be the device separator"); //$NON-NLS-1$ + } + //return the receiver if the device is the same + if (value == device || (value != null && value.equals(device))) + return this; + + return new RemotePath(value, segments, flags); + } + + /* (Intentionally not included in javadoc) + * @see IPath#toFile() + */ + @Override + public File toFile() { + return new File(toOSString()); + } + + /* (Intentionally not included in javadoc) + * @see IPath#toOSString() + */ + @Override + public String toOSString() { + //Note that this method is identical to toString except + //it uses the OS file separator instead of the path separator + int resultSize = computeLength(); + if (resultSize <= 0) + return EMPTY_STRING; + char FILE_SEPARATOR = File.separatorChar; + char[] result = new char[resultSize]; + int offset = 0; + if (device != null) { + int size = device.length(); + device.getChars(0, size, result, offset); + offset += size; + } + if ((flags & HAS_LEADING) != 0) + result[offset++] = FILE_SEPARATOR; + if ((flags & IS_UNC) != 0) + result[offset++] = FILE_SEPARATOR; + int len = segments.length - 1; + if (len >= 0) { + //append all but the last segment, with file separators + for (int i = 0; i < len; i++) { + int size = segments[i].length(); + segments[i].getChars(0, size, result, offset); + offset += size; + result[offset++] = FILE_SEPARATOR; + } + //append the last segment + int size = segments[len].length(); + segments[len].getChars(0, size, result, offset); + offset += size; + } + if ((flags & HAS_TRAILING) != 0) + result[offset++] = FILE_SEPARATOR; + return new String(result); + } + + /* (Intentionally not included in javadoc) + * @see IPath#toPortableString() + */ + @Override + public String toPortableString() { + int resultSize = computeLength(); + if (resultSize <= 0) + return EMPTY_STRING; + StringBuffer result = new StringBuffer(resultSize); + if (device != null) + result.append(device); + if ((flags & HAS_LEADING) != 0) + result.append(SEPARATOR); + if ((flags & IS_UNC) != 0) + result.append(SEPARATOR); + int len = segments.length; + //append all segments with separators + for (int i = 0; i < len; i++) { + if (segments[i].indexOf(DEVICE_SEPARATOR) >= 0) + encodeSegment(segments[i], result); + else + result.append(segments[i]); + if (i < len - 1 || (flags & HAS_TRAILING) != 0) + result.append(SEPARATOR); + } + return result.toString(); + } + + /* (Intentionally not included in javadoc) + * @see IPath#toString() + */ + @Override + public String toString() { + int resultSize = computeLength(); + if (resultSize <= 0) + return EMPTY_STRING; + char[] result = new char[resultSize]; + int offset = 0; + if (device != null) { + int size = device.length(); + device.getChars(0, size, result, offset); + offset += size; + } + if ((flags & HAS_LEADING) != 0) + result[offset++] = SEPARATOR; + if ((flags & IS_UNC) != 0) + result[offset++] = SEPARATOR; + int len = segments.length - 1; + if (len >= 0) { + //append all but the last segment, with separators + for (int i = 0; i < len; i++) { + int size = segments[i].length(); + segments[i].getChars(0, size, result, offset); + offset += size; + result[offset++] = SEPARATOR; + } + //append the last segment + int size = segments[len].length(); + segments[len].getChars(0, size, result, offset); + offset += size; + } + if ((flags & HAS_TRAILING) != 0) + result[offset++] = SEPARATOR; + return new String(result); + } + + /* (Intentionally not included in javadoc) + * @see IPath#uptoSegment(int) + */ + @Override + public IPath uptoSegment(int count) { + if (count == 0) + return new RemotePath(device, NO_SEGMENTS, flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS)); + if (count >= segments.length) + return this; + Assert.isTrue(count > 0, "Invalid parameter to RemotePath.uptoSegment"); //$NON-NLS-1$ + String[] newSegments = new String[count]; + System.arraycopy(segments, 0, newSegments, 0, count); + return new RemotePath(device, newSegments, flags); + } +} diff --git a/bundles/org.eclipse.remote.jsch.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.jsch.core/META-INF/MANIFEST.MF index 1e7ecaccb75..4628e21e730 100644 --- a/bundles/org.eclipse.remote.jsch.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.jsch.core/META-INF/MANIFEST.MF @@ -5,9 +5,9 @@ Bundle-SymbolicName: org.eclipse.remote.jsch.core;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Activator: org.eclipse.remote.internal.jsch.core.Activator Bundle-Vendor: %pluginProvider -Require-Bundle: org.eclipse.core.runtime;bundle-version="3.11.0", +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.9.100", org.eclipse.core.filesystem, - org.eclipse.remote.core, + org.eclipse.remote.core;bundle-version="2.0", org.eclipse.jsch.core, com.jcraft.jsch, org.eclipse.equinox.security diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java index 1ad80c127ce..a23726cdf09 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - Initial API and implementation * Patrick Tasse - [462418] use stored password on non-preferred password based authentication + * Martin Oberhuber - [468889] Support Eclipse older than Mars *******************************************************************************/ package org.eclipse.remote.internal.jsch.core; @@ -19,7 +20,6 @@ import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jsch.core.IJSchService; import org.eclipse.osgi.util.NLS; @@ -34,6 +34,7 @@ import org.eclipse.remote.core.IRemoteProcessBuilder; import org.eclipse.remote.core.IRemoteProcessService; import org.eclipse.remote.core.IUserAuthenticatorService; import org.eclipse.remote.core.RemoteConnectionChangeEvent; +import org.eclipse.remote.core.RemoteServicesUtils; import org.eclipse.remote.core.exception.AddressInUseException; import org.eclipse.remote.core.exception.RemoteConnectionException; import org.eclipse.remote.core.exception.UnableToForwardPortException; @@ -1020,7 +1021,7 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC */ @Override public void setWorkingDirectory(String path) { - if (Path.forPosix(path).isAbsolute()) { + if (RemoteServicesUtils.posixPath(path).isAbsolute()) { fWorkingDir = path; } } diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchFileManager.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchFileManager.java index 7d9b0312d5f..2a6eefe297e 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchFileManager.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchFileManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 IBM Corporation and others. + * Copyright (c) 2007, 2015 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - Initial API and implementation + * Martin Oberhuber - [468889] Support Eclipse older than Mars *******************************************************************************/ package org.eclipse.remote.internal.jsch.core; @@ -14,11 +15,11 @@ import java.net.URI; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; import org.eclipse.remote.core.IRemoteConnection; import org.eclipse.remote.core.IRemoteConnection.Service; import org.eclipse.remote.core.IRemoteFileService; import org.eclipse.remote.core.IRemoteProcessService; +import org.eclipse.remote.core.RemoteServicesUtils; public class JSchFileManager implements IRemoteFileService { @@ -51,9 +52,9 @@ public class JSchFileManager implements IRemoteFileService { @Override public IFileStore getResource(String pathStr) { - IPath path = Path.forPosix(pathStr); + IPath path = RemoteServicesUtils.posixPath(pathStr); if (!path.isAbsolute()) { - path = Path.forPosix(getBaseDirectory()).append(path); + path = RemoteServicesUtils.posixPath(getBaseDirectory()).append(path); } return JschFileStore.getInstance(JSchFileSystem.getURIFor(fConnection.getName(), path.toString())); } @@ -84,7 +85,7 @@ public class JSchFileManager implements IRemoteFileService { @Override public URI toURI(String path) { - return toURI(Path.forPosix(path)); + return toURI(RemoteServicesUtils.posixPath(path)); } } diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JschFileStore.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JschFileStore.java index ce9552aefe3..3712aee109d 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JschFileStore.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JschFileStore.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 IBM Corporation and others. + * Copyright (c) 2007, 2015 IBM Corporation 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - Initial API and implementation * Roland Schulz, University of Tennessee + * Martin Oberhuber - [468889] Support Eclipse older than Mars *******************************************************************************/ package org.eclipse.remote.internal.jsch.core; @@ -25,13 +26,13 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.osgi.util.NLS; import org.eclipse.remote.core.IRemoteConnection; import org.eclipse.remote.core.IRemoteConnectionType; import org.eclipse.remote.core.IRemoteServicesManager; +import org.eclipse.remote.core.RemoteServicesUtils; import org.eclipse.remote.core.exception.RemoteConnectionException; import org.eclipse.remote.internal.jsch.core.commands.ChildInfosCommand; import org.eclipse.remote.internal.jsch.core.commands.DeleteCommand; @@ -68,7 +69,7 @@ public class JschFileStore extends FileStore { private JschFileStore(URI uri) { fURI = uri; - fRemotePath = Path.forPosix(uri.getPath()); + fRemotePath = RemoteServicesUtils.posixPath(uri.getPath()); } private JSchConnection checkConnection(IProgressMonitor monitor) throws RemoteConnectionException { diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java index 84a249f86f2..3d49cba56e0 100755 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2013 IBM Corporation. + * Copyright (c) 2013, 2015 IBM Corporation 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 @@ -7,7 +7,7 @@ * * Contributors: * IBM Corporation - Initial Implementation - * + * Martin Oberhuber - [468889] Support Eclipse older than Mars *****************************************************************************/ package org.eclipse.remote.internal.jsch.core.commands; @@ -28,8 +28,8 @@ import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.provider.FileInfo; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.remote.core.RemoteServicesUtils; import org.eclipse.remote.core.exception.RemoteConnectionException; import org.eclipse.remote.internal.jsch.core.JSchConnection; import org.eclipse.remote.internal.jsch.core.messages.Messages; @@ -107,7 +107,7 @@ public abstract class AbstractRemoteCommand { fMaxWork = max / 1024L; } fWorkToDate = 0; - fMonitor.beginTask(Path.forPosix(src).lastSegment(), (int) max); + fMonitor.beginTask(RemoteServicesUtils.posixPath(src).lastSegment(), (int) max); } } diff --git a/bundles/org.eclipse.remote.jsch.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.jsch.ui/META-INF/MANIFEST.MF index be913eb57be..ab5f186e2ab 100644 --- a/bundles/org.eclipse.remote.jsch.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.jsch.ui/META-INF/MANIFEST.MF @@ -5,9 +5,9 @@ Bundle-SymbolicName: org.eclipse.remote.jsch.ui;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Activator: org.eclipse.remote.internal.jsch.ui.Activator Bundle-Vendor: %pluginProvider -Require-Bundle: org.eclipse.core.runtime;bundle-version="3.11.0", +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.9.100", org.eclipse.core.filesystem, - org.eclipse.remote.core, + org.eclipse.remote.core;bundle-version="2.0", org.eclipse.remote.ui, org.eclipse.remote.jsch.core, org.eclipse.jsch.core, diff --git a/bundles/org.eclipse.remote.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.ui/META-INF/MANIFEST.MF index 6e5bf55148f..1a72bf19ded 100644 --- a/bundles/org.eclipse.remote.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.ui/META-INF/MANIFEST.MF @@ -8,8 +8,8 @@ Bundle-Vendor: %pluginProvider Require-Bundle: org.eclipse.ui, org.eclipse.ui.ide, org.eclipse.ui.forms, - org.eclipse.core.runtime;bundle-version="3.11.0", - org.eclipse.remote.core, + org.eclipse.core.runtime;bundle-version="3.9.100", + org.eclipse.remote.core;bundle-version="2.0", org.eclipse.core.filesystem, org.eclipse.core.resources, org.eclipse.ui.trace, diff --git a/bundles/org.eclipse.remote.ui/src/org/eclipse/remote/ui/widgets/RemoteResourceBrowserWidget.java b/bundles/org.eclipse.remote.ui/src/org/eclipse/remote/ui/widgets/RemoteResourceBrowserWidget.java index f66328f74f0..e4cbc359a84 100644 --- a/bundles/org.eclipse.remote.ui/src/org/eclipse/remote/ui/widgets/RemoteResourceBrowserWidget.java +++ b/bundles/org.eclipse.remote.ui/src/org/eclipse/remote/ui/widgets/RemoteResourceBrowserWidget.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008,2013 IBM Corporation and others. + * Copyright (c) 2008, 2015 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM - Initial API and implementation + * Martin Oberhuber - [468889] Support Eclipse older than Mars *******************************************************************************/ package org.eclipse.remote.ui.widgets; @@ -21,7 +22,6 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.dialogs.Dialog; @@ -45,6 +45,7 @@ import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.remote.core.IRemoteConnection; import org.eclipse.remote.core.IRemoteFileService; import org.eclipse.remote.core.IRemoteProcessService; +import org.eclipse.remote.core.RemoteServicesUtils; import org.eclipse.remote.internal.ui.DeferredFileStore; import org.eclipse.remote.internal.ui.DeferredFileStoreComparer; import org.eclipse.remote.internal.ui.PendingUpdateAdapter; @@ -586,15 +587,15 @@ public class RemoteResourceBrowserWidget extends Composite { */ private IPath findInitialPath(String cwd, String initialPath) { if (initialPath != null) { - IPath path = Path.forPosix(initialPath); + IPath path = RemoteServicesUtils.posixPath(initialPath); if (!path.isAbsolute()) { - path = Path.forPosix(cwd).append(path); + path = RemoteServicesUtils.posixPath(cwd).append(path); } if (fFileMgr.getResource(path.toString()).fetchInfo().exists()) { return path; } } - return Path.forPosix(cwd); + return RemoteServicesUtils.posixPath(cwd); } /** @@ -702,7 +703,7 @@ public class RemoteResourceBrowserWidget extends Composite { fRemotePathText.setText(path); fRemotePathText.setSelection(fRemotePathText.getText().length()); fResources.add(root); - fRootPath = Path.forPosix(path); + fRootPath = RemoteServicesUtils.posixPath(path); } } diff --git a/tests/org.eclipse.remote.core.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.remote.core.tests/META-INF/MANIFEST.MF index 3a024fcdeef..6d8f1b7b975 100644 --- a/tests/org.eclipse.remote.core.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.remote.core.tests/META-INF/MANIFEST.MF @@ -4,7 +4,7 @@ Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.remote.core.tests;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Vendor: %pluginProvider -Require-Bundle: org.eclipse.core.runtime;bundle-version="3.11.0", +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.9.100", org.junit, com.jcraft.jsch;bundle-version="0.1.41", org.eclipse.core.filesystem;bundle-version="1.2.0", diff --git a/tests/org.eclipse.remote.jsch.tests/.classpath b/tests/org.eclipse.remote.jsch.tests/.classpath index eca7bdba8f0..098194ca4b7 100644 --- a/tests/org.eclipse.remote.jsch.tests/.classpath +++ b/tests/org.eclipse.remote.jsch.tests/.classpath @@ -1,6 +1,6 @@ - + diff --git a/tests/org.eclipse.remote.jsch.tests/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.remote.jsch.tests/.settings/org.eclipse.jdt.core.prefs index 0c68a61dca8..f42de363afa 100644 --- a/tests/org.eclipse.remote.jsch.tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/org.eclipse.remote.jsch.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/tests/org.eclipse.remote.jsch.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.remote.jsch.tests/META-INF/MANIFEST.MF index 34f51811796..2bbda3d108d 100644 --- a/tests/org.eclipse.remote.jsch.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.remote.jsch.tests/META-INF/MANIFEST.MF @@ -6,10 +6,10 @@ Bundle-Version: 1.0.0.qualifier Bundle-Activator: org.eclipse.remote.jsch.tests.Activator Bundle-Vendor: Eclipse PTP Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime;bundle-version="3.11.0", + org.eclipse.core.runtime;bundle-version="3.9.100", org.eclipse.core.filesystem, org.eclipse.remote.core, org.eclipse.remote.jsch.core, org.junit -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy