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    }