001 package org.meta_environment.eclipse.files;
002
003 import java.io.ByteArrayInputStream;
004 import java.io.File;
005
006 import org.eclipse.core.resources.IFile;
007 import org.eclipse.core.resources.IFolder;
008 import org.eclipse.core.resources.IProject;
009 import org.eclipse.core.resources.IResource;
010 import org.eclipse.core.resources.IResourceChangeEvent;
011 import org.eclipse.core.resources.IResourceChangeListener;
012 import org.eclipse.core.resources.IResourceDelta;
013 import org.eclipse.core.resources.IResourceDeltaVisitor;
014 import org.eclipse.core.resources.ResourcesPlugin;
015 import org.eclipse.core.runtime.CoreException;
016 import org.eclipse.core.runtime.IPath;
017 import org.eclipse.core.runtime.NullProgressMonitor;
018 import org.eclipse.core.runtime.Path;
019 import org.eclipse.imp.language.Language;
020 import org.eclipse.imp.language.LanguageRegistry;
021 import org.eclipse.imp.runtime.RuntimePlugin;
022
023 import toolbus.adapter.eclipse.EclipseTool;
024 import aterm.ATerm;
025 import aterm.pure.binary.BinaryWriter;
026
027 public class ResourceChanges extends EclipseTool implements IResourceChangeListener {
028 private static final String BIN_FOLDER = "bin";
029 private static final String EXTENSION_SEPARATOR = ".";
030
031 private static class InstanceKeeper {
032 private static ResourceChanges sInstance = new ResourceChanges();
033 static{
034 sInstance.connect();
035 }
036 }
037
038 private ResourceChanges() {
039 super("resource-changes");
040 ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
041 }
042
043 static public ResourceChanges getInstance() {
044 return InstanceKeeper.sInstance;
045 }
046
047 public void resourceChanged(IResourceChangeEvent event) {
048 IResourceDelta[] deltas = event.getDelta().getAffectedChildren();
049
050 try {
051 for (IResourceDelta d : deltas) {
052
053 d.accept(new IResourceDeltaVisitor() {
054 public boolean visit(IResourceDelta delta)
055 throws CoreException {
056 IResource resource = delta.getResource();
057
058 if (resource instanceof IFile) {
059 IPath path = resource.getLocation();
060
061 Language l = LanguageRegistry.findLanguage(path,
062 null);
063
064 if (l != null) {
065 switch (delta.getKind()) {
066 case IResourceDelta.OPEN:
067 fileCreated(l, resource);
068 break;
069 case IResourceDelta.ADDED:
070 fileCreated(l, resource);
071 break;
072 case IResourceDelta.CHANGED:
073 if ((delta.getFlags() & IResourceDelta.CONTENT) != 0) {
074 fileChanged(l, resource);
075 }
076 break;
077 case IResourceDelta.REMOVED:
078 fileRemovedEvent(l, resource);
079 break;
080 }
081 }
082 return false;
083 }
084 return true;
085 }
086 });
087
088 }
089 } catch (CoreException e) {
090 e.printStackTrace();
091 }
092 }
093
094 private void fileCreated(Language l, IResource resource) {
095
096 if (l != null && !resource.isDerived() && resource.isAccessible()) {
097 sendEvent(factory.make("create-module(<str>,<str>)", l.getName(),
098 resource.getLocation().toOSString()));
099 }
100 }
101
102 private void fileRemovedEvent(Language l, IResource resource) {
103 if (l != null) {
104 sendEvent(factory.make("delete-module(<str>,<str>)", l.getName(),
105 resource.getLocation().toOSString()));
106 }
107
108 }
109
110 private void fileChanged(Language l, IResource resource) {
111 if (l != null) {
112 sendEvent(factory.make("build-module(<str>,<str>)", l.getName(),
113 resource.getLocation().toOSString()
114 ));
115 }
116 }
117
118 public void saveBuild(String sourcePathStr, String targetExt, String content) {
119 try {
120 IFile targetFile = getTargetFile(sourcePathStr, targetExt);
121
122 if (targetFile != null) {
123 if (targetFile.exists()) {
124 targetFile.setContents(new ByteArrayInputStream(content.getBytes()),
125 IResource.FORCE,
126 new NullProgressMonitor());
127 }
128 else {
129 targetFile.create(new ByteArrayInputStream(content.getBytes()), IResource.FORCE,
130 new NullProgressMonitor());
131 }
132
133 targetFile.setDerived(true);
134 }
135 }
136 catch (CoreException e) {
137 RuntimePlugin.getInstance().logException("could not save build for " + sourcePathStr, e);
138 }
139 catch (Exception e) {
140 RuntimePlugin.getInstance().logException("could not save build for " + sourcePathStr, e);
141 }
142 }
143
144 public void saveBuild(String sourcePathStr, String targetExt, ATerm content) {
145 try {
146 IFile targetFile = getTargetFile(sourcePathStr, targetExt);
147
148 if (targetFile != null) {
149
150 BinaryWriter.writeTermToSAFFile(decode(content), new File(targetFile.getLocation().toOSString()));
151
152 targetFile.refreshLocal(0, new NullProgressMonitor());
153 targetFile.setDerived(true);
154 }
155 }
156 catch (CoreException e) {
157 RuntimePlugin.getInstance().logException("could not save build for " + sourcePathStr, e);
158 }
159 catch (Exception e) {
160 RuntimePlugin.getInstance().logException("could not save build for " + sourcePathStr, e);
161 }
162 }
163
164 public void cleanBuild(String sourcePathStr, String targetExt) {
165
166 try {
167 IFile targetFile = getTargetFile(sourcePathStr, targetExt);
168
169 if (targetFile != null && targetFile.exists()) {
170 targetFile.delete(true, false, new NullProgressMonitor());
171 System.err.println("Resources: cleaned " + targetFile);
172 }
173 } catch (CoreException e) {
174 RuntimePlugin.getInstance().logException("could not clean build for " + sourcePathStr, e);
175 }
176 }
177
178 private IFile getTargetFile(String sourcePathStr, String targetExt)
179 throws CoreException {
180 IFile sourceFile = getFile(sourcePathStr);
181
182 while (targetExt.startsWith(EXTENSION_SEPARATOR)) {
183 targetExt = targetExt.substring(1);
184 }
185
186 if (sourceFile != null) {
187 IProject project = sourceFile.getProject();
188 IPath sourcePath = sourceFile.getProjectRelativePath();
189 IFolder binFolder = project.getFolder(BIN_FOLDER);
190 IPath targetPath = binFolder.getProjectRelativePath().append(sourcePath.removeFileExtension()
191 .addFileExtension(targetExt));
192
193 IPath current = Path.ROOT;
194 for (String segment : targetPath.removeLastSegments(1).segments()) {
195 current = current.append(segment);
196 IFolder path = project.getFolder(current);
197 if (!path.exists()) {
198 path.create(true, true, null);
199 }
200 }
201
202 IFile targetFile = sourceFile.getProject().getFile(targetPath);
203
204 return targetFile;
205 }
206
207 return null;
208 }
209
210 private IFile getFile(String source) {
211 return ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(source));
212 }
213 }