org.eclipse.jem.internal.beaninfo.core.BeaninfoEntry.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jem.internal.beaninfo.core.BeaninfoEntry.java

Source

/*******************************************************************************
 * Copyright (c) 2001, 2006 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 org.eclipse.jem.internal.beaninfo.core;
/*
    
    
 */

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.w3c.dom.*;

import org.eclipse.jem.internal.beaninfo.adapters.*;

/**
 * Beaninfo entry. Location of the beaninfos. Much like a standard classpath entry.
 * The BeanInfos are either in a jar or another project. They can be supplied as
 * a local file in the project, or as an external jar, or as external jar through a
 * variable, or an external jar through a plugin.
 * <p>
 * An external jar through containers is not valid because container are attached to
 * projects. they aren't standalone.
 * 
 * @version    1.0
 * @author
 */
public class BeaninfoEntry implements IBeaninfosDocEntry {

    final static String sBeaninfo = "beaninfo"; // Beaninfo entry, shared with BeaninfosDoc. //$NON-NLS-1$

    public static final int BIE_PLUGIN = 100; // Beaninfo jar can be found in a plugin.

    static int kindFromString(String kindStr) {
        if (kindStr == null || kindStr.length() == 0)
            return BIE_PLUGIN; // Default to plugin. If coming from beaninfoconfig, there should always be kind. But if coming from plugin.xml there shouldn't be one.
        if (kindStr.equalsIgnoreCase("con")) //$NON-NLS-1$
            return IClasspathEntry.CPE_CONTAINER;
        if (kindStr.equalsIgnoreCase("var")) //$NON-NLS-1$
            return IClasspathEntry.CPE_VARIABLE;
        if (kindStr.equalsIgnoreCase("src")) //$NON-NLS-1$
            return IClasspathEntry.CPE_SOURCE;
        if (kindStr.equalsIgnoreCase("lib")) //$NON-NLS-1$
            return IClasspathEntry.CPE_LIBRARY;
        if (kindStr.equalsIgnoreCase("plugin")) //$NON-NLS-1$
            return BIE_PLUGIN;
        return -1;
    }

    static String kindToString(int kind) {

        switch (kind) {
        case IClasspathEntry.CPE_PROJECT:
            return "src"; // backward compatibility //$NON-NLS-1$
        case IClasspathEntry.CPE_SOURCE:
            return "src"; //$NON-NLS-1$
        case IClasspathEntry.CPE_LIBRARY:
            return "lib"; //$NON-NLS-1$
        case IClasspathEntry.CPE_VARIABLE:
            return "var"; //$NON-NLS-1$
        case IClasspathEntry.CPE_CONTAINER:
            return "con"; //$NON-NLS-1$
        case BIE_PLUGIN:
            return "plugin"; //$NON-NLS-1$
        default:
            return "unknown"; //$NON-NLS-1$
        }
    }

    /**
     * Return the appropriate kind of entry when we know it is a classpath entry.
     */
    public static IClasspathEntry createEntry(int kind, IPath path, IProject project, boolean isExported) {
        switch (kind) {

        case IClasspathEntry.CPE_LIBRARY:
            if (path.isAbsolute())
                return JavaCore.newLibraryEntry(path, null, null, isExported);
            break;

        case IClasspathEntry.CPE_SOURCE:
            if (path.isAbsolute()) {
                // must be an entry in this project or specify another project
                String projSegment = path.segment(0);
                if (project != null && projSegment != null && projSegment.equals(project.getName())) {
                    // this project
                    return JavaCore.newSourceEntry(path);
                } else {
                    // another project
                    return JavaCore.newProjectEntry(path, isExported);
                }
            }
            break;

        case IClasspathEntry.CPE_VARIABLE:
            return JavaCore.newVariableEntry(path, null, null, isExported);

        case IClasspathEntry.CPE_CONTAINER:
            return JavaCore.newContainerEntry(path, isExported);

        }

        return null;
    }

    /**
     * Read the entry in from the element.
     */
    public static BeaninfoEntry readEntry(IReader reader, Object element, IProject project) {
        String elementKind = reader.getAttribute(element, BeaninfosDoc.sKind);
        String pathStr = reader.getAttribute(element, BeaninfosDoc.sPath);
        // ensure path is absolute
        IPath path = new Path(pathStr);
        int kind = kindFromString(elementKind);
        if (kind != IClasspathEntry.CPE_VARIABLE && kind != IClasspathEntry.CPE_CONTAINER && kind != BIE_PLUGIN
                && !path.isAbsolute()) {
            path = project != null ? project.getFullPath().append(path) : path.makeAbsolute(); // Some folder/jar within this project
        }

        // exported flag
        String exportedString = reader.getAttribute(element, BeaninfosDoc.sExported);
        boolean isExported = "true".equalsIgnoreCase(exportedString); //$NON-NLS-1$
        //$NON-NLS-1$

        // recreate the entry
        IClasspathEntry cpEntry = null;
        IPath pluginPath = null;
        if (kind != BIE_PLUGIN) {
            cpEntry = createEntry(kind, path, project, isExported);
        } else {
            if (path.isAbsolute())
                pluginPath = path;
            else {
                // Kludge This should only be a plugin type if from configuration element. So we will cast to that
                // and get the plugin id to create an absolute plugin path.
                if (element instanceof IConfigurationElement) {
                    pluginPath = new Path('/'
                            + ((IConfigurationElement) element).getDeclaringExtension().getContributor().getName())
                                    .append(path);
                } else
                    return null; // Not valid because can't have plugin from .beaninfoconfig file.
            }
        }

        ArrayList searchpaths = new ArrayList();
        Object children = reader.getChildren(element);
        int childrenLength = reader.getLength(children);
        for (int i = 0; i < childrenLength; i++) {
            Object child = reader.getItem(children, i);
            if (reader.isNodeTypeElement(child)) {
                Object entry = null;
                if (reader.getNodeName(child).equalsIgnoreCase(SearchpathEntry.sSearchpath)) {
                    entry = SearchpathEntry.readEntry(reader, child, project, true);
                }
                if (entry != null)
                    searchpaths.add(entry);
            }
        }

        if (cpEntry != null)
            return new BeaninfoEntry(cpEntry,
                    (SearchpathEntry[]) searchpaths.toArray(new SearchpathEntry[searchpaths.size()]), isExported);
        else
            return new BeaninfoEntry(pluginPath,
                    (SearchpathEntry[]) searchpaths.toArray(new SearchpathEntry[searchpaths.size()]), isExported);
    }

    protected IClasspathEntry entry; // Store it as a classpath entry for convienence. It is the RAW classpath entry. This is only used when pointing to something other than a plugin.
    protected IPath pluginPath; // When stored in a plugin, this will be set instead.
    protected boolean isExported;
    protected SearchpathEntry[] searchpaths;

    /**
     * Used when the beaninfo jar is within a plugin. In that case, the first segment
     * of the path is the plugin descriptor, and the rest is the path from the plugin
     * directory to the jar.
     */
    public BeaninfoEntry(IPath pluginPath, SearchpathEntry[] searchpaths, boolean isExported) {
        this(searchpaths, isExported);
        this.pluginPath = pluginPath;
    }

    /**
     * Used when the beaninfo jar/folder is either an external jar/folder or is somewhere else
     * in the workspace. In that case the entry is the RAW classpath entry to that code.
     */
    public BeaninfoEntry(IClasspathEntry entry, SearchpathEntry[] searchpaths, boolean isExported) {
        this(searchpaths, isExported);
        this.entry = entry;
    }

    protected BeaninfoEntry(SearchpathEntry[] searchpaths, boolean isExported) {
        this.isExported = isExported;
        this.searchpaths = searchpaths != null ? searchpaths : new SearchpathEntry[0];
    }

    public SearchpathEntry[] getSearchPaths() {
        return searchpaths;
    }

    public void setSearchPaths(SearchpathEntry[] searchpaths) {
        this.searchpaths = searchpaths;
    }

    public boolean isExported() {
        return isExported;
    }

    public void setIsExported(boolean isExported) {
        this.isExported = isExported;
    }

    public Node writeEntry(Document doc, IProject project) {

        Element element = doc.createElement(sBeaninfo);
        IPath path = null;
        if (entry != null) {
            element.setAttribute(BeaninfosDoc.sKind, kindToString(entry.getEntryKind()));
            path = entry.getPath();
            if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE
                    && entry.getEntryKind() != IClasspathEntry.CPE_CONTAINER) {
                // translate to project relative from absolute (unless a device path)
                if (path.isAbsolute()) {
                    if (path.segment(0).equals(project.getFullPath().segment(0))) {
                        path = path.removeFirstSegments(1);
                        path = path.makeRelative();
                    } else {
                        path = path.makeAbsolute();
                    }
                }
            }
        } else {
            element.setAttribute(BeaninfosDoc.sKind, kindToString(BIE_PLUGIN));
            path = pluginPath;
        }

        element.setAttribute(BeaninfosDoc.sPath, path.toString()); //$NON-NLS-1$
        if (isExported()) {
            element.setAttribute(BeaninfosDoc.sExported, "true"); //$NON-NLS-1$
        }

        for (int i = 0; i < searchpaths.length; i++) {
            SearchpathEntry spe = searchpaths[i];
            element.appendChild(spe.writeEntry(doc, project));
        }

        return element;
    }

    /**
     * If this is not a plugin info, then return the classpath entry.
     */
    public IClasspathEntry getClasspathEntry() {
        return entry;
    }

    /**
     * Return the resolved classpaths. Each entry in the array will be either:
     * 1) IProject - If it is a project type entry. Want the whole project
     * 2) String - an absolute external path to a jar
     * 3) IPath - a path to a plugin jar. The first segment is the plugin id, the rest is the path relative to that plugin.
     *            
     * 
     * @param javaProject
     * @return The array of paths, or <code>null</code> if no paths.
     * 
     * @since 1.0.0
     */
    public Object[] getClasspath(IJavaProject javaProject) {
        if (entry != null) {
            // It is a standard CPE Entry.
            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            List paths = new ArrayList(1);
            IClasspathEntry resolvedEntry = JavaCore.getResolvedClasspathEntry(entry);
            resolveEntry(root, paths, resolvedEntry, javaProject);
            return paths.toArray();
        } else if (pluginPath != null)
            return new Object[] { pluginPath };

        return null;

    }

    private void resolveEntry(IWorkspaceRoot root, List paths, IClasspathEntry entry, IJavaProject javaProject) {
        switch (entry.getEntryKind()) {
        case IClasspathEntry.CPE_PROJECT:
            IProject reqProject = (IProject) root.findMember(entry.getPath().lastSegment());
            // Project entries only have one segment.
            if (reqProject != null && reqProject.isOpen())
                paths.add(reqProject);
            break;

        case IClasspathEntry.CPE_SOURCE:
            reqProject = (IProject) root.findMember(entry.getPath().segment(0));
            // Find project from the first segment.
            IJavaProject jProject = JavaCore.create(reqProject);
            if (jProject != null) {
                try {
                    IPath outputLocation = jProject.getOutputLocation();
                    IResource resource = root.findMember(outputLocation);
                    if (resource != null) {
                        paths.add(resource.getLocation().toString());
                    }
                } catch (JavaModelException e) {
                }
            }
            break;

        case IClasspathEntry.CPE_LIBRARY:
            IResource library = root.findMember(entry.getPath());
            // can be external or in workspace
            paths.add((library != null) ? library.getLocation().toString() : entry.getPath().toString());
            break;

        case IClasspathEntry.CPE_CONTAINER:
            try {
                IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), javaProject);
                if (container != null) {
                    IClasspathEntry[] entries = container.getClasspathEntries();
                    for (int i = 0; i < entries.length; i++) {
                        resolveEntry(root, paths, entries[i], javaProject);
                    }
                }
            } catch (JavaModelException e) {
                BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
            }
        }
    }

    public int getKind() {
        return entry != null ? entry.getEntryKind() : BIE_PLUGIN;
    }

    public IPath getPath() {
        return entry != null ? entry.getPath() : pluginPath;
    }

    public boolean equals(Object other) {
        if (this == other)
            return true;

        if (!(other instanceof BeaninfoEntry))
            return false;

        // Return equal if the classpath entry is the same classpath entry or plugin path entry.
        // The search path doesn't have any affect on the semantic equality.
        BeaninfoEntry otherEntry = (BeaninfoEntry) other;
        if (isExported != otherEntry.isExported)
            return false;
        if (entry != null)
            return entry.equals(otherEntry.entry);

        return pluginPath.equals(otherEntry.pluginPath);
    }

    public int hashCode() {
        if (entry != null)
            return entry.hashCode() ^ (isExported ? Boolean.TRUE : Boolean.FALSE).hashCode();
        else
            return pluginPath.hashCode() ^ (isExported ? Boolean.TRUE : Boolean.FALSE).hashCode();
    }

}