package org.rubypeople.rdt.internal.core; import java.io.CharArrayReader; import java.io.File; import java.io.IOException; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.jruby.ast.Node; import org.jruby.lexer.yacc.SyntaxException; import org.rubypeople.rdt.core.IBuffer; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.core.WorkingCopyOwner; import org.rubypeople.rdt.core.util.Util; import org.rubypeople.rdt.internal.core.buffer.BufferManager; import org.rubypeople.rdt.internal.core.parser.RubyParser; public class ExternalRubyScript extends RubyScript { public ExternalRubyScript(ExternalSourceFolder parent, String name, WorkingCopyOwner owner) { super(parent, name, owner); } @Override protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws RubyModelException { RubyScriptElementInfo unitInfo = (RubyScriptElementInfo) info; // get buffer contents IBuffer buffer = getBufferManager().getBuffer(this); if (buffer == null) { buffer = openBuffer(pm, unitInfo); // open buffer independently // from the info, since we are // building the info } final char[] contents = buffer == null ? null : buffer.getCharacters(); try { RubyScriptStructureBuilder visitor = new RubyScriptStructureBuilder(this, unitInfo, newElements); SourceElementParser sp = new SourceElementParser(visitor); sp.parse(contents, null); unitInfo.setIsStructureKnown(true); } catch (SyntaxException e) { unitInfo.setIsStructureKnown(false); unitInfo.setSyntaxException(e) ; } catch (Exception e) { RubyCore.log(e); } return unitInfo.isStructureKnown(); } @Override public boolean exists() { return getFile().exists(); } /** * Opens and returns buffer on the source code associated with this class file. * Maps the source code to the children elements of this class file. * If no source code is associated with this class file, * <code>null</code> is returned. * * @see Openable */ protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws RubyModelException { char[] contents = findSource(); if (contents != null) { // create buffer IBuffer buffer = getBufferManager().createBuffer(this); if (buffer == null) return null; BufferManager bufManager = getBufferManager(); bufManager.addBuffer(buffer); // set the buffer source if (buffer.getCharacters() == null){ buffer.setContents(contents); } // listen to buffer changes buffer.addBufferChangedListener(this); return buffer; } return null; } public File getFile() { ExternalSourceFolder parent = (ExternalSourceFolder) getParent(); IPath parentPath = parent.getPath(); return parentPath.append(name).toFile(); } private char[] findSource() { String source = null; try { source = getSource(); } catch (RubyModelException e) { RubyCore.log(e); } if (source == null) return new char[0]; return source.toCharArray(); } @Override public IResource getResource() { // TODO Auto-generated method stub return null; } @Override public IPath getPath() { return getParent().getPath().append(getElementName()); } @Override public String getSource() throws RubyModelException { File file = getFile(); if (!file.exists()) return null; byte[] bytes; try { bytes = Util.getFileByteContent(file); } catch (IOException e) { RubyCore.log(e); return null; } return new String(bytes); } }