org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2005 Oracle Corporation.
 * 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:
 *    Ian Trimble - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.jsf.core.jsfappconfig;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jst.j2ee.common.ParamValue;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
import org.eclipse.jst.j2ee.model.IModelProvider;
import org.eclipse.jst.j2ee.model.ModelProviderManager;
import org.eclipse.jst.j2ee.web.componentcore.util.WebArtifactEdit;
import org.eclipse.jst.j2ee.webapplication.ContextParam;
import org.eclipse.jst.j2ee.webapplication.WebApp;
import org.eclipse.jst.jsf.common.internal.componentcore.AbstractVirtualComponentQuery.DefaultVirtualComponentQuery;
import org.eclipse.jst.jsf.core.IJSFCoreConstants;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.core.internal.Messages;
import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigFactory;
import org.eclipse.jst.jsf.facesconfig.emf.ManagedBeanExtensionType;
import org.eclipse.jst.jsf.facesconfig.emf.ManagedBeanType;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;

/**
 * JSFAppConfigUtils provides utility methods useful in processing of a JSF
 * application configuration.
 * 
 * <p><b>Provisional API - subject to change</b></p>
 * 
 * @author Ian Trimble - Oracle
 */
public class JSFAppConfigUtils {

    /**
     * Name of JSF CONFIG_FILES context parameter ("javax.faces.CONFIG_FILES").
     */
    public static final String CONFIG_FILES_CONTEXT_PARAM_NAME = "javax.faces.CONFIG_FILES"; //$NON-NLS-1$

    /**
     * Location in JAR file of application configuration resource file
     * ("META-INF/faces-config.xml"). 
     */
    public static final String FACES_CONFIG_IN_JAR_PATH = "META-INF/faces-config.xml"; //$NON-NLS-1$

    /** ID of managed bean's description instance to indicate content identifies bean's "source" **/
    public static final String MANAGEDBEAN_SOURCE_ID = "MANAGEDBEAN_SOURCE_ID"; //$NON-NLS-1$
    /** Indicates that a managed bean was defined in a faces-config file **/
    public static final String MANAGEDBEAN_SOURCE_FACES_CONFIG_FILE = "FACES_CONFIG_FILE"; //$NON-NLS-1$
    /** Indicates that a managed bean was defined by a JSF annotation **/
    public static final String MANAGEDBEAN_SOURCE_JSF_ANNOTATION = "JSF_ANNOTATION"; //$NON-NLS-1$
    /** Indicates that a managed bean was defined by a CDI annotation **/
    public static final String MANAGEDBEAN_SOURCE_CDI_ANNOTATION = "CDI_ANNOTATION"; //$NON-NLS-1$

    /**
     * @param project
     * @param minVersion
     * @return true if project is a JSF facet project and the version of the project
     * is at least minVersion.
     */
    public static boolean isValidJSFProject(IProject project, String minVersion) {
        boolean isValid = false;

        final IProjectFacetVersion projectFacetVersion = getProjectFacet(project);

        if (projectFacetVersion != null) {
            try {
                final String versionString = projectFacetVersion.getVersionString();
                final Comparator comparator = projectFacetVersion.getProjectFacet().getVersionComparator();
                final int compareToMin = comparator.compare(versionString, minVersion);

                if (compareToMin >= 0) {
                    return true;
                }
            } catch (CoreException ce) {
                JSFCorePlugin.log(ce, "Error checking facet version"); //$NON-NLS-1$
            }
        }
        return isValid;
    }

    /**
     * Tests if the passed IProject instance is a valid JSF project in the
     * following ways:
     * <ul>
     * <li>project is not null and is accessible, </li>
     * <li>project has the JSF facet set on it.</li>
     * </ul>
     * 
     * @param project IProject instance to be tested.
     * @return true if the IProject instance is a valid JSF project, else
     * false.
     */
    public static boolean isValidJSFProject(IProject project) {
        boolean isValid = false;
        IProjectFacetVersion projectFacet = getProjectFacet(project);
        if (projectFacet != null) {
            isValid = true;
        }
        return isValid;
    }

    /**
     * Get the facet version for the project 
     * @param project
     * @return the project facet version or null if could not be found or if
     * project is not accessible
     */
    public static IProjectFacetVersion getProjectFacet(IProject project) {
        //check for null or inaccessible project
        if (project != null && project.isAccessible()) {
            //check for JSF facet on project
            try {
                IFacetedProject facetedProject = ProjectFacetsManager.create(project);
                if (facetedProject != null) {
                    Set projectFacets = facetedProject.getProjectFacets();
                    Iterator itProjectFacets = projectFacets.iterator();
                    while (itProjectFacets.hasNext()) {
                        IProjectFacetVersion projectFacetVersion = (IProjectFacetVersion) itProjectFacets.next();
                        if (IJSFCoreConstants.JSF_CORE_FACET_ID
                                .equals(projectFacetVersion.getProjectFacet().getId())) {
                            return projectFacetVersion;
                        }
                    }
                }
            } catch (CoreException ce) {
                //log error
                JSFCorePlugin.log(IStatus.ERROR, ce.getLocalizedMessage(), ce);
            }
        }
        return null;
    }

    /**
     * Gets an IVirtualFolder instance which represents the root context's
     * web content folder.
     * 
     * @param project IProject instance for which to get the folder.
     * @return IVirtualFolder instance which represents the root context's
     * web content folder.
     * @deprecated Call DefaultVirtualComponentQuery.getWebContentFolder instead
     */
    public static IVirtualFolder getWebContentFolder(IProject project) {
        return new DefaultVirtualComponentQuery().getWebContentFolder(project);
    }

    /**
     * Gets an IPath instance representing the path of the passed IFile
     * instance relative to the web content folder.
     * 
     * @param file IFile instance for which a path is required.
     * @return IPath instance representing the path relative to the web content
     * folder.
     */
    public static IPath getWebContentFolderRelativePath(IFile file) {
        IPath path = null;
        if (file != null) {
            IVirtualFolder webContentFolder = getWebContentFolder(file.getProject());
            if (webContentFolder != null) {
                IPath webContentPath = webContentFolder.getProjectRelativePath();
                IPath filePath = file.getProjectRelativePath();
                int matchingFirstSegments = webContentPath.matchingFirstSegments(filePath);
                path = filePath.removeFirstSegments(matchingFirstSegments);
            }
        }
        return path;
    }

    /**
     * Gets list of application configuration file names as listed in the JSF
     * CONFIG_FILES context parameter ("javax.faces.CONFIG_FILES"). Will return
     * an empty list if WebArtifactEdit is null, if WebApp is null, if context
     * parameter does not exist, or if trimmed context parameter's value is
     * an empty String.
     * 
     * @param project IProject instance for which to get the context
     * parameter's value.
     * @return List of application configuration file names as listed in the
     * JSF CONFIG_FILES context parameter ("javax.faces.CONFIG_FILES"); list
     * may be empty.
     */
    public static List getConfigFilesFromContextParam(IProject project) {
        List filesList = Collections.EMPTY_LIST;
        if (isValidJSFProject(project)) {
            IModelProvider provider = ModelProviderManager.getModelProvider(project);
            Object webAppObj = provider.getModelObject();
            if (webAppObj != null) {
                if (webAppObj instanceof WebApp)
                    filesList = getConfigFilesForJ2EEApp(project);
                else if (webAppObj instanceof org.eclipse.jst.javaee.web.WebApp)
                    filesList = getConfigFilesForJEEApp((org.eclipse.jst.javaee.web.WebApp) webAppObj);
            }

        }
        return filesList;
    }

    private static List getConfigFilesForJEEApp(org.eclipse.jst.javaee.web.WebApp webApp) {
        String filesString = null;
        List contextParams = webApp.getContextParams();
        Iterator itContextParams = contextParams.iterator();
        while (itContextParams.hasNext()) {
            org.eclipse.jst.javaee.core.ParamValue paramValue = (org.eclipse.jst.javaee.core.ParamValue) itContextParams
                    .next();
            if (paramValue.getParamName().equals(CONFIG_FILES_CONTEXT_PARAM_NAME)) {
                filesString = paramValue.getParamValue();
                break;
            }
        }
        return parseFilesString(filesString);
    }

    private static List getConfigFilesForJ2EEApp(IProject project) {
        List filesList = new ArrayList();
        WebArtifactEdit webArtifactEdit = WebArtifactEdit.getWebArtifactEditForRead(project);
        if (webArtifactEdit != null) {
            try {
                WebApp webApp = null;
                try {
                    webApp = webArtifactEdit.getWebApp();
                } catch (ClassCastException cce) {
                    //occasionally thrown from WTP code in RC3 and possibly later
                    JSFCorePlugin.log(IStatus.ERROR, cce.getLocalizedMessage(), cce);
                    return filesList;
                }
                if (webApp != null) {
                    String filesString = null;
                    //need to branch here due to model version differences (BugZilla #119442)
                    if (webApp.getVersionID() == J2EEVersionConstants.WEB_2_3_ID) {
                        EList contexts = webApp.getContexts();
                        Iterator itContexts = contexts.iterator();
                        while (itContexts.hasNext()) {
                            ContextParam contextParam = (ContextParam) itContexts.next();
                            if (contextParam.getParamName().equals(CONFIG_FILES_CONTEXT_PARAM_NAME)) {
                                filesString = contextParam.getParamValue();
                                break;
                            }
                        }
                    } else {
                        EList contextParams = webApp.getContextParams();
                        Iterator itContextParams = contextParams.iterator();
                        while (itContextParams.hasNext()) {
                            ParamValue paramValue = (ParamValue) itContextParams.next();
                            if (paramValue.getName().equals(CONFIG_FILES_CONTEXT_PARAM_NAME)) {
                                filesString = paramValue.getValue();
                                break;
                            }
                        }
                    }
                    filesList = parseFilesString(filesString);
                }
            } finally {
                webArtifactEdit.dispose();
            }
        }

        return filesList;
    }

    private static List parseFilesString(String filesString) {
        List filesList = new ArrayList();
        if (filesString != null && filesString.trim().length() > 0) {
            StringTokenizer stFilesString = new StringTokenizer(filesString, ","); //$NON-NLS-1$
            while (stFilesString.hasMoreTokens()) {
                String configFile = stFilesString.nextToken().trim();
                filesList.add(configFile);
            }
        }
        return filesList;
    }

    /**
     * Gets list of JAR file names, where each file name represents a JAR on
     * the classpath that contains a /META-INF/faces-config.xml entry. Will
     * return an empty list if no such JAR files are located.
     * 
     * @param project IProject instance for which to scan the classpath.
     * @return List of JAR file names, where each file name represents a JAR
     * on the classpath that contains a ...META-INF/faces-config.xml entry;
     * list may be empty.
     * @throws CoreException Thrown when underlying calls into JavaCore fail.
     * @throws IOException Thrown when attempt to open JAR to determine if it
     * contains a /META-INF/faces-config.xml entry fails.
     */
    public static List getConfigFileJARsFromClasspath(IProject project) throws CoreException, IOException {
        ArrayList JARsList = new ArrayList();
        if (project.isAccessible() && project.hasNature(JavaCore.NATURE_ID)) {
            IJavaProject javaProject = JavaCore.create(project);
            if (javaProject != null) {
                IClasspathEntry[] classpathEntries = javaProject.getResolvedClasspath(true);
                if (classpathEntries != null && classpathEntries.length > 0) {
                    IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
                    for (int i = 0; i < classpathEntries.length; i++) {
                        IClasspathEntry classpathEntry = classpathEntries[i];
                        if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
                            IPath libraryPath = classpathEntry.getPath();
                            if (libraryPath.getFileExtension() != null
                                    && libraryPath.getFileExtension().length() > 0) {
                                if (libraryPath.getDevice() == null
                                        && workspaceRoot.getProject(libraryPath.segment(0)).exists()) {
                                    libraryPath = workspaceRoot.getFile(libraryPath).getLocation();
                                }
                                String libraryPathString = libraryPath.toString();
                                JarFile jarFile = null;
                                try {
                                    //check existence first [222249]
                                    File file = new File(libraryPathString);
                                    if (file.exists()) {
                                        jarFile = new JarFile(file, false);
                                        if (jarFile != null) {
                                            JarEntry jarEntry = jarFile.getJarEntry(FACES_CONFIG_IN_JAR_PATH);
                                            if (jarEntry != null) {
                                                JARsList.add(libraryPathString);
                                            }
                                        }
                                    }
                                } catch (FileNotFoundException fnfex) {
                                    //should not get here, but eat error since this could only occur in under strange circumstances [222249]
                                } catch (IOException ioe) {
                                    JSFCorePlugin.log(IStatus.ERROR,
                                            NLS.bind(Messages.JSFAppConfigUtils_ErrorOpeningJarFile,
                                                    libraryPathString),
                                            ioe);
                                } finally {
                                    if (jarFile != null) {
                                        jarFile.close();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return JARsList;
    }

    //Bug 306451 - [JSF2.0] Support for Implicit navigation
    /**
     * Get all files that are possible destinations for implicit navigation (JSF 2.x or greater).
     * 
     * @param fromFile IFile instance that navigation is from.
     * @return List of IFile instances that are possible destinations.
     */
    public static List<IFile> getImplicitNavigationFiles(final IFile fromFile) {
        List<IFile> files = new ArrayList<IFile>();
        if (fromFile != null) {
            final IProject project = fromFile.getProject();
            if (isValidJSFProject(project, IJSFCoreConstants.JSF_VERSION_2_0)) {
                final IVirtualFolder webContentFolder = new DefaultVirtualComponentQuery()
                        .getWebContentFolder(project);
                if (webContentFolder != null) {
                    final IContainer[] rootContainers = webContentFolder.getUnderlyingFolders();
                    if (rootContainers != null && rootContainers.length > 0) {
                        for (int i = 0; i < rootContainers.length; i++) {
                            try {
                                rootContainers[i].accept(
                                        new JSFAppConfigUtils().new ImplicitNavigationResourceProxyVisitor(files),
                                        IResource.NONE);
                            } catch (CoreException cEx) {
                                JSFCorePlugin.log(IStatus.ERROR, cEx.getLocalizedMessage(), cEx);
                            }
                        }
                        files.remove(fromFile);
                    }
                }
            }
        }
        return files;
    }

    /**
     * Sets the "source" (one of the MANAGEDBEAN_SOURCE_* constants) of the managed bean.
     * @param managedBean Managed bean instance.
     * @param source "Source" of the managed bean.
     */
    public static void setManagedBeanSource(final ManagedBeanType managedBean, final String source) {
        if (managedBean != null) {
            ManagedBeanExtensionType extension = getManagedBeanSourceExtension(managedBean);
            if (extension == null) {
                extension = FacesConfigFactory.eINSTANCE.createManagedBeanExtensionType();
                extension.setId(MANAGEDBEAN_SOURCE_ID);
                managedBean.getManagedBeanExtension().add(extension);
            }
            final String content = extension.getTextContent();
            if (content != null) {
                if (!content.trim().equals(source)) {
                    extension.setTextContent(source);
                }
            } else {
                extension.setTextContent(source);
            }
        }
    }

    /**
     * Gets the "source" (one of the MANAGEDBEAN_SOURCE_* constants) of the managed bean.
     * @param managedBean Managed bean instance.
     * @return "Source" of the managed bean (assumes MANAGEDBEAN_SOURCE_FACES_CONFIG_FILE if not
     * set on the managed bean).
     */
    public static String getManagedBeanSource(final ManagedBeanType managedBean) {
        String source = MANAGEDBEAN_SOURCE_FACES_CONFIG_FILE;
        final ManagedBeanExtensionType extension = getManagedBeanSourceExtension(managedBean);
        if (extension != null) {
            source = extension.getTextContent().trim();
        }
        return source;
    }

    /**
     * Gets the managed bean instance's extension object that has ID of MANAGEDBEAN_SOURCE_ID.
     * @param managedBean Managed bean instance.
     * @return The managed bean's extension object that has ID of MANAGEDBEAN_SOURCE_ID.
     */
    public static ManagedBeanExtensionType getManagedBeanSourceExtension(final ManagedBeanType managedBean) {
        ManagedBeanExtensionType extension = null;
        if (managedBean != null) {
            final EList extensions = managedBean.getManagedBeanExtension();
            for (final Object curExtObj : extensions) {
                if (curExtObj instanceof ManagedBeanExtensionType) {
                    final ManagedBeanExtensionType curExt = (ManagedBeanExtensionType) curExtObj;
                    final String id = curExt.getId();
                    if (id != null && id.equals(MANAGEDBEAN_SOURCE_ID)) {
                        extension = curExt;
                        break;
                    }
                }
            }
        }
        return extension;
    }

    /**
     * Returns <code>true</code> if the managed bean is defined in a faces-config file.
     * @param managedBean Managed bean instance to test.
     * @return <code>true</code> if the managed bean is defined in a faces-config file, else
     * <code>false</code>.
     */
    public static boolean isDefinedInFacesConfigFile(final ManagedBeanType managedBean) {
        boolean ret = false;
        if (managedBean != null) {
            ret = !isDefinedByJSFAnnotation(managedBean) && !isDefinedByCDIAnnotation(managedBean);
        }
        return ret;
    }

    /**
     * Returns <code>true</code> if the managed bean is defined by a JSF annotation.
     * @param managedBean Managed bean instance to test.
     * @return <code>true</code> if the managed bean is defined by a JSF annotation, else
     * <code>false</code>.
     */
    public static boolean isDefinedByJSFAnnotation(final ManagedBeanType managedBean) {
        boolean ret = false;
        if (managedBean != null) {
            final String source = getManagedBeanSource(managedBean);
            if (source != null && source.equals(MANAGEDBEAN_SOURCE_JSF_ANNOTATION)) {
                ret = true;
            }
        }
        return ret;
    }

    /**
     * Returns <code>true</code> if the managed bean is defined by a CDI annotation.
     * @param managedBean Managed bean instance to test.
     * @return <code>true</code> if the managed bean is defined by a CDI annotation, else
     * <code>false</code>.
     */
    public static boolean isDefinedByCDIAnnotation(final ManagedBeanType managedBean) {
        boolean ret = false;
        if (managedBean != null) {
            final String source = getManagedBeanSource(managedBean);
            if (source != null && source.equals(MANAGEDBEAN_SOURCE_CDI_ANNOTATION)) {
                ret = true;
            }
        }
        return ret;
    }

    class ImplicitNavigationResourceProxyVisitor implements IResourceProxyVisitor {

        private List<IFile> files;
        private IContentTypeManager contentTypeMgr;
        private IContentType jspSourceType;
        private IContentType htmlSourceType;

        public ImplicitNavigationResourceProxyVisitor(List<IFile> files) {
            this.files = files;
            this.contentTypeMgr = Platform.getContentTypeManager();
            this.jspSourceType = contentTypeMgr.getContentType("org.eclipse.jst.jsp.core.jspsource"); //$NON-NLS-1$
            this.htmlSourceType = contentTypeMgr.getContentType("org.eclipse.wst.html.core.htmlsource"); //$NON-NLS-1$
        }

        public boolean visit(IResourceProxy proxy) throws CoreException {
            switch (proxy.getType()) {
            case IResource.FOLDER:
                return true;
            case IResource.FILE:
                IContentType contentType = contentTypeMgr.findContentTypeFor(proxy.getName());
                if (contentType != null) {
                    if (contentType.isKindOf(jspSourceType) || contentType.isKindOf(htmlSourceType)) {
                        files.add((IFile) proxy.requestResource());
                    }
                }
                break;
            }
            return false;
        }

    }

}