blob: 268565a47458b20b9ee1ae9c198d99166b478caf [file] [log] [blame]
/*******************************************************************************
* 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;
}
}