All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.faces.config.processor.AbstractConfigProcessor Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.faces.config.processor;

import static com.sun.faces.application.ApplicationResourceBundle.DEFAULT_KEY;
import static com.sun.faces.config.ConfigManager.INJECTION_PROVIDER_KEY;
import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesProjectStage;
import static com.sun.faces.util.ReflectionUtils.lookupConstructor;
import static jakarta.faces.FactoryFinder.APPLICATION_FACTORY;
import static jakarta.faces.application.ProjectStage.Development;
import static jakarta.faces.application.ProjectStage.Production;
import static java.text.MessageFormat.format;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.SEVERE;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.sun.faces.application.ApplicationAssociate;
import com.sun.faces.application.ApplicationInstanceFactoryMetadataMap;
import com.sun.faces.application.ApplicationResourceBundle;
import com.sun.faces.config.ConfigManager;
import com.sun.faces.config.ConfigurationException;
import com.sun.faces.config.WebConfiguration;
import com.sun.faces.spi.InjectionProvider;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.Util;

import jakarta.faces.FacesException;
import jakarta.faces.FactoryFinder;
import jakarta.faces.application.Application;
import jakarta.faces.application.ApplicationFactory;
import jakarta.faces.application.ProjectStage;
import jakarta.faces.context.FacesContext;
import jakarta.servlet.ServletContext;

/**
 * 

* This is the base ConfigProcessor that all concrete ConfigProcessor implementations should * extend. *

*/ public abstract class AbstractConfigProcessor implements ConfigProcessor { private static final Logger LOGGER = FacesLogger.CONFIG.getLogger(); private static final String CLASS_METADATA_MAP_KEY_SUFFIX = ".METADATA"; // -------------------------------------------- Methods from ConfigProcessor private ApplicationInstanceFactoryMetadataMap getClassMetadataMap(ServletContext servletContext) { ApplicationInstanceFactoryMetadataMap classMetadataMap = (ApplicationInstanceFactoryMetadataMap) servletContext .getAttribute(getClassMetadataMapKey()); if (classMetadataMap == null) { classMetadataMap = new ApplicationInstanceFactoryMetadataMap(new ConcurrentHashMap<>()); servletContext.setAttribute(getClassMetadataMapKey(), classMetadataMap); } return classMetadataMap; } @Override public void initializeClassMetadataMap(ServletContext servletContext, FacesContext facesContext) { getClassMetadataMap(servletContext); } protected String getClassMetadataMapKey() { return getClass().getName() + CLASS_METADATA_MAP_KEY_SUFFIX; } @Override public void destroy(ServletContext sc, FacesContext facesContext) { } // ------------------------------------------------------- Protected Methods /** * @return return the Application instance for this context. */ protected Application getApplication() { return ((ApplicationFactory) FactoryFinder.getFactory(APPLICATION_FACTORY)).getApplication(); } /** *

* Return the text of the specified Node, if any. * * @param node the Node * @return the text of the Node If the length of the text is zero, this method will return * null */ protected String getNodeText(Node node) { String res = null; if (node != null) { res = node.getTextContent(); if (res != null) { res = res.trim(); } } return res != null && res.length() != 0 ? res : null; } /** * @return a Map of of textual values keyed off the values of any lang or xml:lang attributes specified on * an attribute. If no such attribute exists, then the key {@link ApplicationResourceBundle#DEFAULT_KEY} will be used * (i.e. this represents the default Locale). * @param list a list of nodes representing textual elements such as description or display-name */ protected Map getTextMap(List list) { if (list != null && !list.isEmpty()) { int len = list.size(); HashMap names = new HashMap<>(len, 1.0f); for (int i = 0; i < len; i++) { Node node = list.get(i); String textValue = getNodeText(node); if (textValue != null) { if (node.hasAttributes()) { NamedNodeMap attributes = node.getAttributes(); String lang = getNodeText(attributes.getNamedItem("lang")); if (lang == null) { lang = getNodeText(attributes.getNamedItem("xml:lang")); } if (lang != null) { names.put(lang, textValue); } else { names.put(DEFAULT_KEY, textValue); } } else { names.put(DEFAULT_KEY, textValue); } } } return names; } return null; } protected Class findRootType(ServletContext sc, FacesContext facesContext, String source, Node sourceNode, Class[] ctorArguments) { try { Class sourceClass = loadClass(sc, facesContext, source, this, null); for (Class ctorArg : ctorArguments) { if (lookupConstructor(sourceClass, ctorArg) != null) { return ctorArg; } } } catch (ClassNotFoundException cnfe) { throw new ConfigurationException(buildMessage(format("Unable to find class ''{0}''", source), sourceNode), cnfe); } return null; } protected Object createInstance(ServletContext sc, FacesContext facesContext, String className, Node source) { return createInstance(sc, facesContext, className, null, null, source); } protected Object createInstance(ServletContext sc, FacesContext facesContext, String className, Class rootType, Object root, Node source) { boolean[] didPerformInjection = { false }; Object result = createInstance(sc, facesContext, className, rootType, root, source, true, didPerformInjection); return result; } protected Object createInstance(ServletContext sc, FacesContext facesContext, String className, Class rootType, Object root, Node source, boolean performInjection, boolean[] didPerformInjection) { Class clazz; Object returnObject = null; if (className != null) { try { clazz = loadClass(sc, facesContext, className, returnObject, null); if (clazz != null) { if (returnObject == null) { // Look for an adapter constructor if we've got // an object to adapt if (rootType != null && root != null) { Constructor construct = lookupConstructor(clazz, rootType); if (construct != null) { returnObject = construct.newInstance(root); } } } if (clazz != null && returnObject == null) { returnObject = clazz.newInstance(); } ApplicationInstanceFactoryMetadataMap classMetadataMap = getClassMetadataMap(sc); if (classMetadataMap.hasAnnotations(className) && performInjection) { InjectionProvider injectionProvider = (InjectionProvider) facesContext.getAttributes().get(INJECTION_PROVIDER_KEY); try { injectionProvider.inject(returnObject); } catch (InjectionProviderException ex) { LOGGER.log(SEVERE, "Unable to inject instance" + className, ex); throw new FacesException(ex); } try { injectionProvider.invokePostConstruct(returnObject); } catch (InjectionProviderException ex) { LOGGER.log(SEVERE, "Unable to invoke @PostConstruct annotated method on instance " + className, ex); throw new FacesException(ex); } didPerformInjection[0] = true; } } } catch (ClassNotFoundException cnfe) { throw new ConfigurationException(buildMessage(format("Unable to find class ''{0}''", className), source), cnfe); } catch (NoClassDefFoundError ncdfe) { throw new ConfigurationException( buildMessage(format("Class ''{0}'' is missing a runtime dependency: {1}", className, ncdfe.toString()), source), ncdfe); } catch (ClassCastException cce) { throw new ConfigurationException(buildMessage(format("Class ''{0}'' is not an instance of ''{1}''", className, rootType), source), cce); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | FacesException e) { throw new ConfigurationException(buildMessage(format("Unable to create a new instance of ''{0}'': {1}", className, e.toString()), source), e); } } return returnObject; } protected void destroyInstance(ServletContext sc, FacesContext facesContext, String className, Object instance) { if (instance != null) { ApplicationInstanceFactoryMetadataMap classMetadataMap = getClassMetadataMap(sc); if (classMetadataMap.hasAnnotations(className)) { InjectionProvider injectionProvider = (InjectionProvider) facesContext.getAttributes().get(INJECTION_PROVIDER_KEY); if (injectionProvider != null) { try { injectionProvider.invokePreDestroy(instance); } catch (InjectionProviderException ex) { LOGGER.log(SEVERE, "Unable to invoke @PreDestroy annotated method on instance " + className, ex); throw new FacesException(ex); } } } } } protected Class loadClass(ServletContext sc, FacesContext facesContext, String className, Object fallback, Class expectedType) throws ClassNotFoundException { ApplicationInstanceFactoryMetadataMap classMetadataMap = getClassMetadataMap(sc); Class clazz = (Class) classMetadataMap.get(className); if (clazz == null) { try { clazz = Util.loadClass(className, fallback); if (!isDevModeEnabled(sc, facesContext)) { classMetadataMap.put(className, clazz); } else { classMetadataMap.scanForAnnotations(className, clazz); } } catch (Exception e) { throw new FacesException(e.getMessage(), e); } } if (expectedType != null && !expectedType.isAssignableFrom(clazz)) { throw new ClassCastException(); } return clazz; } protected void processAnnotations(FacesContext ctx, Class annotationType) { ApplicationAssociate.getInstance(ctx.getExternalContext()).getAnnotationManager().applyConfigAnnotations(ctx, annotationType, ConfigManager.getAnnotatedClasses(ctx).get(annotationType)); } // --------------------------------------------------------- Private Methods private String buildMessage(String cause, Node source) { return MessageFormat.format("\n Source Document: {0}\n Cause: {1}", source.getOwnerDocument().getDocumentURI(), cause); } private boolean isDevModeEnabled(ServletContext sc, FacesContext facesContext) { return getProjectStage(sc, facesContext).equals(Development); } private ProjectStage getProjectStage(ServletContext sc, FacesContext facesContext) { final String projectStageKey = AbstractConfigProcessor.class.getName() + ".PROJECTSTAGE"; ProjectStage projectStage = (ProjectStage) sc.getAttribute(projectStageKey); if (projectStage == null) { WebConfiguration webConfig = WebConfiguration.getInstance(facesContext.getExternalContext()); String value = webConfig.getEnvironmentEntry(WebConfiguration.WebEnvironmentEntry.ProjectStage); if (value != null) { if (LOGGER.isLoggable(FINE)) { LOGGER.log(FINE, "ProjectStage configured via JNDI: {0}", value); } } else { value = webConfig.getOptionValue(JakartaFacesProjectStage); if (value != null) { if (LOGGER.isLoggable(FINE)) { LOGGER.log(FINE, "ProjectStage configured via servlet context init parameter: {0}", value); } } } if (value != null) { try { projectStage = ProjectStage.valueOf(value); } catch (IllegalArgumentException iae) { if (LOGGER.isLoggable(INFO)) { LOGGER.log(INFO, "Unable to discern ProjectStage for value {0}.", value); } } } if (projectStage == null) { projectStage = Production; } sc.setAttribute(projectStageKey, projectStage); } return projectStage; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy