/*******************************************************************************
* 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
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.core.model;
import static org.eclipse.tcf.te.tcf.locator.model.ModelManager.getPeerModel;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.tcf.protocol.IChannel;
import org.eclipse.tcf.protocol.IChannel.IChannelListener;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.services.IFileSystem;
import org.eclipse.tcf.te.core.interfaces.IConnectable;
import org.eclipse.tcf.te.core.interfaces.IPropertyChangeProvider;
import org.eclipse.tcf.te.runtime.model.ContainerModelNode;
import org.eclipse.tcf.te.runtime.model.factory.Factory;
import org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory;
import org.eclipse.tcf.te.runtime.services.ServiceManager;
import org.eclipse.tcf.te.runtime.services.interfaces.IDelegateService;
import org.eclipse.tcf.te.runtime.services.interfaces.IService;
import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelService;
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.IRuntimeModel;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.FSTreeNode;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.UserAccount;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCopyLocal;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpParsePath;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRestoreFavorites;
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;
/**
* The file system model implementation.
*/
public final class RuntimeModel extends ContainerModelNode implements IRuntimeModel, IChannelListener {
private final IPeerNode fPeerNode;
private final FSTreeNode fRoot;
private final UserAccount fUserAccount;
private IChannel fChannel;
private IFileSystem fFileSystem;
private Delegate fDelegate;
/**
* Create a File System ModelManager.
*/
public RuntimeModel(IPeerNode peerNode, IChannel channel, IFileSystem fileSystem, UserAccount userAccount) {
fPeerNode = peerNode;
fChannel = channel;
fFileSystem = fileSystem;
fUserAccount = userAccount;
fRoot = new FSTreeNode(this, Messages.FSTreeNodeContentProvider_rootNodeLabel);
channel.addChannelListener(this);
fDelegate = findDelegate();
}
private Delegate findDelegate() {
IService[] services = ServiceManager.getInstance().getServices(fPeerNode, IDelegateService.class, false);
for (IService service : services) {
Delegate cand = ((IDelegateService) service).getDelegate(this, Delegate.class);
if (cand != null)
return cand;
}
return new Delegate();
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#checkThreadAccess()
*/
@Override
protected boolean checkThreadAccess() {
return Protocol.isDispatchThread();
}
/* (non-Javadoc)
* @see org.eclipse.tcf.protocol.IChannel.IChannelListener#onChannelOpened()
*/
@Override
public void onChannelOpened() {
}
/* (non-Javadoc)
* @see org.eclipse.tcf.protocol.IChannel.IChannelListener#congestionLevel(int)
*/
@Override
public void congestionLevel(int level) {
}
/* (non-Javadoc)
* @see org.eclipse.tcf.protocol.IChannel.IChannelListener#onChannelClosed(java.lang.Throwable)
*/
@Override
public void onChannelClosed(Throwable error) {
ModelManager.disposeRuntimeModel(fPeerNode);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#dispose()
*/
@Override
public void dispose() {
Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
fFileSystem = null;
fRoot.setContent(new FSTreeNode[0], false);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#isDisposed()
*/
@Override
public boolean isDisposed() {
Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
return fFileSystem == null;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#getService(java.lang.Class)
*/
@Override
@SuppressWarnings("unchecked")
public <V extends IModelService> V getService(Class<V> serviceInterface) {
Assert.isNotNull(serviceInterface);
return (V)getAdapter(serviceInterface);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IRuntimeModel#getDelegate()
*/
@Override
public Delegate getDelegate() {
return fDelegate;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#getAdapter(java.lang.Class)
*/
@Override
public Object getAdapter(Class adapter) {
if (IPeerNode.class.isAssignableFrom(adapter) || IConnectable.class.isAssignableFrom(adapter)) {
return getPeerNode();
}
return super.getAdapter(adapter);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#setFactory(org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory)
*/
@Override
public void setFactory(IFactory factory) {
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#getFactory()
*/
@Override
public IFactory getFactory() {
return Factory.getInstance();
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider#getPeerNode()
*/
@Override
public final IPeerNode getPeerNode() {
return fPeerNode;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.runtime.model.ModelNode#toString()
*/
@Override
public String toString() {
if (isDisposed()) {
return "*DISPOSED* : " + super.toString(); //$NON-NLS-1$
}
return super.toString();
}
@Override
public FSTreeNode getRoot() {
return fRoot;
}
public UserAccount getUserAccount() {
return fUserAccount;
}
public void firePropertyChanged(PropertyChangeEvent propertyChangeEvent) {
IPropertyChangeProvider provider = (IPropertyChangeProvider) fPeerNode.getAdapter(IPropertyChangeProvider.class);
if (provider != null)
provider.firePropertyChange(propertyChangeEvent);
}
@Override
public IOperation operationDownload(List<IFSTreeNode> nodes, File destination, IConfirmCallback confirmCallback) {
return new OpCopyLocal(nodes, destination, confirmCallback);
}
@Override
public IResultOperation<IFSTreeNode> operationRestoreFromPath(String path) {
return new OpParsePath(fPeerNode, path);
}
public static IPeerNode getPeerFromPath(String path) {
String cacheRoot = CacheManager.getCacheRoot().getAbsolutePath();
if (!path.startsWith(cacheRoot))
return null;
path = path.substring(cacheRoot.length() + 1);
int slash = path.indexOf(File.separator);
if (slash == -1)
return null;
String peerId = path.substring(0, slash);
peerId = peerId.replace(CacheManager.PATH_ESCAPE_CHAR, ':');
for (IPeerNode peer : getPeerModel().getPeerNodes()) {
if (peerId.equals(peer.getPeerId()))
return peer;
}
return null;
}
@Override
public IResultOperation<IFSTreeNode[]> operationRestoreFavorites() {
return new OpRestoreFavorites(this);
}
@Override
public IChannel getChannel() {
return fChannel;
}
public IFileSystem getFileSystem() {
return fFileSystem;
}
}