Copyright (c) 2000, 2015 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.launching; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jdt.internal.launching.DefaultProjectClasspathEntry; import org.eclipse.jdt.internal.launching.VariableClasspathEntry;
Default implementation of source lookup path computation and resolution.

This class may be sub-classed.

Since:2.0
/** * Default implementation of source lookup path computation and resolution. * <p> * This class may be sub-classed. * </p> * @since 2.0 */
public class StandardSourcePathProvider extends StandardClasspathProvider { /* (non-Javadoc) * @see org.eclipse.jdt.launching.IRuntimeClasspathProvider#computeUnresolvedClasspath(org.eclipse.debug.core.ILaunchConfiguration) */ @Override public IRuntimeClasspathEntry[] computeUnresolvedClasspath(ILaunchConfiguration configuration) throws CoreException { boolean useDefault = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_SOURCE_PATH, true); IRuntimeClasspathEntry[] entries = null; if (useDefault) { // the default source lookup path is the same as the classpath entries = super.computeUnresolvedClasspath(configuration); } else { // recover persisted source path entries = recoverRuntimePath(configuration, IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH); } return entries; } /* (non-Javadoc) * @see org.eclipse.jdt.launching.IRuntimeClasspathProvider#resolveClasspath(org.eclipse.jdt.launching.IRuntimeClasspathEntry[], org.eclipse.debug.core.ILaunchConfiguration) */ @Override public IRuntimeClasspathEntry[] resolveClasspath(IRuntimeClasspathEntry[] entries, ILaunchConfiguration configuration) throws CoreException { List<IRuntimeClasspathEntry> all = new UniqueList(entries.length); for (int i = 0; i < entries.length; i++) { switch (entries[i].getType()) { case IRuntimeClasspathEntry.PROJECT: // a project resolves to itself for source lookup (rather than the class file output locations) all.add(entries[i]); break; case IRuntimeClasspathEntry.OTHER: IRuntimeClasspathEntry2 entry = (IRuntimeClasspathEntry2)entries[i]; String typeId = entry.getTypeId(); IRuntimeClasspathEntry[] res = null; if (typeId.equals(DefaultProjectClasspathEntry.TYPE_ID)) { // add the resolved children of the project IRuntimeClasspathEntry[] children = entry.getRuntimeClasspathEntries(configuration); res = JavaRuntime.resolveSourceLookupPath(children, configuration); } else if (typeId.equals(VariableClasspathEntry.TYPE_ID)) { // add the archive itself - we currently do not allow a source attachment res = JavaRuntime.resolveRuntimeClasspathEntry(entry, configuration); } else { res = JavaRuntime.resolveRuntimeClasspathEntry(entry, configuration); } if (res != null) { for (int j = 0; j < res.length; j++) { all.add(res[j]); addManifestReferences(res[j], all); } } break; default: IRuntimeClasspathEntry[] resolved =JavaRuntime.resolveRuntimeClasspathEntry(entries[i], configuration); for (int j = 0; j < resolved.length; j++) { all.add(resolved[j]); addManifestReferences(resolved[j], all); } break; } } return all.toArray(new IRuntimeClasspathEntry[all.size()]); }
If the given entry is an archive, adds any archives referenced by the associated manifest.
Params:
  • entry – runtime classpath entry
  • all – list to add references to
/** * If the given entry is an archive, adds any archives referenced by the associated manifest. * * @param entry runtime classpath entry * @param all list to add references to */
protected void addManifestReferences(IRuntimeClasspathEntry entry, List<IRuntimeClasspathEntry> all) { if (entry.getType() == IRuntimeClasspathEntry.ARCHIVE) { String location = entry.getLocation(); if (location != null) { try (JarFile jar = new JarFile(location, false);) { Manifest manifest = jar.getManifest(); if (manifest != null) { Attributes mainAttributes = manifest.getMainAttributes(); if (mainAttributes != null) { String value = mainAttributes.getValue(Attributes.Name.CLASS_PATH); if (value != null) { String[] entries = value.split("\\s+"); //$NON-NLS-1$ IPath base = new Path(location); base = base.removeLastSegments(1); for (int i = 0; i < entries.length; i++) { IPath path = base.append(entries[i]); if (path.toFile().exists()) { IRuntimeClasspathEntry ref = JavaRuntime.newArchiveRuntimeClasspathEntry(path); if (!all.contains(ref)) { all.add(ref); } } } } } } } catch (IOException e) { } } } } /* * An ArrayList that acts like a set -i.e. does not allow duplicate items. * hack for bug 112774 */ class UniqueList extends ArrayList<IRuntimeClasspathEntry> { private static final long serialVersionUID = -7402160651027036270L; HashSet<IRuntimeClasspathEntry> set; public UniqueList(int length) { super(length); set = new HashSet<>(length); } @Override public void add(int index, IRuntimeClasspathEntry element) { if (set.add(element)) { super.add(index, element); } } @Override public boolean add(IRuntimeClasspathEntry o) { if (set.add(o)) { return super.add(o); } return false; } @Override public boolean addAll(Collection<? extends IRuntimeClasspathEntry> c) { if (set.addAll(c)) { return super.addAll(c); } return false; } @Override public boolean addAll(int index, Collection<? extends IRuntimeClasspathEntry> c) { if (set.addAll(c)) { return super.addAll(index, c); } return false; } @Override public void clear() { set.clear(); super.clear(); } @Override public boolean contains(Object elem) { return set.contains(elem); } @Override public void ensureCapacity(int minCapacity) { super.ensureCapacity(minCapacity); } @Override public IRuntimeClasspathEntry remove(int index) { IRuntimeClasspathEntry object = super.remove(index); set.remove(object); return object; } @Override protected void removeRange(int fromIndex, int toIndex) { for (int index = fromIndex; index<=toIndex; index++) { remove(index); } } @Override public IRuntimeClasspathEntry set(int index, IRuntimeClasspathEntry element) { set.remove(element); if (set.add(element)) { return super.set(index, element); } return null; //should not happen. } } }