package monolipse.core.internal; import java.io.*; import java.util.*; import monolipse.core.*; import monolipse.core.foundation.*; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.jdt.core.*; import com.thoughtworks.xstream.*; import com.thoughtworks.xstream.io.xml.*; public class BooAssemblySource implements IAssemblySource { private static final String SETTINGS_CHARSET = "utf-8"; private static final String SETTINGS_FILE = ".monolipse"; private static final QualifiedName ASSEMBLY_SOURCE_SESSION_KEY = new QualifiedName("monolipse.core.resources", "BooAssemblySourceSession"); public static IAssemblySource create(IFolder folder, AssemblySourceLanguage language) throws CoreException { synchronized (folder) { IAssemblySource source = BooAssemblySource.get(folder); if (null != source) return source; source = internalCreate(folder, language); source.save(null); return source; } } public static BooAssemblySource get(IFolder folder) throws CoreException { synchronized (folder) { BooAssemblySource source = (BooAssemblySource) folder.getSessionProperty(ASSEMBLY_SOURCE_SESSION_KEY); if (source == null) { if (isAssemblySource(folder)) { source = internalCreate(folder, null); } } return source; } } private static BooAssemblySource internalCreate(IFolder folder, AssemblySourceLanguage defaultLanguage) throws CoreException { BooAssemblySource source = new BooAssemblySource(folder, defaultLanguage); folder.setSessionProperty(ASSEMBLY_SOURCE_SESSION_KEY, source); return source; } public static boolean isAssemblySource(Object element) { try { return element instanceof IFolder && BooAssemblySource.isAssemblySource((IFolder)element); } catch (CoreException x) { x.printStackTrace(); } return false; } public static boolean isAssemblySource(IFolder folder) throws CoreException { return folder.getFile(SETTINGS_FILE).exists(); } private IFolder _folder; private IAssemblyReference[] _references; private String _outputType; private AssemblySourceLanguage _language; private IFolder _outputFolder; private String _additionalOptions; BooAssemblySource(IFolder folder, AssemblySourceLanguage defaultLanguage) throws CoreException { if (null == folder || !folder.exists()) throw new IllegalArgumentException(); _folder = folder; _language = defaultLanguage; _outputFolder = null; refresh(null); } public void setLanguage(AssemblySourceLanguage language) { _language = language; } public AssemblySourceLanguage getLanguage() { return _language == null ? AssemblySourceLanguage.BOO : _language; } public void setOutputFolder(IFolder folder) { _outputFolder = folder; } public IFolder getOutputFolder() throws CoreException { return _outputFolder != null ? _outputFolder : defaultOutputFolder(); } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#getFolder() */ public IFolder getFolder() { return _folder; } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#getSourceFiles() */ public IFile[] getSourceFiles() throws CoreException { final List<IResource> files = new ArrayList<IResource>(); IResourceVisitor visitor = new IResourceVisitor() { public boolean visit(IResource resource) throws CoreException { if (isBooFile(resource) && resource.exists()) { files.add(resource); } return true; } }; _folder.accept(visitor, IResource.DEPTH_INFINITE, IResource.FILE); return files.toArray(new IFile[files.size()]); } @SuppressWarnings({ "rawtypes", "unchecked" }) public Object getAdapter(Class adapter) { if (adapter.isAssignableFrom(IFolder.class)) { return _folder; } return null; } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#setReferences(monolipse.core.IBooAssemblyReference[]) */ public void setReferences(IAssemblyReference... references) { if (null == references) throw new IllegalArgumentException("references"); _references = references; } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#getReferences() */ public IAssemblyReference[] getReferences() { return _references; } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#getOutputType() */ public String getOutputType() { return _outputType; } public void setOutputType(String outputType) { if (null == outputType) throw new IllegalArgumentException(); if (!outputType.equals(OutputType.CONSOLE_APPLICATION) && !outputType.equals(OutputType.WINDOWS_APPLICATION) && !outputType.equals(OutputType.LIBRARY)) { throw new IllegalArgumentException("outputType"); } _outputType = outputType; } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#getOutputFile() */ public IFile getOutputFile() throws CoreException { return getOutputFolder().getFile(assemblyFileName()); } private String assemblyFileName() { return assemblyName() + getOutputAssemblyExtension(); } private String assemblyName() { return _folder.getName(); } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#refresh(org.eclipse.core.runtime.IProgressMonitor) */ public void refresh(IProgressMonitor monitor) throws CoreException { IWorkspaceRunnable action = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { IFile file = getSettingsFile(); file.refreshLocal(IResource.DEPTH_ZERO, monitor); if (!file.exists()) { useDefaultSettings(); save(monitor); } else { loadSettingsFrom(file); } } }; ResourcesPlugin.getWorkspace().run(action, monitor); } static public class AssemblySourceRemembrance { public String language; public String outputType; public IRemembrance[] references; public String outputFolder; public String additionalOptions; public AssemblySourceRemembrance(BooAssemblySource source) throws CoreException { language = source.getLanguage().id(); outputType = source.getOutputType(); references = new IRemembrance[source._references.length]; outputFolder = source.hasOutputFolder() ? source.getOutputFolder().getFullPath().toPortableString() : null; additionalOptions = source.getAdditionalOptions(); for (int i=0; i<references.length; ++i) { references[i] = source._references[i].getRemembrance(); } } /** * public no arg constructor for xstream deserialization * on less capable virtual machines. */ public AssemblySourceRemembrance() { } public IAssemblyReference[] activateReferences() throws CoreException { IAssemblyReference[] asmReferences = new IAssemblyReference[references.length]; for (int i=0; i<asmReferences.length; ++i) { asmReferences[i] = activateReference(references[i]); } return asmReferences; } private IAssemblyReference activateReference(IRemembrance ref) { try { return (IAssemblyReference) ref.activate(); } catch (CoreException e) { return new AssemblyReferenceError(e, ref); } } } /* (non-Javadoc) * @see monolipse.core.IBooAssemblySource#save() */ public void save(IProgressMonitor monitor) throws CoreException { XStream stream = createXStream(); String xml = stream.toXML(new AssemblySourceRemembrance(this)); IFile file = getSettingsFile(); if (!file.exists()) { file.create(encode(xml), true, monitor); file.setCharset(SETTINGS_CHARSET, monitor); } else { file.setContents(encode(xml), true, true, monitor); } } public boolean hasOutputFolder() { return _outputFolder != null; } private void loadSettingsFrom(IFile file) throws CoreException { AssemblySourceRemembrance remembrance = (AssemblySourceRemembrance) createXStream().fromXML(decode(file)); String language = remembrance.language; _language = isEmptyOrNull(language) ? AssemblySourceLanguage.BOO : AssemblySourceLanguage.forId(language); _outputType = remembrance.outputType; _references = remembrance.activateReferences(); _additionalOptions = remembrance.additionalOptions; String path = remembrance.outputFolder; _outputFolder = isEmptyOrNull(path) ? null : WorkspaceUtilities.getFolder(path); } private boolean isEmptyOrNull(String language) { return language == null || language.length() == 0; } private IFile getSettingsFile() { return _folder.getFile(SETTINGS_FILE); } private XStream createXStream() { XStream stream = new XStream(new DomDriver()); stream.alias("settings", AssemblySourceRemembrance.class); return stream; } private InputStream encode(String xml) throws CoreException { try { return new ByteArrayInputStream(xml.getBytes(SETTINGS_CHARSET)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); WorkspaceUtilities.throwCoreException(e); } return null; } private Reader decode(IFile file) throws CoreException { try { return new InputStreamReader(file.getContents(), file.getCharset()); } catch (IOException e) { e.printStackTrace(); WorkspaceUtilities.throwCoreException(e); } return null; } private void useDefaultSettings() { _references = getLanguage() == AssemblySourceLanguage.BOO ? defaultBooAssemblyReferences() : new IAssemblyReference[0]; _outputType = OutputType.CONSOLE_APPLICATION; } private IAssemblyReference[] defaultBooAssemblyReferences() { return new IAssemblyReference[] { BooCore.createBooAssemblyReference("Boo.Lang"), BooCore.createBooAssemblyReference("Boo.Lang.PatternMatching") }; } private String getOutputAssemblyExtension() { if (getLanguage() == AssemblySourceLanguage.BOOJAY) return ".jar"; return OutputType.LIBRARY.equals(getOutputType()) ? ".dll" : ".exe"; } boolean isBooFile(IResource resource) { if (IResource.FILE != resource.getType()) return false; final String extension = resource.getFileExtension(); if (extension == null) return false; return extension.equalsIgnoreCase(expectedSourceFileExtension()); } private String expectedSourceFileExtension() { return getLanguage().fileExtension(); } public static IAssemblySource getContainer(IResource resource) throws CoreException { IContainer parent = resource instanceof IContainer ? (IContainer)resource : resource.getParent(); while (null != parent && IResource.FOLDER == parent.getType()) { BooAssemblySource source = get((IFolder)parent); if (null != source) return source; parent = parent.getParent(); } return null; } public boolean visitReferences(IAssemblyReferenceVisitor visitor) throws CoreException { for (IAssemblyReference r : _references) if (!r.accept(visitor)) return false; return true; } public String toString() { return _folder.getFullPath().toString(); } public static boolean references(IAssemblySource l, final IAssemblySource r) { IAssemblyReference[] references = l.getReferences(); for (int i = 0; i < references.length; ++i) { IAssemblyReference reference = references[i]; if (reference instanceof IAssemblySourceReference) { if (r == ((IAssemblySourceReference) reference).getAssemblySource()) { return true; } } } return false; } public String getAdditionalOptions() { return _additionalOptions == null ? "" : _additionalOptions; } public void setAdditionalOptions(String additionalOptions) { _additionalOptions = additionalOptions; } private IFolder defaultOutputFolder() throws CoreException { return _language == AssemblySourceLanguage.BOOJAY ? javaOutputFolder() : projectFolder("bin"); } private IFolder projectFolder(String path) { return project().getFolder(path); } private IFolder javaOutputFolder() throws JavaModelException { return workspaceFolder(javaProject().getOutputLocation()); } private IFolder workspaceFolder(IPath location) { return workspaceRoot().getFolder(location); } private IWorkspaceRoot workspaceRoot() { return workspace().getRoot(); } private IWorkspace workspace() { return project().getWorkspace(); } private IJavaProject javaProject() { return JavaCore.create(project()); } private IProject project() { return _folder.getProject(); } }