Skip to content

Commit

Permalink
MYFACES-4442: avoid UnsupportedOperationException
Browse files Browse the repository at this point in the history
  • Loading branch information
pnicolucci committed Aug 29, 2022
1 parent 7d3f827 commit 67ea9eb
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 77 deletions.
Expand Up @@ -85,19 +85,19 @@ public class FacesInitializerImpl implements FacesInitializer
private static final Logger log = Logger.getLogger(FacesInitializerImpl.class.getName());

public static final String CDI_BEAN_MANAGER_INSTANCE = "oam.cdi.BEAN_MANAGER_INSTANCE";

private static final String CDI_SERVLET_CONTEXT_BEAN_MANAGER_ATTRIBUTE =
"jakarta.enterprise.inject.spi.BeanManager";

public static final String INJECTED_BEAN_STORAGE_KEY = "org.apache.myfaces.spi.BEAN_ENTRY_STORAGE";

public static final String INITIALIZED = "org.apache.myfaces.INITIALIZED";

private static final byte FACES_INIT_PHASE_PREINIT = 0;
private static final byte FACES_INIT_PHASE_POSTINIT = 1;
private static final byte FACES_INIT_PHASE_PREDESTROY = 2;
private static final byte FACES_INIT_PHASE_POSTDESTROY = 3;

/**
* Performs all necessary initialization tasks like configuring this Faces
* application.
Expand All @@ -115,14 +115,14 @@ public void initFaces(ServletContext servletContext)
}
return;
}

try
{
if (log.isLoggable(Level.FINEST))
{
log.finest("Initializing MyFaces");
}

long start = System.currentTimeMillis();

// Some parts of the following configuration tasks have been implemented
Expand All @@ -144,43 +144,34 @@ public void initFaces(ServletContext servletContext)
{
spf.initKnownServiceProviderMapInfo(externalContext, spfConfig);
}

// Parse and validate the web.xml configuration file


if (!WebConfigParamUtils.getBooleanInitParameter(externalContext,
MyfacesConfig.INITIALIZE_ALWAYS_STANDALONE, false))
{
FacesServletMappingUtils.ServletRegistrationInfo facesServletRegistration =
FacesServletMappingUtils.getFacesServletRegistration(facesContext, servletContext);
if (facesServletRegistration == null
|| facesServletRegistration.getMappings() == null
|| facesServletRegistration.getMappings().length == 0)
// check to see if the FacesServlet was found by MyFacesContainerInitializer
Boolean mappingAdded = (Boolean) servletContext.getAttribute(
MyFacesContainerInitializer.FACES_SERVLET_FOUND);

if (mappingAdded == null || !mappingAdded)
{
// check to see if the FacesServlet was found by MyFacesContainerInitializer
Boolean mappingAdded = (Boolean) servletContext.getAttribute(
MyFacesContainerInitializer.FACES_SERVLET_FOUND);
// check if the FacesServlet has been added dynamically
// in a Servlet 3.0 environment by MyFacesContainerInitializer
mappingAdded = (Boolean) servletContext.getAttribute(
MyFacesContainerInitializer.FACES_SERVLET_ADDED_ATTRIBUTE);

if (mappingAdded == null || !mappingAdded)
{
// check if the FacesServlet has been added dynamically
// in a Servlet 3.0 environment by MyFacesContainerInitializer
mappingAdded = (Boolean) servletContext.getAttribute(
MyFacesContainerInitializer.FACES_SERVLET_ADDED_ATTRIBUTE);

if (mappingAdded == null || !mappingAdded)
if (log.isLoggable(Level.WARNING))
{
if (log.isLoggable(Level.WARNING))
{
log.warning("No mappings of FacesServlet found. Abort initializing MyFaces.");
}
return;
log.warning("No mappings of FacesServlet found. Abort initializing MyFaces.");
}
return;
}
}
}

initCDIIntegration(servletContext, externalContext);

initContainerIntegration(servletContext, externalContext);

// log environment integrations
Expand All @@ -205,10 +196,10 @@ public void initFaces(ServletContext servletContext)
initWebsocketIntegration(servletContext, externalContext);

WebConfigParamsLogger.logWebContextParams(facesContext);

//Start ViewPoolProcessor if necessary
ViewPoolProcessor.initialize(facesContext);

MyfacesConfig config = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext());
if (config.isAutomaticExtensionlessMapping())
{
Expand All @@ -222,7 +213,7 @@ public void initFaces(ServletContext servletContext)
facesContext.getExternalContext().getApplicationMap().put(
MyfacesConfig.RESOURCE_BUNDLE_CONTROL, resourceBundleControl);
}

// print out a very prominent log message if the project stage is != Production
if (!facesContext.isProjectStage(ProjectStage.Production)
&& !facesContext.isProjectStage(ProjectStage.UnitTest))
Expand Down Expand Up @@ -476,49 +467,49 @@ public FacesContext initStartupFacesContext(ServletContext servletContext)
// before Application and RenderKit factories, so we should use different object.
return _createFacesContext(servletContext, true);
}

@Override
public void destroyStartupFacesContext(FacesContext facesContext)
{
_releaseFacesContext(facesContext);
}

@Override
public FacesContext initShutdownFacesContext(ServletContext servletContext)
{
return _createFacesContext(servletContext, false);
}
@Override

@Override
public void destroyShutdownFacesContext(FacesContext facesContext)
{
_releaseFacesContext(facesContext);
}

private FacesContext _createFacesContext(ServletContext servletContext, boolean startup)
{
ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, startup);
ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
FacesContext facesContext = new StartupFacesContextImpl(externalContext,
FacesContext facesContext = new StartupFacesContextImpl(externalContext,
externalContext, exceptionHandler, startup);
// If getViewRoot() is called during application startup or shutdown,

// If getViewRoot() is called during application startup or shutdown,
// it should return a new UIViewRoot with its locale set to Locale.getDefault().
UIViewRoot startupViewRoot = new UIViewRoot();
startupViewRoot.setLocale(Locale.getDefault());
facesContext.setViewRoot(startupViewRoot);

return facesContext;
}

private void _releaseFacesContext(FacesContext facesContext)
{
// make sure that the facesContext gets released.
// This is important in an OSGi environment
if (facesContext != null)
{
facesContext.release();
}
}
}

/**
Expand Down Expand Up @@ -819,7 +810,7 @@ private void dispatchInitializationEvent(ServletContext context, int operation)
* @return false if there are not plugins defined via ServiceLoader.
*/
private boolean loadFacesInitPluginsViaServiceLoader(ServletContext servletContext)
{
{
ServiceLoader<StartupListener> loader = ServiceLoader.load(StartupListener.class,
ClassUtils.getContextClassLoader());

Expand Down
Expand Up @@ -132,6 +132,9 @@ public void onStartup(Set<Class<?>> clazzes, ServletContext servletContext) thro
return;
}

// Check for a FacesServlet and store the result so it can be used by the FacesInitializer.
boolean isFacesServletPresent = checkForFacesServlet(servletContext);

// Check for one or more of this conditions:
// 1. A faces-config.xml file is found in WEB-INF
// 2. A faces-config.xml file is found in the META-INF directory of a jar in the application's classpath.
Expand All @@ -142,45 +145,42 @@ public void onStartup(Set<Class<?>> clazzes, ServletContext servletContext) thro
// implementation is not empty.
if ((clazzes != null && !clazzes.isEmpty()) || isFacesConfigPresent(servletContext))
{
// look for the FacesServlet
Map<String, ? extends ServletRegistration> servlets = servletContext.getServletRegistrations();
for (Map.Entry<String, ? extends ServletRegistration> servletEntry : servlets.entrySet())
/*
* If we get into this code block the application contains some Faces artifacts, either a faces-config.xml
* or one ore more classes from @HandlesTypes. However if classes from @HandlesTypes or a faces-config.xml
* is available a FacesServlet definition might not be defined.
*
* If a FacesServet definition was not found then add it dynamically.
*/
if(!isFacesServletPresent)
{
String className = servletEntry.getValue().getClassName();
if (FACES_SERVLET_CLASS.getName().equals(className) || isDelegatedFacesServlet(className))
// the FacesServlet is not installed yet - install it
ServletRegistration.Dynamic servlet =
servletContext.addServlet(FACES_SERVLET_NAME, FACES_SERVLET_CLASS);

//try to add typical Faces mappings
String[] mappings = isAutomaticXhtmlMappingDisabled(servletContext) ?
FACES_SERVLET_MAPPINGS : FACES_SERVLET_FULL_MAPPINGS;
Set<String> conflictMappings = servlet.addMapping(mappings);
if (conflictMappings != null && !conflictMappings.isEmpty())
{
// we found a FacesServlet; set an attribute for use during initialization
servletContext.setAttribute(FACES_SERVLET_FOUND, Boolean.TRUE);
return;
//at least one of the attempted mappings is in use, remove and try again
Set<String> newMappings = new HashSet<>(Arrays.asList(mappings));
newMappings.removeAll(conflictMappings);
mappings = newMappings.toArray(new String[newMappings.size()]);
servlet.addMapping(mappings);
}
}

// the FacesServlet is not installed yet - install it
ServletRegistration.Dynamic servlet = servletContext.addServlet(FACES_SERVLET_NAME, FACES_SERVLET_CLASS);

//try to add typical Faces mappings
String[] mappings = isAutomaticXhtmlMappingDisabled(servletContext) ?
FACES_SERVLET_MAPPINGS : FACES_SERVLET_FULL_MAPPINGS;
Set<String> conflictMappings = servlet.addMapping(mappings);
if (conflictMappings != null && !conflictMappings.isEmpty())
{
//at least one of the attempted mappings is in use, remove and try again
Set<String> newMappings = new HashSet<>(Arrays.asList(mappings));
newMappings.removeAll(conflictMappings);
mappings = newMappings.toArray(new String[newMappings.size()]);
servlet.addMapping(mappings);
}

if (mappings != null && mappings.length > 0)
{
// at least one mapping was added
// now we have to set a field in the ServletContext to indicate that we have
// added the mapping dynamically, because MyFaces just parsed the web.xml to
// find mappings and thus it would abort initializing
servletContext.setAttribute(FACES_SERVLET_ADDED_ATTRIBUTE, Boolean.TRUE);
if (mappings != null && mappings.length > 0)
{
// at least one mapping was added
// now we have to set a field in the ServletContext to indicate that we have
// added the mapping dynamically.
servletContext.setAttribute(FACES_SERVLET_ADDED_ATTRIBUTE, Boolean.TRUE);

// add a log message
log.log(Level.INFO, "Added FacesServlet with mappings=" + Arrays.toString(mappings));
// add a log message
log.log(Level.INFO, "Added FacesServlet with mappings=" + Arrays.toString(mappings));
}
}
}
}
Expand Down Expand Up @@ -304,6 +304,28 @@ private boolean isFacesConfigPresent(ServletContext servletContext)
}
}

/*
* Checks if a FacesServlet has been mapped.
*/
private boolean checkForFacesServlet(ServletContext servletContext)
{
// look for the FacesServlet
Map<String, ? extends ServletRegistration> servlets = servletContext.getServletRegistrations();
boolean isFacesServletPresent = false;

for (Map.Entry<String, ? extends ServletRegistration> servletEntry : servlets.entrySet())
{
String className = servletEntry.getValue().getClassName();
if (FACES_SERVLET_CLASS.getName().equals(className) || isDelegatedFacesServlet(className))
{
// we found a FacesServlet; set an attribute for use during initialization
servletContext.setAttribute(FACES_SERVLET_FOUND, Boolean.TRUE);
isFacesServletPresent = true;
}
}
return isFacesServletPresent;
}

/**
* Checks if the class represented by className implements DelegatedFacesServlet.
* @param className
Expand Down

0 comments on commit 67ea9eb

Please sign in to comment.