blob: eaae3bf609bcc290ba5e3c057ad79c4dcf113d20 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 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.launching;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathContainer;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IBuiltinModuleProvider;
import org.eclipse.dltk.core.IInterpreterContainerExtension;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.internal.core.BuildpathEntry;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.IInterpreterInstallChangedListener;
import org.eclipse.dltk.launching.LaunchingMessages;
import org.eclipse.dltk.launching.LibraryLocation;
import org.eclipse.dltk.launching.PropertyChangeEvent;
import org.eclipse.dltk.launching.ScriptRuntime;
import com.ibm.icu.text.MessageFormat;
/**
* Interpreter Container - resolves a buildpath container tp interpreter
*/
public class InterpreterContainer implements IBuildpathContainer {
/**
* Corresponding interpreter
*/
private IInterpreterInstall fInterpreterInstall = null;
/**
* Container path used to resolve to this interpreter
*/
private IPath fPath = null;
/**
* Cache of buildpath entries per Interpreter install. Cleared when a
* Interpreter changes.
*/
private static Map<IInterpreterInstall, IBuildpathEntry[]> fgBuildpathEntries = null;
private static IAccessRule[] EMPTY_RULES = new IAccessRule[0];
/**
* Returns the buildpath entries associated with the given interpreter.
*
* @param interpreter
* @return buildpath entries
*/
private static IBuildpathEntry[] getBuildpathEntries(
IInterpreterInstall interpreter, IScriptProject project) {
if (fgBuildpathEntries == null) {
fgBuildpathEntries = new HashMap<IInterpreterInstall, IBuildpathEntry[]>(
10);
// add a listener to clear cached value when a Interpreter changes
// or is
// removed
IInterpreterInstallChangedListener listener = new IInterpreterInstallChangedListener() {
public void defaultInterpreterInstallChanged(
IInterpreterInstall previous,
IInterpreterInstall current) {
}
public void interpreterChanged(PropertyChangeEvent event) {
if (event.getSource() != null) {
fgBuildpathEntries.remove(event.getSource());
}
}
public void interpreterAdded(IInterpreterInstall newInterpreter) {
}
public void interpreterRemoved(
IInterpreterInstall removedInterpreter) {
fgBuildpathEntries.remove(removedInterpreter);
}
};
ScriptRuntime.addInterpreterInstallChangedListener(listener);
}
IBuildpathEntry[] entries = fgBuildpathEntries.get(interpreter);
if (entries == null) {
entries = computeBuildpathEntries(interpreter, project);
fgBuildpathEntries.put(interpreter, entries);
}
return entries;
}
/**
* Computes the buildpath entries associated with a interpreter - one entry
* per library.
*
* @param interpreter
* @return buildpath entries
* @since 2.0
*/
public static IBuildpathEntry[] computeBuildpathEntries(
IInterpreterInstall interpreter, IScriptProject project) {
LibraryLocation[] libs = interpreter.getLibraryLocations();
if (libs == null) {
libs = ScriptRuntime.getLibraryLocations(interpreter);
}
List<IBuildpathEntry> entries = new ArrayList<IBuildpathEntry>(
libs.length);
Set<IPath> rawEntries = new HashSet<IPath>(libs.length);
for (int i = 0; i < libs.length; i++) {
IPath entryPath = libs[i].getLibraryPath();
if (!entryPath.isEmpty()) {
if (rawEntries.contains(entryPath))
continue;
IBuildpathAttribute[] attributes = new IBuildpathAttribute[0];
ArrayList<IPath> excluded = new ArrayList<IPath>(); // paths to
// exclude
for (int j = 0; j < libs.length; j++) {
IPath otherPath = libs[j].getLibraryPath();
if (otherPath.isEmpty())
continue;
// compare, if it contains some another
if (entryPath.isPrefixOf(otherPath)
&& !otherPath.equals(entryPath)) {
IPath pattern = otherPath.setDevice(null)
.removeFirstSegments(entryPath.segmentCount())
.append("*"); //$NON-NLS-1$
if (!excluded.contains(pattern)) {
excluded.add(pattern);
}
}
}
entries.add(DLTKCore.newLibraryEntry(entryPath, EMPTY_RULES,
attributes, BuildpathEntry.INCLUDE_ALL, excluded
.toArray(new IPath[excluded.size()]), false,
true));
rawEntries.add(entryPath);
}
}
// Add builtin entry.
{
IBuildpathAttribute[] attributes = new IBuildpathAttribute[0];
entries.add(DLTKCore.newBuiltinEntry(
IBuildpathEntry.BUILTIN_EXTERNAL_ENTRY.append(interpreter
.getInstallLocation().toOSString()), EMPTY_RULES,
attributes, BuildpathEntry.INCLUDE_ALL, new IPath[0],
false, true));
}
// Preprocess entries using extension
IInterpreterContainerExtension extension = DLTKLanguageManager
.getInterpreterContainerExtensions(project);
if (extension != null) {
extension.preProcessEntries(project, entries);
}
return entries.toArray(new IBuildpathEntry[entries.size()]);
}
/**
* Constructs a interpreter buildpath container on the given interpreter
* install
*
* @param interpreter
* Interpreter install - cannot be <code>null</code>
* @param path
* container path used to resolve this interpreter
*/
public InterpreterContainer(IInterpreterInstall interpreter, IPath path) {
fInterpreterInstall = interpreter;
fPath = path;
}
/**
* @see IBuildpathContainer#getBuildpathEntries(IScriptProject)
*/
public IBuildpathEntry[] getBuildpathEntries(IScriptProject project) {
IBuildpathEntry[] buildpathEntries = getBuildpathEntries(
fInterpreterInstall, project);
List<IBuildpathEntry> entries = new ArrayList<IBuildpathEntry>();
entries.addAll(Arrays.asList(buildpathEntries));
// Use custom per project interpreter entries.
IInterpreterContainerExtension extension = DLTKLanguageManager
.getInterpreterContainerExtensions(project);
if (extension != null) {
extension.processEntres(project, entries);
}
return entries.toArray(new IBuildpathEntry[entries.size()]);
}
/**
* @since 2.0
*/
public IBuildpathEntry[] getRawBuildpathEntries(IScriptProject project) {
IBuildpathEntry[] buildpathEntries = getBuildpathEntries(
fInterpreterInstall, project);
List<IBuildpathEntry> entries = new ArrayList<IBuildpathEntry>();
entries.addAll(Arrays.asList(buildpathEntries));
return entries.toArray(new IBuildpathEntry[entries.size()]);
}
/**
* @see IBuildpathContainer#getDescription()
*/
public String getDescription(IScriptProject project) {
String tag = fInterpreterInstall.getName();
return MessageFormat
.format(
LaunchingMessages.InterpreterEnvironmentContainer_InterpreterEnvironment_System_Library_1,
new String[] { tag });
}
/**
* @see IBuildpathContainer#getKind()
*/
public int getKind() {
return IBuildpathContainer.K_DEFAULT_SYSTEM;
}
/**
* @see IBuildpathContainer#getPath()
*/
public IPath getPath() {
return fPath;
}
public IBuiltinModuleProvider getBuiltinProvider(IScriptProject project) {
return fInterpreterInstall;
}
}