/******************************************************************************* * Copyright (c) 2014, 2015 Wind River Systems, Inc. * 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: * Markus Schorn - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.tcf.remote.core; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.provider.FileInfo; import org.eclipse.core.filesystem.provider.FileStore; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.remote.core.IRemoteConnectionType; import org.eclipse.remote.core.IRemoteServicesManager; import org.eclipse.remote.internal.core.RemotePath; import org.eclipse.tcf.services.IFileSystem.FileAttrs; import org.eclipse.tcf.te.tcf.remote.core.activator.CoreBundleActivator; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationChildStores; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationDelete; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationFetchInfo; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationMkDir; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationOpenInputStream; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationOpenOutputStream; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationPutInfo; public final class TCFFileStore extends FileStore { public static final String SCHEME = "tcf"; //$NON-NLS-1$ public static final String NOSLASH_MARKER = "/./"; //$NON-NLS-1$ public static String addNoSlashMarker(String path) { if (path.length() > 0 && path.charAt(0) != '/') return NOSLASH_MARKER + path; return path; } public static String stripNoSlashMarker(String path) { if (path.startsWith(NOSLASH_MARKER)) return path.substring(NOSLASH_MARKER.length()); return path; } public static URI toURI(TCFConnection connection, String path) { try { return new URI(SCHEME, connection.getName(), addNoSlashMarker(path), null, null); } catch (URISyntaxException e) { return null; } } public static String toPath(URI uri) { return stripNoSlashMarker(uri.getPath()); } public static TCFConnection toConnection(URI uri) { IRemoteServicesManager rsm = CoreBundleActivator.getService(IRemoteServicesManager.class); if (rsm == null) return null; IRemoteConnectionType ct = rsm.getConnectionType(uri); if (ct == null) return null; String peerName = uri.getAuthority(); if (peerName == null) return null; return TCFConnectionManager.INSTANCE.mapConnection(ct.getConnection(peerName)); } public static IFileStore getInstance(URI uri) { TCFConnection connection = toConnection(uri); String path = toPath(uri); if (connection != null) { return new TCFFileStore(connection, path, null); } return EFS.getNullFileSystem().getStore(RemotePath.forPosix(path)); } private final TCFConnection fConnection; private final String fPath; private FileAttrs fAttributes; private TCFFileStore fParent; private boolean fArtificialRoot; TCFFileStore(TCFConnection connection, String path, TCFFileStore parent) { fPath = path; fConnection = connection; fParent = parent; } @Override public URI toURI() { return toURI(fConnection, fPath); } public TCFConnection getConnection() { return fConnection; } public String getPath() { return fPath; } public void setAttributes(FileAttrs attrs) { fAttributes = attrs; } public FileAttrs getAttributes() { return fAttributes; } @Override public IFileStore getChild(String name) { // Remove trailing slash if (name.length() > 1 && name.endsWith("/")) //$NON-NLS-1$ name = name.substring(0, name.length()-1); String path; if (fArtificialRoot) { path = name; } else if (fPath.endsWith("/")) { //$NON-NLS-1$ path = fPath + name; } else { path = fPath + "/" + name; //$NON-NLS-1$ } return new TCFFileStore(fConnection, path, this); } @Override public String getName() { String path = getPath(); if (fParent == null || fParent.fArtificialRoot) return path; int idx = path.lastIndexOf('/', path.length()-2); if (idx > 0) return path.substring(idx + 1); return path; } @Override public IFileStore getParent() { if (fParent != null) return fParent; int idx = fPath.lastIndexOf('/'); if (idx < 1) return null; fParent = new TCFFileStore(fConnection, fPath.substring(0, idx-1), null); return fParent; } @Override public IFileInfo fetchInfo(int options, IProgressMonitor monitor) throws CoreException { try { return new TCFOperationFetchInfo(this).execute(SubMonitor.convert(monitor)); } catch (OperationCanceledException e) { } return new FileInfo(getName()); } @Override public IFileStore[] childStores(int options, IProgressMonitor monitor) throws CoreException { try { return new TCFOperationChildStores(this).execute(SubMonitor.convert(monitor)); } catch (OperationCanceledException e) { } return new IFileStore[0]; } @Override public String[] childNames(int options, IProgressMonitor monitor) throws CoreException { IFileStore[] children = childStores(options, monitor); String[] result = new String[children.length]; int i = 0; for (IFileStore s : children) { result[i++] = s.getName(); } return result; } @Override public void delete(int options, IProgressMonitor monitor) throws CoreException { try { new TCFOperationDelete(this).execute(SubMonitor.convert(monitor)); } catch (OperationCanceledException e) { } } @Override public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException { boolean shallow = (options & EFS.SHALLOW) == EFS.SHALLOW; try { new TCFOperationMkDir(this, shallow).execute(SubMonitor.convert(monitor)); } catch (OperationCanceledException e) { } return this; } @Override public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException { boolean setAttribs = (options & EFS.SET_ATTRIBUTES) != 0; boolean setLastModified = (options & EFS.SET_LAST_MODIFIED) != 0; try { if (setAttribs || setLastModified) { new TCFOperationPutInfo(this, info, setAttribs, setLastModified).execute(SubMonitor.convert(monitor)); } } catch (OperationCanceledException e) { } } @Override public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException { try { return new TCFOperationOpenInputStream(this).execute(SubMonitor.convert(monitor)); } catch (OperationCanceledException e) { return null; } } @Override public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException { boolean append = (options & EFS.APPEND) != 0; try { return new TCFOperationOpenOutputStream(this, append).execute(SubMonitor.convert(monitor)); } catch (OperationCanceledException e) { return null; } } public void setIsArtificialRoot() { fArtificialRoot = true; } }