com.siteview.mde.internal.core.ClasspathHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.siteview.mde.internal.core.ClasspathHelper.java

Source

/*******************************************************************************
 * Copyright (c) 2003, 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.siteview.mde.internal.core;

import java.io.*;
import java.net.URL;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.*;
import com.siteview.mde.core.build.IBuild;
import com.siteview.mde.core.build.IBuildEntry;
import com.siteview.mde.core.monitor.*;
import com.siteview.mde.internal.core.build.WorkspaceBuildModel;
import com.siteview.mde.internal.core.project.PDEProject;

public class ClasspathHelper {

    private static final String DOT = "."; //$NON-NLS-1$
    private static final String FRAGMENT_ANNOTATION = "@fragment@"; //$NON-NLS-1$

    public static String getDevEntriesProperties(String fileName, boolean checkExcluded) {
        File file = new File(fileName);
        if (!file.exists()) {
            File directory = file.getParentFile();
            if (directory != null && (!directory.exists() || directory.isFile())) {
                directory.mkdirs();
            }
        }
        Properties properties = new Properties();
        // account for cascading workspaces
        TargetWeaver.weaveDevProperties(properties);
        IMonitorModelBase[] models = MonitorRegistry.getWorkspaceModels();
        for (int i = 0; i < models.length; i++) {
            String id = models[i].getMonitorBase().getId();
            if (id == null)
                continue;
            String entry = writeEntry(getDevPaths(models[i], checkExcluded, null));
            if (entry.length() > 0) {
                String currentValue = (String) properties.get(id);
                if (!entry.equals(currentValue)) {
                    if (currentValue != null)
                        entry = currentValue.concat(",").concat(entry); //$NON-NLS-1$
                    properties.put(id, entry);
                }
            }
        }
        properties.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$

        FileOutputStream stream = null;
        try {
            stream = new FileOutputStream(fileName);
            properties.store(stream, ""); //$NON-NLS-1$
            stream.flush();
            return new URL("file:" + fileName).toString(); //$NON-NLS-1$
        } catch (IOException e) {
            MDECore.logException(e);
        } finally {
            try {
                if (stream != null)
                    stream.close();
            } catch (IOException e) {
            }
        }
        return getDevEntries(checkExcluded);
    }

    public static String getDevEntriesProperties(String fileName, Map map) {
        File file = new File(fileName);
        if (!file.exists()) {
            File directory = file.getParentFile();
            if (directory != null && (!directory.exists() || directory.isFile())) {
                directory.mkdirs();
            }
        }
        Properties properties = new Properties();
        // account for cascading workspaces
        TargetWeaver.weaveDevProperties(properties);
        Iterator iter = map.values().iterator();
        while (iter.hasNext()) {
            IMonitorModelBase model = (IMonitorModelBase) iter.next();
            if (model.getUnderlyingResource() != null) {
                String entry = writeEntry(getDevPaths(model, true, map));
                if (entry.length() > 0) {
                    String id = model.getMonitorBase().getId();
                    String currentValue = (String) properties.get(id);
                    if (!entry.equals(currentValue)) {
                        if (currentValue != null)
                            entry = currentValue.concat(",").concat(entry); //$NON-NLS-1$
                        properties.put(id, entry);
                    }
                }
            }
        }
        properties.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$

        FileOutputStream stream = null;
        try {
            stream = new FileOutputStream(fileName);
            properties.store(stream, ""); //$NON-NLS-1$
            stream.flush();
            return new URL("file:" + fileName).toString(); //$NON-NLS-1$
        } catch (IOException e) {
            MDECore.logException(e);
        } finally {
            try {
                if (stream != null)
                    stream.close();
            } catch (IOException e) {
            }
        }
        return getDevEntries(true);
    }

    private static String getDevEntries(boolean checkExcluded) {
        IMonitorModelBase[] models = MonitorRegistry.getWorkspaceModels();
        ArrayList list = new ArrayList();
        for (int i = 0; i < models.length; i++) {
            String id = models[i].getMonitorBase().getId();
            if (id == null || id.trim().length() == 0)
                continue;
            IPath[] paths = getDevPaths(models[i], checkExcluded, null);
            for (int j = 0; j < paths.length; j++) {
                list.add(paths[j]);
            }
        }
        String entry = writeEntry((IPath[]) list.toArray(new IPath[list.size()]));
        return entry.length() > 0 ? entry : "bin"; //$NON-NLS-1$
    }

    private static String writeEntry(IPath[] paths) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < paths.length; i++) {
            buffer.append(paths[i].toString());
            if (i < paths.length - 1)
                buffer.append(","); //$NON-NLS-1$
        }
        return buffer.toString();
    }

    // TODO remove - no longer used after bug 217870
    public static Dictionary getDevDictionary(IMonitorModelBase model) {
        if (model.getUnderlyingResource() == null)
            return null;

        String id = model.getMonitorBase().getId();
        if (id == null || id.trim().length() == 0)
            return null;
        IPath[] paths = getDevPaths(model, false, null);
        String entry = writeEntry(paths);
        Hashtable map = new Hashtable(2);
        map.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        map.put(id, entry.length() > 0 ? entry : "bin"); //$NON-NLS-1$
        return map;
    }

    // creates a map whose key is a Path to the source directory/jar and the value is a Path output directory or jar.
    private static Map getClasspathMap(IProject project, boolean checkExcluded, boolean onlyJarsIfLinked,
            boolean absolutePaths) throws JavaModelException {
        List excluded = getFoldersToExclude(project, checkExcluded);
        IJavaProject jProject = JavaCore.create(project);
        HashMap map = new HashMap();
        IClasspathEntry[] entries = jProject.getRawClasspath();
        for (int i = 0; i < entries.length; i++) {
            // most of the paths we get will be project relative, so we need to make the paths relative
            // we will have problems adding an "absolute" path that is workspace relative
            IPath output = null, source = null;
            if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                source = entries[i].getPath();
                output = entries[i].getOutputLocation();
                if (output == null)
                    output = jProject.getOutputLocation();
            } else if (entries[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
                source = entries[i].getPath();
                output = entries[i].getPath();
                if (source.segmentCount() == 1)
                    source = new Path(DOT);
            }
            if (output != null && !excluded.contains(output)) {
                IResource file = project.findMember(output.removeFirstSegments(1));
                // make the path either relative or absolute
                if (file != null) {
                    boolean isLinked = file.isLinked(IResource.CHECK_ANCESTORS);
                    if (entries[i].getEntryKind() != IClasspathEntry.CPE_SOURCE && !isLinked && onlyJarsIfLinked)
                        continue;
                    output = (isLinked || absolutePaths) ? file.getLocation().makeAbsolute()
                            : output.makeRelative();
                } else
                    continue;
                ArrayList list = (ArrayList) map.get(source);
                if (list == null)
                    list = new ArrayList();
                list.add(output);
                map.put(source, list);
            }
        }
        return map;
    }

    // find the corresponding paths for a library name.  Searches for source folders first, but includes any libraries on the buildpath with the same name
    private static IPath[] findLibrary(String libName, IProject project, Map classpathMap, IBuild build) {
        ArrayList paths = new ArrayList();
        IBuildEntry entry = (build != null) ? build.getEntry(IBuildEntry.JAR_PREFIX + libName) : null;
        if (entry != null) {
            String[] resources = entry.getTokens();
            for (int j = 0; j < resources.length; j++) {
                IResource res = project.findMember(resources[j]);
                if (res != null) {
                    ArrayList list = (ArrayList) classpathMap.get(res.getFullPath());
                    if (list != null) {
                        ListIterator li = list.listIterator();
                        while (li.hasNext())
                            paths.add(li.next());
                    }
                }
            }
        }

        // search for a library that exists in jar form on the buildpath
        IPath path = null;
        if (libName.equals(DOT))
            path = new Path(DOT);
        else {
            IResource res = project.findMember(libName);
            if (res != null)
                path = res.getFullPath();
        }

        ArrayList list = (ArrayList) classpathMap.get(path);
        if (list != null) {
            ListIterator li = list.listIterator();
            while (li.hasNext())
                paths.add(li.next());
        }
        return (IPath[]) paths.toArray(new IPath[paths.size()]);
    }

    private static IPath[] getDevPaths(IMonitorModelBase model, boolean checkExcluded, Map pluginsMap) {
        ArrayList result = new ArrayList();
        IProject project = model.getUnderlyingResource().getProject();
        IMonitorBase base = model.getMonitorBase();
        IMonitorLibrary[] libraries = base.getLibraries();
        try {
            if (project.hasNature(JavaCore.NATURE_ID)) {
                Map classpathMap = getClasspathMap(project, checkExcluded,
                        !base.getId().equals(MDECore.getDefault().getModelManager().getSystemBundleId()), false);
                IFile file = PDEProject.getBuildProperties(project);
                IPath filePath = file.getLocation();
                boolean searchBuild = filePath != null && filePath.toFile().exists();
                if (searchBuild) {
                    WorkspaceBuildModel bModel = new WorkspaceBuildModel(file);
                    IBuild build = bModel.getBuild();
                    // if it is a custom build, act like there is no build.properties (add everything)
                    IBuildEntry entry = build.getEntry("custom"); //$NON-NLS-1$
                    if (entry != null)
                        searchBuild = false;
                    else {
                        if (libraries.length == 0) {
                            IPath[] paths = findLibrary(DOT, project, classpathMap, build);
                            if (paths.length == 0) {
                                // No mapping for default library, if there are source folders just add their corresponding output folders to the build path.
                                // This likely indicates an error in the build.properties, but to be friendly we should add the output folders so running/debugging
                                // works (see bug 237025)
                                if (!classpathMap.isEmpty()) {
                                    Iterator iterator = classpathMap.values().iterator();
                                    List collect = new ArrayList();
                                    while (iterator.hasNext()) {
                                        ArrayList list = (ArrayList) iterator.next();
                                        collect.addAll(list);
                                    }
                                    paths = (IPath[]) collect.toArray(new IPath[collect.size()]);
                                }
                            }
                            for (int j = 0; j < paths.length; j++)
                                addPath(result, project, paths[j]);
                        } else {
                            for (int i = 0; i < libraries.length; i++) {
                                IPath[] paths = findLibrary(libraries[i].getName(), project, classpathMap, build);
                                if (paths.length == 0 && !libraries[i].getName().equals(DOT)) {
                                    paths = findLibraryFromFragments(libraries[i].getName(), model, checkExcluded,
                                            pluginsMap);
                                }
                                for (int j = 0; j < paths.length; j++)
                                    addPath(result, project, paths[j]);
                            }
                        }
                    }
                }
                if (!searchBuild) {
                    // if no build.properties, add all output folders
                    Iterator it = classpathMap.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry entry = (Map.Entry) it.next();
                        ArrayList list = (ArrayList) entry.getValue();
                        ListIterator li = list.listIterator();
                        while (li.hasNext())
                            addPath(result, project, (IPath) li.next());
                    }
                }
            }
        } catch (JavaModelException e) {
        } catch (CoreException e) {
        }
        return (IPath[]) result.toArray(new IPath[result.size()]);
    }

    // looks for fragments for a plug-in.  Then searches the fragments for a specific library.  Will return paths which are absolute (required by runtime)
    private static IPath[] findLibraryFromFragments(String libName, IMonitorModelBase model, boolean checkExcluded,
            Map plugins) {
        IFragmentModel[] frags = MDEManager.findFragmentsFor(model);
        for (int i = 0; i < frags.length; i++) {
            if (plugins != null && !plugins.containsKey(frags[i].getBundleDescription().getSymbolicName()))
                continue;
            // look in project first
            if (frags[i].getUnderlyingResource() != null) {
                try {
                    IProject project = frags[i].getUnderlyingResource().getProject();
                    Map classpathMap = getClasspathMap(project, checkExcluded, false, true);
                    IFile file = PDEProject.getBuildProperties(project);
                    IBuild build = null;
                    if (file.exists()) {
                        WorkspaceBuildModel bModel = new WorkspaceBuildModel(file);
                        build = bModel.getBuild();
                    }
                    IPath[] paths = findLibrary(libName, project, classpathMap, build);
                    if (paths.length > 0)
                        return postfixFragmentAnnotation(paths);

                } catch (JavaModelException e) {
                    continue;
                }
                // if external plugin, look in child directories for library
            } else {
                File file = new File(frags[i].getInstallLocation());
                if (file.isDirectory()) {
                    file = new File(file, libName);
                    if (file.exists())
                        // Postfix fragment annotation for fragment path (fix bug 294211)
                        return new IPath[] { new Path(file.getPath() + FRAGMENT_ANNOTATION) };
                }
            }
        }
        return new IPath[0];
    }

    /*
     * Postfixes the fragment annotation for the paths that we know come
     * from fragments.  This is needed to fix bug 294211.
     */
    private static IPath[] postfixFragmentAnnotation(IPath[] paths) {
        for (int i = 0; i < paths.length; i++)
            paths[i] = new Path(paths[i].toString() + FRAGMENT_ANNOTATION);
        return paths;
    }

    private static void addPath(ArrayList result, IProject project, IPath path) {
        IPath resultPath = null;
        if (path.isAbsolute())
            resultPath = path;
        else if (path.segmentCount() > 0 && path.segment(0).equals(project.getName())) {
            IContainer bundleRoot = PDEProject.getBundleRoot(project);
            IPath rootPath = bundleRoot.getFullPath();
            // make path relative to bundle root
            path = path.makeRelativeTo(rootPath);
            if (path.segmentCount() == 0)
                resultPath = new Path(DOT);
            else {
                IResource resource = bundleRoot.findMember(path);
                if (resource != null)
                    resultPath = path;
            }
        }

        if (resultPath != null && !result.contains(resultPath))
            result.add(resultPath);
    }

    private static List getFoldersToExclude(IProject project, boolean checkExcluded) {
        ArrayList list = new ArrayList();
        if (checkExcluded) {
            IEclipsePreferences pref = new ProjectScope(project).getNode(MDECore.PLUGIN_ID);
            if (pref != null) {
                String binExcludes = pref.get(ICoreConstants.SELFHOSTING_BIN_EXCLUDES, ""); //$NON-NLS-1$
                StringTokenizer tokenizer = new StringTokenizer(binExcludes, ","); //$NON-NLS-1$
                while (tokenizer.hasMoreTokens()) {
                    list.add(new Path(tokenizer.nextToken().trim()));
                }
            }
        }
        return list;
    }

}