/******************************************************************************* * Copyright (c) 2005, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ package org.eclipse.dltk.internal.core; import java.io.File; import java.util.ArrayList; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.IBuildpathContainer; import org.eclipse.dltk.core.IBuildpathContainerExtension; import org.eclipse.dltk.core.IBuildpathEntry; import org.eclipse.dltk.core.IBuiltinModuleProvider; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.IModelStatusConstants; import org.eclipse.dltk.core.IProjectFragment; import org.eclipse.dltk.core.IScriptFolder; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.core.WorkingCopyOwner; import org.eclipse.dltk.internal.core.util.MementoTokenizer; import org.eclipse.dltk.internal.core.util.Util; /** * Project fragment for buildpath script folders and modules. * * @author haiodo * */ public class BuiltinProjectFragment extends ProjectFragment { public final static ArrayList EMPTY_LIST = new ArrayList(); static final Object INTERPRETER_CONTAINER = "org.eclipse.dltk.launching.INTERPRETER_CONTAINER"; //$NON-NLS-1$ protected final IPath fPath; IBuiltinModuleProvider builtinProvider; /** * Maps folder names and source module names. */ protected BuiltinProjectFragment(IPath path, ScriptProject project) { super(null, project); this.fPath = path; builtinProvider = getBuiltinProvider(project); } public static IBuiltinModuleProvider getBuiltinProvider( IScriptProject project) { try { IBuildpathEntry[] entries = project.getRawBuildpath(); IPath containerPath = null; for (int i = 0; i < entries.length; i++) { if (entries[i].getEntryKind() == IBuildpathEntry.BPE_CONTAINER) { IPath path = entries[i].getPath(); if (path.segment(0).equals(INTERPRETER_CONTAINER)) { containerPath = entries[i].getPath(); break; } } } if (containerPath == null) { return null; } IBuildpathContainer buildpathContainer = ModelManager .getModelManager().getBuildpathContainer(containerPath, project); if (buildpathContainer != null && buildpathContainer instanceof IBuildpathContainerExtension) { return ((IBuildpathContainerExtension) buildpathContainer) .getBuiltinProvider(); } } catch (CoreException ex) { if (DLTKCore.DEBUG) { ex.printStackTrace(); } } return null; } public static boolean isSupported(IScriptProject project) { IBuiltinModuleProvider prov = getBuiltinProvider(project); return prov != null && prov.getBuiltinModules() != null; } /** * Compute the package fragment children of this package fragment root. */ @Override protected boolean computeChildren(OpenableElementInfo info, Map newElements) throws ModelException { ArrayList vChildren = new ArrayList(5); ArrayList vForeign = new ArrayList(5); char[][] inclusionPatterns = fullInclusionPatternChars(); char[][] exclusionPatterns = fullExclusionPatternChars(); computeFolderChildren(this.fPath, !Util.isExcluded(this.fPath, inclusionPatterns, exclusionPatterns, true), vChildren, vForeign, newElements, inclusionPatterns, exclusionPatterns); IModelElement[] children = new IModelElement[vChildren.size()]; vChildren.toArray(children); info.setChildren(children); return true; } /** * Starting at this folder, create folders and add them to the collection of * children. * * @param newElements * * @exception ModelException * The resource associated with this project fragment does * not exist */ protected void computeFolderChildren(IPath path, boolean isIncluded, ArrayList vChildren, ArrayList vForeign, Map newElements, char[][] inclusionPatterns, char[][] exclusionPatterns) throws ModelException { BuiltinScriptFolder fldr = (BuiltinScriptFolder) getScriptFolder(Path.EMPTY); vChildren.add(fldr); if (this.builtinProvider == null) { return; } try { BuiltinScriptFolderInfo fragInfo = new BuiltinScriptFolderInfo(); fldr.computeChildren(fragInfo, this.builtinProvider.getBuiltinModules()); fldr.computeForeignResources(fragInfo); newElements.put(fldr, fragInfo); } catch (IllegalArgumentException e) { throw new ModelException(e, IModelStatusConstants.ELEMENT_DOES_NOT_EXIST); /* * could be thrown by ElementTree when path is not found */ } } @Override public IScriptFolder getScriptFolder(IPath path) { try { String portablePath = path.toPortableString(); IModelElement[] children = getChildren(); for (int i = 0; i < children.length; ++i) { IModelElement child = children[i]; if (child.getElementType() == SCRIPT_FOLDER && ((IScriptFolder) child).getElementName().equals( portablePath)) { return ((IScriptFolder) child); } } } catch (ModelException e) { if (DLTKCore.DEBUG) { e.printStackTrace(); } } return new BuiltinScriptFolder(this, path); } @Override public IScriptFolder getScriptFolder(String path) { return getScriptFolder(new Path(path)); } @Override public boolean isReadOnly() { return true; } @Override protected Object createElementInfo() { return new BuiltinProjectFragmentInfo(); } @Override public boolean isArchive() { return false; } @Override public boolean isExternal() { return true; } @Override public boolean isBuiltin() { return true; } @Override public IResource getUnderlyingResource() throws ModelException { return null; } @Override public int hashCode() { return this.fPath.hashCode(); } @Override public IPath getPath() { if (isExternal()) { return this.fPath; } else { return super.getPath(); } } @Override public IResource getResource() { return null; } /** * Returns whether the corresponding resource or associated file exists */ @Override protected boolean resourceExists() { return true; } @Override protected void toStringAncestors(StringBuffer buffer) { if (isExternal()) return; super.toStringAncestors(buffer); } @Override public int getKind() { return IProjectFragment.K_SOURCE; } @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof BuiltinProjectFragment) { BuiltinProjectFragment other = (BuiltinProjectFragment) o; return this.fPath.equals(other.fPath); } return false; } @Override public String getElementName() { return fPath.toOSString().replace(File.separatorChar, JEM_SKIP_DELIMETER); } @Override public void getHandleMemento(StringBuffer buff) { ((ModelElement) getParent()).getHandleMemento(buff); buff.append(getHandleMementoDelimiter()); escapeMementoName(buff, getElementName()); } @Override public IModelElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { switch (token.charAt(0)) { case JEM_SCRIPTFOLDER: String pkgName; if (memento.hasMoreTokens()) { pkgName = memento.nextToken(); char firstChar = pkgName.charAt(0); if (firstChar == JEM_SOURCEMODULE || firstChar == JEM_COUNT) { token = pkgName; pkgName = IProjectFragment.DEFAULT_SCRIPT_FOLDER_NAME; } else { token = null; } } else { pkgName = IScriptFolder.DEFAULT_FOLDER_NAME; token = null; } ModelElement pkg = (ModelElement) getScriptFolder(pkgName); if (token == null) { return pkg.getHandleFromMemento(memento, owner); } else { return pkg.getHandleFromMemento(token, memento, owner); } } return null; } @Override protected char getHandleMementoDelimiter() { return JEM_PROJECTFRAGMENT; } @Override public IBuildpathEntry getRawBuildpathEntry() throws ModelException { IBuildpathEntry rawEntry = null; ScriptProject project = (ScriptProject) this.getScriptProject(); project.getResolvedBuildpath(); // force the reverse rawEntry cache to // be populated Map<IPath, IBuildpathEntry> rootPathToRawEntries = project .getPerProjectInfo().rootPathToRawEntries; if (rootPathToRawEntries != null) { rawEntry = rootPathToRawEntries.get(this.getPath()); } if (rawEntry == null) { throw new ModelException(new ModelStatus( IModelStatusConstants.ELEMENT_NOT_ON_BUILDPATH, this)); } return rawEntry; } @Override public IBuildpathEntry getBuildpathEntry() throws ModelException { ScriptProject project = (ScriptProject) this.getScriptProject(); IBuildpathEntry rawEntry = getRawBuildpathEntry(); // try to guest map from internal element. if (rawEntry != null && rawEntry.getEntryKind() == IBuildpathEntry.BPE_CONTAINER) { IBuildpathContainer container = DLTKCore.getBuildpathContainer( rawEntry.getPath(), project); IBuildpathEntry entrys[] = container.getBuildpathEntries(); for (int i = 0; i < entrys.length; ++i) { if (entrys[i].getPath().equals( new Path(this.getPath().segment(0)))) { return entrys[i]; } } } return rawEntry; } /* * Validate whether this project fragment is on the buildpath of its * project. */ @Override protected IStatus validateOnBuildpath() { return Status.OK_STATUS; } @Override public boolean exists() { return true; } public long lastModified() { return builtinProvider != null ? builtinProvider.lastModified() : 0; } }