/******************************************************************************* * 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.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.IBuildpathContainer; import org.eclipse.dltk.core.IBuildpathEntry; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.IModelStatusConstants; import org.eclipse.dltk.core.IProjectFragment; import org.eclipse.dltk.core.IProjectFragmentTimestamp; import org.eclipse.dltk.core.IScriptFolder; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.core.WorkingCopyOwner; import org.eclipse.dltk.core.environment.EnvironmentManager; import org.eclipse.dltk.core.environment.EnvironmentPathUtils; import org.eclipse.dltk.core.environment.IEnvironment; import org.eclipse.dltk.core.environment.IFileHandle; import org.eclipse.dltk.core.internal.environment.EFSFileHandle; import org.eclipse.dltk.internal.core.util.MementoTokenizer; import org.eclipse.dltk.internal.core.util.Util; /** * Project fragment to external source folder. * * @author haiodo * */ public class ExternalProjectFragment extends ProjectFragment implements IProjectFragmentTimestamp { public final static ArrayList EMPTY_LIST = new ArrayList(); /** * The path to the zip file (a workspace relative path if the archive is * internal, or an OS path if the archive is external) */ protected final IPath fPath; protected final boolean fReadOnly; protected final boolean fOnlyScriptResources; protected ExternalProjectFragment(IPath path, ScriptProject project, boolean isReadOnly, boolean onlyScriptResources) { super(null, project); this.fPath = path; this.fReadOnly = isReadOnly; this.fOnlyScriptResources = onlyScriptResources; } /** * 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 = this.fullInclusionPatternChars(); char[][] exclusionPatterns = this.fullExclusionPatternChars(); Set realPaths = new HashSet(); this.computeFolderChildren(this.fPath, !Util.isExcluded(this.fPath, inclusionPatterns, exclusionPatterns, true), vChildren, vForeign, newElements, inclusionPatterns, exclusionPatterns, realPaths); 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, Set realPaths) throws ModelException { IEnvironment environment = EnvironmentPathUtils .getPathEnvironment(path); if (environment != null) { IFileHandle file = environment.getFile(EnvironmentPathUtils .getLocalPath(path)); String canonicalPath = file.getCanonicalPath(); if (!realPaths.add(canonicalPath)) { return; } } IPath lpath = path.setDevice(null).removeFirstSegments( this.fPath.segmentCount()); ExternalScriptFolder fldr = (ExternalScriptFolder) this .getScriptFolder(lpath); boolean valid = Util.isValidSourcePackageName(this, path); if ((lpath.segmentCount() == 0 || valid) && isIncluded) { vChildren.add(fldr); } else { if (this.fOnlyScriptResources) { return; } if (!valid) { return; } } List scriptElements = new ArrayList(); List nonScriptElements = new ArrayList(); try { IFileHandle file = EnvironmentPathUtils.getFile(path); IFileHandle[] members = file.getChildren(); if (members != null) { for (int i = 0, max = members.length; i < max; i++) { IFileHandle memberFile = members[i]; IPath memberPath = memberFile.getFullPath(); if (memberFile.isDirectory()) { boolean isMemberIncluded = !Util.isExcluded(memberPath, inclusionPatterns, exclusionPatterns, true); computeFolderChildren(memberPath, isMemberIncluded, vChildren, vForeign, newElements, inclusionPatterns, exclusionPatterns, realPaths); } else { if (Util.isValidSourceModule(this, memberPath)) { scriptElements.add(memberPath); } else { if (!this.fOnlyScriptResources || valid) { nonScriptElements.add(memberPath); } } } } } ExternalScriptFolderInfo fragInfo = new ExternalScriptFolderInfo(); fldr.computeChildren(fragInfo, scriptElements); fldr.computeForeignResources(fragInfo, nonScriptElements); 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 */ } catch (CoreException e) { throw new ModelException(e); } } @Override public void getHandleMemento(StringBuffer buff) { ((ModelElement) getParent()).getHandleMemento(buff); buff.append(getHandleMementoDelimiter()); escapeMementoName(buff, getElementName()); } @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 ExternalScriptFolder(this, path); } @Override public IScriptFolder getScriptFolder(String path) { return this.getScriptFolder(new Path(path)); } @Override public boolean isReadOnly() { return this.fReadOnly; } @Override protected Object createElementInfo() { return new ExternalProjectFragmentInfo(); } @Override public boolean isArchive() { return false; } @Override public boolean isExternal() { return true; } @Override public IResource getUnderlyingResource() throws ModelException { return null; } @Override public int hashCode() { return this.fPath.hashCode(); } @Override public IPath getPath() { return this.fPath; } @Override public IResource getResource() { return null; } /** * Returns whether the corresponding resource or associated file exists */ @Override protected boolean resourceExists() { if (fPath.toString().startsWith( IBuildpathEntry.BUILTIN_EXTERNAL_ENTRY_STR)) { return true; } IFileHandle file = EnvironmentPathUtils.getFile(fPath); return file.exists() && file.isDirectory(); } @Override protected void toStringAncestors(StringBuffer buffer) { } @Override public int getKind() { return IProjectFragment.K_SOURCE; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o instanceof ExternalProjectFragment) { ExternalProjectFragment other = (ExternalProjectFragment) o; if (this.fPath.equals(other.fPath)) { IEnvironment environment = EnvironmentManager .getEnvironment(this); if (environment != null) { IEnvironment environmento = EnvironmentManager .getEnvironment(other); if (!environment.equals(environmento)) { return false; } } return true; } } return false; } @Override public String getElementName() { IEnvironment env = EnvironmentManager.getEnvironment(this); if (env == null) { env = EnvironmentPathUtils.getPathEnvironment(fPath); } String pathString = EnvironmentPathUtils.getLocalPathString(fPath); if (env != null && pathString != null) { return pathString.replace(env.getSeparatorChar(), JEM_SKIP_DELIMETER); } return fPath.lastSegment(); } @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) this.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 getBuildpathEntry() throws ModelException { IBuildpathEntry rawEntry = super.getRawBuildpathEntry(); // try to guest map from internal element. if (rawEntry != null && rawEntry.getEntryKind() == IBuildpathEntry.BPE_CONTAINER) { IBuildpathContainer container = DLTKCore.getBuildpathContainer( rawEntry.getPath(), this.getScriptProject()); IBuildpathEntry entrys[] = container.getBuildpathEntries(); for (int i = 0; i < entrys.length; ++i) { if (entrys[i].getPath().equals(this.getPath())) { return entrys[i]; } } } return rawEntry; } @Override public long getTimeStamp() { // All files inside timestamps hash. IEnvironment environment = EnvironmentManager.getEnvironment(this); try { long stamp = 0; IFileHandle file = environment.getFile(this.getPath()); if (file != null && file.exists()) { long lmodif = 0; if (file instanceof EFSFileHandle) { lmodif = ((EFSFileHandle) file).lastModified(); } else { lmodif = file.lastModified(); } stamp = lmodif; } else { return 0; } IModelElement[] children = getChildren(); for (int i = 0; i < children.length; i++) { if (children[i].getElementType() == IModelElement.SCRIPT_FOLDER) { IScriptFolder folder = (IScriptFolder) children[i]; IPath path = folder.getPath(); file = environment.getFile(path); if (file != null && file.exists()) { stamp = stamp * 13 + file.lastModified(); } } } } catch (ModelException e) { if (DLTKCore.DEBUG) { e.printStackTrace(); } } return 0; } }