/*******************************************************************************
* Copyright (c) 2012, 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
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.core.internal.operations;
import static java.text.MessageFormat.format;
import static org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager.getRuntimeModel;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.runtime.utils.Host;
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.IRuntimeModel;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.FSTreeNode;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.testers.TargetPropertyTester;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager;
import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode;
import org.eclipse.tcf.te.tcf.locator.interfaces.services.IPeerModelLookupService;
import org.eclipse.tcf.te.tcf.locator.model.ModelManager;
/**
* The operation to parse a platform specific path to a target's node.
*/
public class OpParsePath extends AbstractOperation implements IResultOperation<IFSTreeNode> {
// The peer on which the file is located.
IPeerNode peer;
// The path on the target.
String path;
// The parsing result.
FSTreeNode result;
/**
* Create an instance with a path on a specified target.
*
* @param peer The target peer.
* @param path The path to be parsed.
*/
public OpParsePath(IPeerNode peer, String path) {
this.peer = peer;
this.path = path;
}
/**
* The path of the cache file to be parsed.
*
* @param filePath The local cache's file.
*/
public OpParsePath(String filePath) {
String cache_root = CacheManager.getCacheRoot().getAbsolutePath();
if (filePath.startsWith(cache_root)) {
filePath = filePath.substring(cache_root.length() + 1);
int slash = filePath.indexOf(File.separator);
if (slash != -1) {
String peerId = filePath.substring(0, slash);
peerId = peerId.replace(CacheManager.PATH_ESCAPE_CHAR, ':');
final AtomicReference<IPeerNode> peerNode = new AtomicReference<IPeerNode>();
final String finPeerId = peerId;
Runnable runnable = new Runnable() {
@Override
public void run() {
peerNode.set(ModelManager.getPeerModel().getService(IPeerModelLookupService.class).lkupPeerModelById(finPeerId));
}
};
if (Protocol.isDispatchThread()) runnable.run();
else Protocol.invokeAndWait(runnable);
this.peer = peerNode.get();
if (peer != null) {
boolean hostWindows = Host.isWindowsHost();
boolean windows = TargetPropertyTester.isWindows(peer);
filePath = filePath.substring(slash + 1);
if (hostWindows) {
if (windows) {
slash = filePath.indexOf(File.separator);
if (slash != -1) {
String disk = filePath.substring(0, slash);
filePath = filePath.substring(slash + 1);
disk = disk.replace(CacheManager.PATH_ESCAPE_CHAR, ':');
filePath = disk + File.separator + filePath;
}
}
else {
filePath = "/" + filePath.replace('\\', '/'); //$NON-NLS-1$
}
}
else {
if (windows) {
slash = filePath.indexOf(File.separator);
if (slash != -1) {
String disk = filePath.substring(0, slash);
filePath = filePath.substring(slash + 1);
disk = disk.replace(CacheManager.PATH_ESCAPE_CHAR, ':');
filePath = disk + File.separator + filePath;
}
filePath = filePath.replace(File.separatorChar, '\\');
}
else {
filePath = "/" + filePath; //$NON-NLS-1$
}
}
path = filePath;
}
}
}
}
@Override
public FSTreeNode getResult() {
return result;
}
@Override
public IStatus doRun(IProgressMonitor monitor) {
monitor.beginTask(getName(), IProgressMonitor.UNKNOWN);
if (peer == null || path == null)
return Status.OK_STATUS;
IRuntimeModel rtm = getRuntimeModel(peer);
if (rtm == null)
return null;
final FSTreeNode node = (FSTreeNode) rtm.getRoot();
return findPath(node, path, monitor);
}
private IStatus findPath(FSTreeNode node, String path, IProgressMonitor monitor) {
if (path == null || path.length() == 0) {
result = node;
return Status.OK_STATUS;
}
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
path = path.replace(':', CacheManager.PATH_ESCAPE_CHAR);
if (node.getChildren() == null) {
IStatus status = node.operationRefresh(false).run(new SubProgressMonitor(monitor, 0));
if (!status.isOK())
return status;
}
if (node.isFileSystem()) {
for (FSTreeNode child : node.getChildren()) {
if (path.startsWith(child.getName().replace(':', CacheManager.PATH_ESCAPE_CHAR))) {
return findPath(child, path.substring(child.getName().length()), monitor);
}
}
return Status.OK_STATUS;
}
String osPathSep = node.isWindowsNode() ? "\\" : "/"; //$NON-NLS-1$ //$NON-NLS-2$
int delim = path.indexOf(osPathSep);
final String segment;
if (delim == -1) {
segment = path;
path = null;
} else {
segment = path.substring(0, delim);
path = path.substring(delim+1);
}
node = node.findChild(segment);
if (node == null)
return Status.OK_STATUS;
return findPath(node, path, monitor);
}
@Override
public String getName() {
return format(Messages.OpParsePath_name, path);
}
}