/******************************************************************************* * Copyright (c) 2013 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.graphfile.hack; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.URI; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFileState; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IPathVariableManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourceAttributes; 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.QualifiedName; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.graphfile.Activator; import org.simantics.graphfile.ontology.GraphFileResource; import org.simantics.layer0.Layer0; /** * This is an implementation of IFile that can be used to open external editor for any file. * (Original implementation (org.eclipse.core.filesystem.File) doesn't work without project/file structure) * * @author Marko Luukkainen * */ public class GraphFile implements IFile { private Resource fileResource; private IWorkspace workspace; public GraphFile(Resource fileResource, IWorkspace ws) { this.fileResource = fileResource; this.workspace = ws; } public Resource getFileResource() { return fileResource; } private String getResourceName() { try { return Simantics.getSession().syncRequest(new Read() { @Override public String perform(ReadGraph graph) throws DatabaseException { Layer0 l0 = Layer0.getInstance(graph); return graph.getPossibleRelatedValue(fileResource, l0.HasName); } }); } catch (DatabaseException e) { Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to get resource name: " + fileResource, e)); return e.getMessage(); } } private byte[] getResourceData() throws DatabaseException { return Simantics.getSession().syncRequest(new Read() { @Override public byte[] perform(ReadGraph graph) throws DatabaseException { return getResourceData(graph); } }); } private byte[] getResourceData(ReadGraph graph) throws DatabaseException { GraphFileResource gf = GraphFileResource.getInstance(graph); return graph.getRelatedValue(fileResource, gf.HasFiledata); } private long getResourceModificationTime() { try { return Simantics.getSession().syncRequest(new Read() { @Override public Long perform(ReadGraph graph) throws DatabaseException { return getResourceMofificationTime(graph); } }); } catch (DatabaseException e) { return IFile.NULL_STAMP; } } private long getResourceMofificationTime(ReadGraph graph) throws DatabaseException { GraphFileResource gf = GraphFileResource.getInstance(graph); long time = graph.getRelatedValue(fileResource, gf.LastModified); //System.out.println("Modification time is " + time + " " + fileResource); return time; } private void setResourceModificationTime(final long time) throws DatabaseException{ Simantics.getSession().syncRequest(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { setResourceModificationTime(graph, time); } }); } private void setResourceModificationTime(WriteGraph graph, long time) throws DatabaseException{ GraphFileResource gf = GraphFileResource.getInstance(graph); graph.claimLiteral(fileResource, gf.LastModified, time); //System.out.println("Modification time set to " + time + " " + fileResource); } @Override public void accept(IResourceProxyVisitor visitor, int memberFlags) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void accept(IResourceVisitor visitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void accept(IResourceVisitor visitor, int depth, boolean includePhantoms) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void accept(IResourceVisitor visitor, int depth, int memberFlags) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void accept(IResourceProxyVisitor visitor, int depth, int memberFlags) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void clearHistory(IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void copy(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void copy(IProjectDescription description, boolean force, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void copy(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public IMarker createMarker(String type) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public IResourceProxy createProxy() { return null; } @Override public void delete(boolean force, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void delete(int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void deleteMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public boolean exists() { return true; } @Override public IMarker findMarker(long id) throws CoreException { return null; } @Override public IMarker[] findMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { return null; } @Override public int findMaxProblemSeverity(String type, boolean includeSubtypes, int depth) throws CoreException { return 0; } @Override public String getFileExtension() { String name = getResourceName(); if (name == null) return null; int i = name.lastIndexOf("."); if (i > 0) return name.substring(i); else return null; } @Override public long getLocalTimeStamp() { return 0; } @Override public long setLocalTimeStamp(long value) throws CoreException { try { setResourceModificationTime(value); } catch (DatabaseException e) { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"GraphFile transaction error",e)); } return value; } @Override public IPath getLocation() { //return new Path(getResourceAbsolutePath()); return new GraphPath(this); } @Override public URI getLocationURI() { return null; } @Override public IMarker getMarker(long id) { return null; } @Override public long getModificationStamp() { return getResourceModificationTime(); } @Override public IContainer getParent() { return SystemProject.getDefault(); } @Override public String getPersistentProperty(QualifiedName key)throws CoreException { return null; } @Override public IProject getProject() { return SystemProject.getDefault(); } @Override public IPath getProjectRelativePath() { return null; } @Override public IPath getRawLocation() { //return new Path(getResourceAbsolutePath()); return new GraphPath(this); } @Override public URI getRawLocationURI() { return null; } @Override public ResourceAttributes getResourceAttributes() { return null; } @Override public Object getSessionProperty(QualifiedName key) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public int getType() { return IFile.FILE; } @Override public IWorkspace getWorkspace() { return workspace; } @Override public boolean isAccessible() { return true; } @Override public boolean isDerived() { return false; } @Override public boolean isLinked() { return false; } @Override public boolean isLinked(int options) { return false; } @Override public boolean isLocal(int depth) { return true; } @Override public boolean isPhantom() { return false; } @Override public boolean isSynchronized(int depth) { return true; // FIXME } @Override public boolean isTeamPrivateMember() { return false; } @Override public void move(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void move(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void move(IProjectDescription description, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void refreshLocal(int depth, IProgressMonitor monitor) throws CoreException { //throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void revertModificationStamp(long value) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setDerived(boolean isDerived) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setLocal(boolean flag, int depth, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setPersistentProperty(QualifiedName key, String value) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setReadOnly(boolean readOnly) { } @Override public void setResourceAttributes(ResourceAttributes attributes) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setSessionProperty(QualifiedName key, Object value) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setTeamPrivateMember(boolean isTeamPrivate) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void touch(IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @SuppressWarnings({ "rawtypes" }) @Override public Object getAdapter(Class adapter) { return null; } @Override public boolean contains(ISchedulingRule rule) { if (this.equals(rule)) return true; return false; } @Override public boolean isConflicting(ISchedulingRule rule) { if (this.equals(rule)) // TODO : check cached timestamp return true; return false; } @Override public void appendContents(InputStream source, boolean force,boolean keepHistory, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void appendContents(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void create(InputStream source, boolean force, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void create(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void createLink(IPath localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void createLink(URI location, int updateFlags, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void delete(boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public String getCharset() throws CoreException { return getCharset(true); } @Override public String getCharset(boolean checkImplicit) throws CoreException { // FIXME return "UTF-8"; } @Override public int getEncoding() throws CoreException { // FIXME return ENCODING_UTF_8; } @Override public String getCharsetFor(Reader reader) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public IContentDescription getContentDescription() throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public InputStream getContents() throws CoreException { return getContents(false); } @Override public InputStream getContents(boolean force) throws CoreException { try { return new ByteArrayInputStream(getResourceData()); } catch (DatabaseException e) { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"GraphFile transaction error",e)); } } @Override public IPath getFullPath() { //return new Path(getResourceAbsolutePath()); return new GraphPath(this); } @Override public IFileState[] getHistory(IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public String getName() { return getResourceName(); } @Override public boolean isReadOnly() { return false; } @Override public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setCharset(String newCharset, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setCharset(String newCharset) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public void setContents(IFileState source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { setContents(source.getContents(), force, keepHistory, monitor); setLocalTimeStamp(source.getModificationTime()); } @Override public void setContents(IFileState source, int updateFlags, IProgressMonitor monitor) throws CoreException { setContents(source.getContents(), updateFlags, monitor); setLocalTimeStamp(source.getModificationTime()); } @Override public void setContents(InputStream source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { setContents(source, (keepHistory ? KEEP_HISTORY : IResource.NONE) | (force ? FORCE : IResource.NONE), monitor); } @Override public void setContents(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException { final ByteArrayOutputStream os = new ByteArrayOutputStream(); try { byte buf[] = new byte[1024]; int count = 0; while ((count = source.read(buf)) > 0) { os.write(buf,0,count); } os.close(); Simantics.getSession().syncRequest(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { long time = System.currentTimeMillis(); GraphFileResource gf = GraphFileResource.getInstance(graph); graph.claimLiteral(fileResource, gf.HasFiledata, os.toByteArray()); setResourceModificationTime(graph, time); } }); } catch (DatabaseException e ) { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"GraphFile transaction error",e)); } catch (IOException e) { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"GraphFile IO error",e)); } } @SuppressWarnings({ "rawtypes" }) @Override public Map getPersistentProperties() throws CoreException { return null; } @SuppressWarnings({ "rawtypes" }) @Override public Map getSessionProperties() throws CoreException { return null; } @Override public boolean isDerived(int options) { return false; } @Override public boolean isHidden() { return false; } @Override public void setHidden(boolean isHidden) throws CoreException { } @Override public boolean isHidden(int options) { return false; } @Override public boolean isTeamPrivateMember(int options) { return false; } @Override public IPathVariableManager getPathVariableManager() { return null; } @Override public boolean isVirtual() { return false; } @Override public void setDerived(boolean isDerived, IProgressMonitor monitor) throws CoreException { throw new CoreException(new Status(Status.ERROR,Activator.PLUGIN_ID,"not supported")); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj.getClass() != getClass()) return false; GraphFile other = (GraphFile)obj; return fileResource.equals(other.fileResource); } @Override public int hashCode() { return fileResource.hashCode(); } }