001    package org.meta_environment.eclipse.files;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.File;
005    import java.io.IOException;
006    
007    import org.eclipse.core.resources.IFile;
008    import org.eclipse.core.resources.IFolder;
009    import org.eclipse.core.resources.IProject;
010    import org.eclipse.core.resources.IResource;
011    import org.eclipse.core.resources.ResourcesPlugin;
012    import org.eclipse.core.runtime.CoreException;
013    import org.eclipse.core.runtime.IPath;
014    import org.eclipse.core.runtime.NullProgressMonitor;
015    import org.eclipse.core.runtime.Path;
016    import org.eclipse.imp.runtime.RuntimePlugin;
017    import org.eclipse.imp.utils.StreamUtils;
018    
019    import toolbus.adapter.eclipse.EclipseTool;
020    import aterm.ATerm;
021    import aterm.pure.binary.BinaryWriter;
022    
023    public class BuildResults extends EclipseTool {
024            private static final String BIN_FOLDER = "bin";
025            private static final String EXTENSION_SEPARATOR = ".";
026    
027            private static class InstanceKeeper {
028                    private static BuildResults sInstance = new BuildResults();
029                    static {
030                            sInstance.connect();
031                    }
032            }
033    
034            private BuildResults() {
035                    super("build-results");
036            }
037    
038            static public BuildResults getInstance() {
039                    return InstanceKeeper.sInstance;
040            }
041    
042            public void saveBuild(String sourcePathStr, String targetExt, String content) {
043                    try {
044                            IFile targetFile = getTargetFile(sourcePathStr, targetExt);
045    
046                            if (targetFile != null) {
047                                    if (targetFile.exists()) {
048                                            targetFile.setContents(new ByteArrayInputStream(content
049                                                            .getBytes()), IResource.FORCE,
050                                                            new NullProgressMonitor());
051                                    } else {
052                                            targetFile.create(new ByteArrayInputStream(content
053                                                            .getBytes()), IResource.FORCE,
054                                                            new NullProgressMonitor());
055                                    }
056    
057                                    targetFile.setDerived(true);
058                            }
059                    } catch (CoreException e) {
060                            RuntimePlugin.getInstance().logException(
061                                            "could not save build for " + sourcePathStr, e);
062                    } catch (Exception e) {
063                            RuntimePlugin.getInstance().logException(
064                                            "could not save build for " + sourcePathStr, e);
065                    }
066            }
067    
068            public void saveBuild(String sourcePathStr, String targetExt, ATerm content) {
069                    try {
070                            IFile targetFile = getTargetFile(sourcePathStr, targetExt);
071    
072                            if (targetFile != null) {
073    
074                                    BinaryWriter.writeTermToSAFFile(decode(content), new File(
075                                                    targetFile.getLocation().toOSString()));
076    
077                                    targetFile.refreshLocal(0, new NullProgressMonitor());
078                                    targetFile.setDerived(true);
079                            }
080                    } catch (CoreException e) {
081                            RuntimePlugin.getInstance().logException(
082                                            "could not save build for " + sourcePathStr, e);
083                    } catch (Exception e) {
084                            RuntimePlugin.getInstance().logException(
085                                            "could not save build for " + sourcePathStr, e);
086                    }
087            }
088    
089            public void cleanBuild(String sourcePathStr, String targetExt) {
090    
091                    try {
092                            IFile targetFile = getTargetFile(sourcePathStr, targetExt);
093    
094                            if (targetFile != null && targetFile.exists()) {
095                                    targetFile.delete(true, false, new NullProgressMonitor());
096                                    System.err.println("Resources: cleaned " + targetFile);
097                            }
098                    } catch (CoreException e) {
099                            RuntimePlugin.getInstance().logException(
100                                            "could not clean build for " + sourcePathStr, e);
101                    }
102            }
103    
104            public ATerm loadBuild(String sourcePathStr, String targetExt) {
105                    try {
106                            IFile targetFile = getTargetFile(sourcePathStr, targetExt);
107    
108                            if (targetFile != null && targetFile.exists()) {
109                                    ATerm build = getFactory().readFromFile(
110                                                    targetFile.getLocation().toOSString());
111    
112                                    return getFactory().make("build(<term>)", build);
113                            }
114                    } catch (CoreException e) {
115                            RuntimePlugin.getInstance().logException(
116                                            "could not get build for " + sourcePathStr, e);
117                    } catch (IOException e) {
118                            RuntimePlugin.getInstance().logException(
119                                            "could not get build for " + sourcePathStr, e);
120                    }
121    
122                    return getFactory().make("build(undefined)");
123            }
124    
125            public ATerm loadStrBuild(String sourcePathStr, String targetExt) {
126                    try {
127                            IFile targetFile = getTargetFile(sourcePathStr, targetExt);
128    
129                            if (targetFile != null && targetFile.exists()) {
130                                    String content = StreamUtils.readStreamContents(targetFile
131                                                    .getContents());
132                                    return getFactory().make("build(<str>)", content);
133                            }
134                    } catch (CoreException e) {
135                            RuntimePlugin.getInstance().logException(
136                                            "could not get build for " + sourcePathStr, e);
137                    }
138    
139                    return getFactory().make("build(\"***build-not-found***\")");
140            }
141    
142            private IFile getTargetFile(String sourcePathStr, String targetExt)
143                            throws CoreException {
144                    IFile sourceFile = getFile(sourcePathStr);
145    
146                    while (targetExt.startsWith(EXTENSION_SEPARATOR)) {
147                            targetExt = targetExt.substring(1);
148                    }
149                    
150                    if (sourceFile != null) {
151                        return createTargetFile(targetExt, sourceFile);
152                    }
153                    return createLibraryTargetFile(sourcePathStr, targetExt);
154            }
155    
156            private IFile createTargetFile(String targetExt, IFile sourceFile)
157                            throws CoreException {
158                    IProject project;
159                    IPath targetPath;
160                    project = sourceFile.getProject();
161                    IFolder binFolder = project.getFolder(BIN_FOLDER);
162                    
163                    IPath sourcePath = sourceFile.getProjectRelativePath();
164                    targetPath = binFolder.getProjectRelativePath().append(
165                                    sourcePath.removeFileExtension().addFileExtension(targetExt));
166                    
167                    return createFile(project, targetPath);
168            }
169    
170            /**
171             * Workaround for not having a feature for libraries. As a heuristic,
172             * we recognize libraries if they are in a "library" subdir and store
173             * the build results in "tmp" project.
174             * 
175             * TODO remove this code and have an implementation of a search path with jars
176             */
177            private IFile createLibraryTargetFile(String sourcePathStr, String targetExt)
178                            throws CoreException {
179                    IProject project;
180                    IPath targetPath;
181                    
182                    project = ResourcesPlugin.getWorkspace().getRoot().getProject("tmp");
183                    if (!project.exists()) {
184                            project.create(null);
185                    }
186                    else if (!project.isOpen()) {
187                            project.open(null);
188                    }
189                    
190                    IFolder binFolder = project.getFolder(BIN_FOLDER);
191    
192                    int libIndex = sourcePathStr.indexOf(File.separator + "library");
193                    if (libIndex != -1) {
194                            sourcePathStr = sourcePathStr.substring(libIndex + "library".length() + 1);
195    
196                            targetPath = binFolder.getProjectRelativePath().append(sourcePathStr).removeFileExtension().addFileExtension(targetExt);
197    
198                            return createFile(project, targetPath);
199                    }
200                    
201                    return null;
202            }
203    
204            private IFile createFile(IProject project, IPath targetPath)
205                            throws CoreException {
206                    IPath current = Path.ROOT;
207                    for (String segment : targetPath.removeLastSegments(1).segments()) {
208                            current = current.append(segment);
209                            IFolder path = project.getFolder(current);
210                            if (!path.exists()) {
211                                    path.create(true, true, null);
212                            }
213                    }
214    
215                    IFile targetFile = project.getFile(targetPath);
216                    return targetFile;
217            }
218    
219            private IFile getFile(String source) {
220                    return ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
221                                    new Path(source));
222            }
223    }