com.liferay.ide.server.remote.ModuleTraverser.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.ide.server.remote.ModuleTraverser.java

Source

/**********************************************************************
 * Copyright (c) 2007, 2011 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
 *
 * Contributors:
 *    Igor Fedorenko & Fabrizio Giustina - Initial API and implementation
 **********************************************************************/
package com.liferay.ide.server.remote;

import com.liferay.ide.core.util.StringPool;
import com.liferay.ide.server.core.LiferayServerCore;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.internal.ComponentResource;
import org.eclipse.wst.common.componentcore.internal.ReferencedComponent;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.impl.PlatformURLModuleConnection;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.server.core.IModule;

/**
 * Temporary solution for https://bugs.eclipse.org/bugs/show_bug.cgi?id=103888
 */
@SuppressWarnings("restriction")
public class ModuleTraverser {

    /**
     * Facet type for EAR modules
     */
    public static final String EAR_MODULE = IModuleConstants.JST_EAR_MODULE;

    /**
     * Facet type for Web modules
     */
    public static final String WEB_MODULE = IModuleConstants.JST_WEB_MODULE;

    /**
     * Facet type for utility modules
     */
    public static final String UTILITY_MODULE = IModuleConstants.JST_UTILITY_MODULE;

    /**
     * Name of the custom Java classpath entry attribute that is used to flag entries
     * which should be exposed as module dependencies via the virtual component API.
     */
    public static final String CLASSPATH_COMPONENT_DEPENDENCY = "org.eclipse.jst.component.dependency"; //$NON-NLS-1$

    /**
     * Name of the custom Java classpath entry attribute that is used to flag
     * the resolved entries of classpath containers that should not be exposed
     * via the virtual component API.
     */
    public static final String CLASSPATH_COMPONENT_NON_DEPENDENCY = "org.eclipse.jst.component.nondependency"; //$NON-NLS-1$

    /**
     * Argument values that are used to select component dependency attribute type.
     */
    private static final int DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY = 0;
    private static final int DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY = 1;
    private static final int DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_NONDEPENDENCY = 2;

    /**
      * Scans the module using the specified visitor.
      *
      * @param module module to traverse
      * @param visitor visitor to handle resources
      * @param monitor a progress monitor
      * @throws CoreException
      */
    public static void traverse(IModule module, IModuleVisitor visitor, IProgressMonitor monitor)
            throws CoreException {
        if (module == null || module.getModuleType() == null)
            return;

        String typeId = module.getModuleType().getId();
        IVirtualComponent component = ComponentCore.createComponent(module.getProject());

        if (component == null) {
            // can happen if project has been closed
            //            Trace.trace(Trace.WARNING, "Unable to create component for module " //$NON-NLS-1$
            //                    + module.getName());
            return;
        }

        if (EAR_MODULE.equals(typeId)) {
            traverseEarComponent(component, visitor, monitor);
        } else if (WEB_MODULE.equals(typeId)) {
            traverseWebComponent(component, visitor, monitor);
        }
    }

    private static void traverseEarComponent(IVirtualComponent component, IModuleVisitor visitor,
            IProgressMonitor monitor) throws CoreException {
        // Currently the JST Server portion of WTP may not depend on the JST Enterprise portion of WTP
        /*        EARArtifactEdit earEdit = EARArtifactEdit
            .getEARArtifactEditForRead(component);
                if (earEdit != null) {
        IVirtualReference[] j2eeComponents = earEdit.getJ2EEModuleReferences();
        for (int i = 0; i < j2eeComponents.length; i++) {
            traverseWebComponent(
                    j2eeComponents[i].getReferencedComponent(), visitor,
                    monitor);
        }
        IVirtualReference[] jarComponents = earEdit.getUtilityModuleReferences();
        for (int i = 0; i < jarComponents.length; i++) {
            IVirtualReference jarReference = jarComponents[i];
            IVirtualComponent jarComponent = jarReference
                    .getReferencedComponent();
            IProject dependentProject = jarComponent.getProject();
            if (!dependentProject.hasNature(JavaCore.NATURE_ID))
                continue;
            IJavaProject project = JavaCore.create(dependentProject);
            IClasspathEntry cpe = getClasspathEntry(project, jarComponent
                    .getRootFolder().getProjectRelativePath());
            visitor.visitEarResource(null, getOSPath(dependentProject,
                    project, cpe.getOutputLocation()));
        }
                }*/
        visitor.endVisitEarComponent(component);
    }

    private static void traverseWebComponent(IVirtualComponent component, IModuleVisitor visitor,
            IProgressMonitor monitor) throws CoreException {

        visitor.visitWebComponent(component);

        IProject proj = component.getProject();
        StructureEdit warStruct = StructureEdit.getStructureEditForRead(proj);
        try {
            WorkbenchComponent comp = warStruct.getComponent();
            if (comp == null) {
                //                Trace.trace(Trace.SEVERE,
                //                        "Error getting WorkbenchComponent from war project. IProject=\"" //$NON-NLS-1$
                //                                + proj + "\" StructureEdit=\"" + warStruct //$NON-NLS-1$
                //                                + "\" WorkbenchComponent=\"" + comp + "\""); //$NON-NLS-1$ //$NON-NLS-2$
                return;
            }
            traverseWebComponentLocalEntries(comp, visitor, monitor);

            // traverse referenced components
            List children = comp.getReferencedComponents();
            for (Iterator itor = children.iterator(); itor.hasNext();) {
                ReferencedComponent childRef = (ReferencedComponent) itor.next();
                IPath rtFolder = childRef.getRuntimePath();
                URI refHandle = childRef.getHandle();

                if (PlatformURLModuleConnection.CLASSPATH
                        .equals(refHandle.segment(ModuleURIUtil.ModuleURI.SUB_PROTOCOL_INDX))) {
                    IPath refPath = getResolvedPathForArchiveComponent(refHandle);
                    // If an archive component, add to list
                    if (refPath != null) {
                        if (!refPath.isAbsolute()) {
                            IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(refPath);
                            IPath refPath2 = file.getLocation();
                            if (refPath2 != null) {
                                visitor.visitArchiveComponent(rtFolder, refPath2);
                            } else {
                                //                             Trace.trace(Trace.WARNING, NLS.bind(
                                //                                   "Could not get the location of a referenced component.  It may not exist.  Project={0}, Parent Component={1}, Referenced Component Path={2}", //$NON-NLS-1$
                                //                                   new Object[] { proj.getName(), comp.getName(), refPath}));
                            }
                        } else {
                            visitor.visitArchiveComponent(rtFolder, refPath);
                        }
                    } else {
                        // TODO Determine if any use case would arrive here.
                    }
                } else {
                    try {
                        WorkbenchComponent childCom = warStruct.findComponentByURI(refHandle);
                        if (childCom == null) {
                            continue;
                        }

                        traverseDependentEntries(visitor, rtFolder, childCom, monitor);
                    } catch (UnresolveableURIException e) {
                        LiferayServerCore.logError(e);
                    }
                }
            }
        } finally {
            warStruct.dispose();
        }

        visitor.endVisitWebComponent(component);
    }

    private static void traverseWebComponentLocalEntries(WorkbenchComponent comp, IModuleVisitor visitor,
            IProgressMonitor monitor) throws CoreException {
        IProject warProject = StructureEdit.getContainingProject(comp);
        if (warProject == null || !warProject.hasNature(JavaCore.NATURE_ID)) {
            return;
        }
        IJavaProject project = JavaCore.create(warProject);

        List res = comp.getResources();
        for (Iterator itorRes = res.iterator(); itorRes.hasNext();) {
            ComponentResource childComp = (ComponentResource) itorRes.next();
            IClasspathEntry cpe = getClasspathEntry(project, childComp.getSourcePath());
            if (cpe == null)
                continue;
            visitor.visitWebResource(childComp.getRuntimePath(),
                    getOSPath(warProject, project, cpe.getOutputLocation()));
        }

        // Include tagged classpath entries
        Map classpathDeps = getComponentClasspathDependencies(project, true);
        for (Iterator iterator = classpathDeps.keySet().iterator(); iterator.hasNext();) {
            IClasspathEntry entry = (IClasspathEntry) iterator.next();
            IClasspathAttribute attrib = (IClasspathAttribute) classpathDeps.get(entry);
            boolean isClassFolder = isClassFolderEntry(entry);
            String rtFolder = attrib.getValue();
            if (rtFolder == null) {
                if (isClassFolder) {
                    rtFolder = "/WEB-INF/classes"; //$NON-NLS-1$
                } else {
                    rtFolder = "/WEB-INF/lib"; //$NON-NLS-1$
                }
            }
            IPath entryPath = entry.getPath();
            IResource entryRes = ResourcesPlugin.getWorkspace().getRoot().findMember(entryPath);
            if (entryRes != null) {
                entryPath = entryRes.getLocation();
            }
            // TODO Determine if different handling is needed for some use cases
            if (isClassFolder) {
                visitor.visitWebResource(new Path(rtFolder), getOSPath(warProject, project, entry.getPath()));
            } else {
                visitor.visitArchiveComponent(new Path(rtFolder), entryPath);
            }
        }
    }

    private static void traverseDependentEntries(IModuleVisitor visitor, IPath runtimeFolder,
            WorkbenchComponent component, IProgressMonitor monitor) throws CoreException {
        IProject dependentProject = StructureEdit.getContainingProject(component);
        if (!dependentProject.hasNature(JavaCore.NATURE_ID))
            return;
        IJavaProject project = JavaCore.create(dependentProject);
        visitor.visitDependentJavaProject(project);

        String name = component.getName(); // assume it is the same as URI

        // go thru all entries
        List res = component.getResources();
        for (Iterator itorRes = res.iterator(); itorRes.hasNext();) {
            ComponentResource childComp = (ComponentResource) itorRes.next();
            IPath rtPath = childComp.getRuntimePath();
            IPath srcPath = childComp.getSourcePath();
            IClasspathEntry cpe = getClasspathEntry(project, srcPath);
            if (cpe != null) {
                visitor.visitDependentComponent(runtimeFolder.append(rtPath).append(name + ".jar"), //$NON-NLS-1$
                        getOSPath(dependentProject, project, cpe.getOutputLocation()));
            }
            // Handle META-INF/resources
            String path = rtPath.toString();
            IFolder resFolder = null;
            String targetPath = StringPool.EMPTY;
            if ("/".equals(path)) { //$NON-NLS-1$
                resFolder = dependentProject.getFolder(srcPath.append("META-INF/resources")); //$NON-NLS-1$
            } else if ("/META-INF".equals(path)) { //$NON-NLS-1$
                resFolder = dependentProject.getFolder(srcPath.append("resources")); //$NON-NLS-1$
            } else if ("/META-INF/resources".equals(path)) { //$NON-NLS-1$
                resFolder = dependentProject.getFolder(srcPath);
            } else if (path.startsWith("/META-INF/resources/")) { //$NON-NLS-1$
                resFolder = dependentProject.getFolder(srcPath);
                targetPath = path.substring("/META-INF/resources".length()); //$NON-NLS-1$
            }
            if (resFolder != null && resFolder.exists()) {
                visitor.visitDependentContentResource(new Path(targetPath), resFolder.getLocation());
            }
        }

        // Include tagged classpath entries
        Map classpathDeps = getComponentClasspathDependencies(project, false);
        for (Iterator iterator = classpathDeps.keySet().iterator(); iterator.hasNext();) {
            IClasspathEntry entry = (IClasspathEntry) iterator.next();
            boolean isClassFolder = isClassFolderEntry(entry);
            String rtFolder = null;
            if (isClassFolder) {
                rtFolder = "/"; //$NON-NLS-1$
            } else {
                rtFolder = "/WEB-INF/lib"; //$NON-NLS-1$
            }
            IPath entryPath = entry.getPath();
            IResource entryRes = ResourcesPlugin.getWorkspace().getRoot().findMember(entryPath);
            if (entryRes != null) {
                entryPath = entryRes.getLocation();
            }
            // TODO Determine if different handling is needed for some use cases
            if (isClassFolder) {
                visitor.visitDependentComponent(runtimeFolder.append(rtFolder).append(name + ".jar"), //$NON-NLS-1$
                        getOSPath(dependentProject, project, entry.getPath()));
            } else {
                visitor.visitArchiveComponent(new Path(rtFolder), entryPath);
            }
        }
    }

    private static IClasspathEntry getClasspathEntry(IJavaProject project, IPath sourcePath)
            throws JavaModelException {
        sourcePath = project.getPath().append(sourcePath);
        IClasspathEntry[] cp = project.getRawClasspath();
        for (int i = 0; i < cp.length; i++) {
            if (sourcePath.equals(cp[i].getPath()))
                return JavaCore.getResolvedClasspathEntry(cp[i]);
        }
        return null;
    }

    private static IPath getOSPath(IProject project, IJavaProject javaProject, IPath outputPath)
            throws JavaModelException {
        if (outputPath == null)
            outputPath = javaProject.getOutputLocation();
        // If we have the root of a project, return project location
        if (outputPath.segmentCount() == 1) {
            return ResourcesPlugin.getWorkspace().getRoot().getProject(outputPath.lastSegment()).getLocation();
        }
        // Otherwise return project folder location
        return ResourcesPlugin.getWorkspace().getRoot().getFolder(outputPath).getLocation();
    }

    /*
     * Derived from J2EEProjectUtilities.getResolvedPathForArchiveComponent()
     */
    private static IPath getResolvedPathForArchiveComponent(URI uri) {

        String resourceType = uri.segment(1);
        URI contenturi = ModuleURIUtil.trimToRelativePath(uri, 2);
        String contentName = contenturi.toString();

        if (resourceType.equals("lib")) { //$NON-NLS-1$
            // module:/classpath/lib/D:/foo/foo.jar
            return Path.fromOSString(contentName);

        } else if (resourceType.equals("var")) { //$NON-NLS-1$

            // module:/classpath/var/<CLASSPATHVAR>/foo.jar
            String classpathVar = contenturi.segment(0);
            URI remainingPathuri = ModuleURIUtil.trimToRelativePath(contenturi, 1);
            String remainingPath = remainingPathuri.toString();

            String[] classpathvars = JavaCore.getClasspathVariableNames();
            boolean found = false;
            for (int i = 0; i < classpathvars.length; i++) {
                if (classpathVar.equals(classpathvars[i])) {
                    found = true;
                    break;
                }
            }
            if (found) {
                IPath path = JavaCore.getClasspathVariable(classpathVar);
                if (path != null) {
                    URI finaluri = URI.createURI(path.toOSString() + IPath.SEPARATOR + remainingPath);
                    return Path.fromOSString(finaluri.toString());
                }
            }
            //         Trace.trace(Trace.WARNING,
            //               NLS.bind("Tomcat publishing could not resolve dependency URI \"{0}\".  A value for classpath variable {1} was not found.", uri, classpathVar)); //$NON-NLS-1$
        }
        return null;
    }

    /*
     * Derived from ClasspathDependencyUtil.getComponentClasspathDependencies()
     */
    private static Map getComponentClasspathDependencies(final IJavaProject javaProject, final boolean isWebApp)
            throws CoreException {

        // get the raw entries
        final Map referencedRawEntries = getRawComponentClasspathDependencies(javaProject);
        final Map<IClasspathEntry, IClasspathAttribute> validRawEntries = new HashMap<IClasspathEntry, IClasspathAttribute>();

        // filter out non-valid referenced raw entries
        final Iterator i = referencedRawEntries.keySet().iterator();
        while (i.hasNext()) {
            final IClasspathEntry entry = (IClasspathEntry) i.next();
            final IClasspathAttribute attrib = (IClasspathAttribute) referencedRawEntries.get(entry);
            if (isValid(entry, attrib, isWebApp, javaProject.getProject())) {
                validRawEntries.put(entry, attrib);
            }
        }

        // if we have no valid raw entries, return empty map
        if (validRawEntries.isEmpty()) {
            return Collections.EMPTY_MAP;
        }

        // XXX Would like to replace the code below with use of a public JDT API that returns
        // the raw IClasspathEntry for a given resolved IClasspathEntry (see see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183995)
        // The code must currently leverage IPackageFragmentRoot to determine this
        // mapping and, because IPackageFragmentRoots do not maintain IClasspathEntry data, a prior
        // call is needed to getResolvedClasspath() and the resolved IClasspathEntries have to be stored in a Map from IPath-to-IClasspathEntry to
        // support retrieval using the resolved IPackageFragmentRoot

        // retrieve the resolved classpath
        final IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
        final Map<IPath, IClasspathEntry> pathToResolvedEntry = new HashMap<IPath, IClasspathEntry>();

        // store in a map from path to entry
        for (int j = 0; j < entries.length; j++) {
            pathToResolvedEntry.put(entries[j].getPath(), entries[j]);
        }

        final Map<IClasspathEntry, IClasspathAttribute> referencedEntries = new LinkedHashMap<IClasspathEntry, IClasspathAttribute>();

        // grab all IPackageFragmentRoots
        final IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
        for (int j = 0; j < roots.length; j++) {
            final IPackageFragmentRoot root = roots[j];
            final IClasspathEntry rawEntry = root.getRawClasspathEntry();

            // is the raw entry valid?
            IClasspathAttribute attrib = validRawEntries.get(rawEntry);
            if (attrib == null) {
                continue;
            }

            final IPath pkgFragPath = root.getPath();
            final IClasspathEntry resolvedEntry = pathToResolvedEntry.get(pkgFragPath);
            final IClasspathAttribute resolvedAttrib = checkForComponentDependencyAttribute(resolvedEntry,
                    DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY);
            // attribute for the resolved entry must either be unspecified or it must be the
            // dependency attribute for it to be included
            if (resolvedAttrib == null || resolvedAttrib.getName().equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
                // filter out resolved entry if it doesn't pass the validation rules
                if (isValid(resolvedEntry, resolvedAttrib != null ? resolvedAttrib : attrib, isWebApp,
                        javaProject.getProject())) {
                    if (resolvedAttrib != null) {
                        // if there is an attribute on the sub-entry, use that
                        attrib = resolvedAttrib;
                    }
                    referencedEntries.put(resolvedEntry, attrib);
                }
            }
        }

        return referencedEntries;
    }

    /*
     * Derived from ClasspathDependencyUtil.getRawComponentClasspathDependencies()
     */
    private static Map getRawComponentClasspathDependencies(final IJavaProject javaProject) throws CoreException {
        if (javaProject == null) {
            return Collections.EMPTY_MAP;
        }
        final Map<IClasspathEntry, IClasspathAttribute> referencedRawEntries = new HashMap<IClasspathEntry, IClasspathAttribute>();
        final IClasspathEntry[] entries = javaProject.getRawClasspath();
        for (int i = 0; i < entries.length; i++) {
            final IClasspathEntry entry = entries[i];
            final IClasspathAttribute attrib = checkForComponentDependencyAttribute(entry,
                    DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY);
            if (attrib != null) {
                referencedRawEntries.put(entry, attrib);
            }
        }
        return referencedRawEntries;
    }

    /*
     * Derived from ClasspathDependencyUtil.checkForComponentDependencyAttribute()
     */
    private static IClasspathAttribute checkForComponentDependencyAttribute(final IClasspathEntry entry,
            final int attributeType) {
        if (entry == null) {
            return null;
        }
        final IClasspathAttribute[] attributes = entry.getExtraAttributes();
        for (int i = 0; i < attributes.length; i++) {
            final IClasspathAttribute attribute = attributes[i];
            final String name = attribute.getName();
            if (name.equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
                if (attributeType == DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY
                        || attributeType == DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY) {
                    return attribute;
                }
            } else if (name.equals(CLASSPATH_COMPONENT_NON_DEPENDENCY)) {
                if (attributeType == DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY
                        || attributeType == DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_NONDEPENDENCY) {
                    return attribute;
                }
            }
        }
        return null;
    }

    /*
     * Derived from ClasspathDependencyValidator.validateVirtualComponentEntry()
     */
    private static boolean isValid(final IClasspathEntry entry, final IClasspathAttribute attrib, boolean isWebApp,
            final IProject project) {
        int kind = entry.getEntryKind();
        boolean isClassFolder = isClassFolderEntry(entry);

        if (kind == IClasspathEntry.CPE_PROJECT || kind == IClasspathEntry.CPE_SOURCE) {
            return false;
        }

        String runtimePath = getRuntimePath(attrib, isWebApp, isClassFolder);
        if (!isWebApp) {
            if (!runtimePath.equals("../") && !runtimePath.equals("/")) { //$NON-NLS-1$//$NON-NLS-2$
                return false;
            }
            if (isClassFolder && !runtimePath.equals("/")) { //$NON-NLS-1$
                return false;
            }
        } else {
            if (runtimePath != null && !runtimePath.equals("/WEB-INF/lib") //$NON-NLS-1$
                    && !runtimePath.equals("/WEB-INF/classes") //$NON-NLS-1$
                    && !runtimePath.equals("../")) { //$NON-NLS-1$
                return false;
            }
            if (isClassFolder && !runtimePath.equals("/WEB-INF/classes")) { //$NON-NLS-1$
                return false;
            }
        }
        return true;
    }

    /*
     * Derived from ClasspathDependencyUtil.isClassFolderEntry()
     */
    private static boolean isClassFolderEntry(final IClasspathEntry entry) {
        if (entry == null || entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) {
            return false;
        }
        // does the path refer to a file or a folder?
        final IPath entryPath = entry.getPath();
        IPath entryLocation = entryPath;
        final IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entryPath);
        if (resource != null) {
            entryLocation = resource.getLocation();
        }
        boolean isFile = true; // by default, assume a jar file
        if (entryLocation.toFile().isDirectory()) {
            isFile = false;
        }
        return !isFile;
    }

    /*
     * Derived from ClasspathDependencyUtil.getRuntimePath()
     */
    private static String getRuntimePath(final IClasspathAttribute attrib, final boolean isWebApp,
            final boolean isClassFolder) {
        if (attrib != null && !attrib.getName().equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
            return null;
        }
        if (attrib == null || attrib.getValue() == null || attrib.getValue().length() == 0) {
            if (isWebApp) {
                return isClassFolder ? "/WEB_INF/classes" : "WEB-INF/lib"; //$NON-NLS-1$ //$NON-NLS-2$
            }
            return isClassFolder ? "/" : "../"; //$NON-NLS-1$ //$NON-NLS-2$
        }
        return attrib.getValue();
    }
}