/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.faces.config; import java.lang.reflect.Field; import java.util.Collection; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Set; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.MalformedURLException; import java.security.Principal; import javax.faces.FacesException; import javax.faces.FactoryFinder; import javax.faces.render.RenderKit; import javax.faces.lifecycle.Lifecycle; import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; import javax.faces.application.NavigationHandler; import javax.faces.application.StateManager; import javax.faces.application.ViewHandler; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.component.behavior.Behavior; import javax.faces.context.FacesContext; import javax.faces.context.FacesContextFactory; import javax.faces.context.ExternalContext; import javax.faces.context.ResponseStream; import javax.faces.context.ResponseWriter; import javax.faces.context.ExternalContextFactory; import javax.faces.convert.Converter; import javax.faces.el.MethodBinding; import javax.faces.el.PropertyResolver; import javax.faces.el.ReferenceSyntaxException; import javax.faces.el.ValueBinding; import javax.faces.el.VariableResolver; import javax.faces.event.ActionListener; import javax.faces.validator.Validator; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.servlet.ServletContext; import com.sun.faces.application.InjectionApplicationFactory; import com.sun.faces.application.ApplicationFactoryImpl; import com.sun.faces.application.ApplicationAssociate; import com.sun.faces.application.ApplicationImpl; import com.sun.faces.cactus.ServletFacesTestCase; import com.sun.faces.config.processor.FactoryConfigProcessor; import com.sun.faces.context.FacesContextFactoryImpl; import com.sun.faces.context.FacesContextImpl; import com.sun.faces.context.ExceptionHandlerFactoryImpl; import com.sun.faces.context.ExternalContextFactoryImpl; import com.sun.faces.context.InjectionFacesContextFactory; import com.sun.faces.context.ExternalContextImpl; import com.sun.faces.lifecycle.ClientWindowFactoryImpl; import com.sun.faces.lifecycle.LifecycleImpl; import com.sun.faces.renderkit.RenderKitFactoryImpl; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @SuppressWarnings({"deprecation"}) public class TestFactoryInjection extends ServletFacesTestCase { // ------------------------------------------------------------ Constructors public TestFactoryInjection() { super("TestFactoryFinder"); } public TestFactoryInjection(String name) { super(name); } // ------------------------------------------------------------ Test Methods public void testFactoryFinderApplicationInjection() throws Exception { Document d = newFacesConfigDocument(); Node facesConfig = d.getFirstChild(); Element factory = createElement(d, "factory"); facesConfig.appendChild(factory); Element application = createElement(d, "application-factory"); factory.appendChild(application); application.setTextContent("com.sun.faces.application.ApplicationFactoryImpl"); // clear the factories FactoryFinder.releaseFactories(); ApplicationAssociate.clearInstance(getFacesContext().getExternalContext()); // invoke the FactoryConfigProcessor FactoryConfigProcessor fcp = new FactoryConfigProcessor(false); fcp.process((ServletContext) getFacesContext().getExternalContext().getContext(), new DocumentInfo[] { new DocumentInfo(d, null) }); // now get an Application instance from the Factory and ensure // no injection occured. ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); assertNotNull(appFactory); assertNull(appFactory.getWrapped()); Application app = appFactory.getApplication(); // reflect the 'defaultApplication' field to ensure it's null Field field = Application.class.getDeclaredField("defaultApplication"); field.setAccessible(true); assertNull(field.get(app)); // reset for the injection portion of the test FactoryFinder.releaseFactories(); ApplicationAssociate.clearInstance(getFacesContext().getExternalContext()); // add another factory to our document Element application2 = createElement(d, "application-factory"); factory.appendChild(application2); application2.setTextContent(BasicApplicationFactory.class.getName()); // process the document. This should cause the the InjectionApplicationFactory // to be put into play since there is more than one ApplicationFactory // being configured fcp.process((ServletContext) getFacesContext().getExternalContext().getContext(), new DocumentInfo[] { new DocumentInfo(d, null) }); // get the ApplicationFactory instance. The top-level factory should // be the InjectionApplicationFactory. appFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); assertNotNull(appFactory); assertEquals(InjectionApplicationFactory.class, appFactory.getClass()); ApplicationFactory wrapped1 = appFactory.getWrapped(); assertNotNull(wrapped1); assertEquals(BasicApplicationFactory.class, wrapped1.getClass()); ApplicationFactory wrapped2 = wrapped1.getWrapped(); assertEquals(ApplicationFactoryImpl.class, wrapped2.getClass()); // no ensure that the top level application instance's defaultApplication // instance was injected with the default Application instance. // This instance should be the same as that returned by wrapped2. app = appFactory.getApplication(); assertNotNull(app); Application fieldResult = (Application) field.get(app); assertNotNull(fieldResult); assertEquals(ApplicationImpl.class, fieldResult.getClass()); // basic application doesn't implement getProjetStage(), so without // injection, this method would throw an UnsupportedOperationException, // however, if we got this far, no exception should be thrown. try { app.getProjectStage(); } catch (UnsupportedOperationException uso) { fail("Application.getProjectStage() threw an Exception; injection failed"); } } public void testFactoryFinderFacesContextInjection() throws Exception { ExternalContext extContext = getFacesContext().getExternalContext(); ServletContext sc = (ServletContext) extContext.getContext(); Document d = newFacesConfigDocument(); Node facesConfig = d.getFirstChild(); Element factory = createElement(d, "factory"); facesConfig.appendChild(factory); Element application = createElement(d, "application-factory"); factory.appendChild(application); application .setTextContent("com.sun.faces.application.ApplicationFactoryImpl"); Element facesContext = createElement(d, "faces-context-factory"); factory.appendChild(facesContext); facesContext.setTextContent(FacesContextFactoryImpl.class.getName()); Element exceptionHandler = createElement(d, "exception-handler-factory"); factory.appendChild(exceptionHandler); exceptionHandler.setTextContent(ExceptionHandlerFactoryImpl.class.getName()); Element externalContextFactory = createElement(d, "external-context-factory"); factory.appendChild(externalContextFactory); externalContextFactory.setTextContent(ExternalContextFactoryImpl.class.getName()); Element clientWindowFactory = createElement(d, "client-window-factory"); factory.appendChild(clientWindowFactory); clientWindowFactory.setTextContent(ClientWindowFactoryImpl.class.getName()); Element renderKitFactory = createElement(d, "render-" + "kit-factory"); factory.appendChild(renderKitFactory); renderKitFactory.setTextContent(RenderKitFactoryImpl.class.getName()); // clear the factories FactoryFinder.releaseFactories(); ApplicationAssociate.clearInstance(extContext); FacesContext.getCurrentInstance().release(); // invoke the FactoryConfigProcessor FactoryConfigProcessor fcp = new FactoryConfigProcessor(false); InitFacesContext initContext = new InitFacesContext(sc); fcp.process(sc, new DocumentInfo[]{new DocumentInfo(d, null)}); initContext.release(); FacesContext.getCurrentInstance().release(); // now get an FacesContext instance from the Factory and ensure // no injection occured. FacesContextFactory fcFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); assertNotNull(fcFactory); assertNull(fcFactory.getWrapped()); FacesContext fc = fcFactory.getFacesContext(sc, request, response, new LifecycleImpl()); // reflect the 'defaultFacesContext' field to ensure it's null Field field = FacesContext.class.getDeclaredField("defaultFacesContext"); Field extField = ExternalContext.class.getDeclaredField("defaultExternalContext"); field.setAccessible(true); extField.setAccessible(true); assertNull(field.get(fc)); // reset for the injection portion of the test FactoryFinder.releaseFactories(); ApplicationAssociate.clearInstance(extContext); FacesContext.getCurrentInstance().release(); // add another factory to our document Element facesContext2 = createElement(d, "faces-context-factory"); factory.appendChild(facesContext2); facesContext2.setTextContent(BasicFacesContextFactory.class.getName()); // process the document. This should cause the the InjectionFacesContextFactory // to be put into play since there is more than one FacesContextFactory // being configured initContext = new InitFacesContext(sc); fcp.process(sc, new DocumentInfo[]{new DocumentInfo(d, null)}); initContext.release(); // get the FacesContextFactory instance. The top-level factory should // be the InjectionFacesContextFactory. fcFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); assertNotNull(fcFactory); assertEquals(InjectionFacesContextFactory.class, fcFactory.getClass()); FacesContextFactory wrapped1 = fcFactory.getWrapped(); assertNotNull(wrapped1); assertEquals(BasicFacesContextFactory.class, wrapped1.getClass()); FacesContextFactory wrapped2 = wrapped1.getWrapped(); assertEquals(FacesContextFactoryImpl.class, wrapped2.getClass()); // now ensure that the top level facescontext instance's defaultFacesContext // field was injected with the default FacesContext implementation. // Also ensure that the top level ExternalContext instance's defaultExternalContext // field was injected with the default ExternalContext implementation. fc = fcFactory.getFacesContext(sc, request, response, new LifecycleImpl()); assertNotNull(fc); FacesContext fieldResult = (FacesContext) field.get(fc); assertNotNull(fieldResult); assertEquals(FacesContextImpl.class, fieldResult.getClass()); ExternalContext extFieldResult = (ExternalContext) extField.get(fc.getExternalContext()); assertNotNull(extFieldResult); assertEquals(ExternalContextImpl.class, extFieldResult.getClass()); // basic facescontext doesn't implement getAttributes(), so without // injection, this method would throw an UnsupportedOperationException, // however, if we got this far, no exception should be thrown. try { fc.getAttributes(); } catch (UnsupportedOperationException uso) { fail("FacesContext.getAttributes() threw an Exception; injection failed"); } } // --------------------------------------------------------- Private Methods private Document newFacesConfigDocument() throws ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setNamespaceAware(true); Document d = factory.newDocumentBuilder().newDocument(); Element e = createElement(d, "faces-config"); d.appendChild(e); return d; } private Element createElement(Document d, String elementName) { final String ns = "http://java.sun.com/xml/ns/javaee"; return d.createElementNS(ns, elementName); } // ---------------------------------------------------------- Nested Classes public static final class BasicExternalContextFactory extends ExternalContextFactory { private ExternalContextFactory delegate; // -------------------------------------------------------- Constructors public BasicExternalContextFactory(ExternalContextFactory delegate) { this.delegate = delegate; } // ------------------------------------------- Methods from FacesWrapper @Override public ExternalContextFactory getWrapped() { return delegate; } // --------------------------------- Methods from ExternalContextFactory public ExternalContext getExternalContext(Object context, Object request, Object response) throws FacesException { ExternalContext extContext = delegate.getExternalContext(context, request, response); return new BasicExternalContext(extContext); } } public static final class BasicExternalContext extends ExternalContext { private ExternalContext delegate; public BasicExternalContext(ExternalContext delegate) { this.delegate = delegate; } public void dispatch(String path) throws IOException { } public String encodeActionURL(String url) { return null; } public String encodeNamespace(String name) { return null; } public String encodePartialActionURL(String viewId) { return null; } public String encodeResourceURL(String url) { return null; } public String encodeWebsocketURL(String url) { return null; } public Map<String, Object> getApplicationMap() { return null; } public String getAuthType() { return null; } public Object getContext() { return null; } public String getInitParameter(String name) { return null; } public Map getInitParameterMap() { return null; } public String getRemoteUser() { return null; } public Object getRequest() { return null; } public String getRequestContextPath() { return null; } public Map<String, Object> getRequestCookieMap() { return null; } public Map<String, String> getRequestHeaderMap() { return null; } public Map<String, String[]> getRequestHeaderValuesMap() { return null; } public Locale getRequestLocale() { return null; } public Iterator<Locale> getRequestLocales() { return null; } public Map<String, Object> getRequestMap() { return null; } public Map<String, String> getRequestParameterMap() { return null; } public Iterator<String> getRequestParameterNames() { return null; } public Map<String, String[]> getRequestParameterValuesMap() { return null; } public String getRequestPathInfo() { return null; } public String getRequestServletPath() { return null; } public URL getResource(String path) throws MalformedURLException { return null; } public InputStream getResourceAsStream(String path) { return null; } public Set<String> getResourcePaths(String path) { return null; } public Object getResponse() { return null; } public Object getSession(boolean create) { return null; } public Map<String, Object> getSessionMap() { return null; } public Principal getUserPrincipal() { return null; } public boolean isUserInRole(String role) { return false; } public void log(String message) { } public void log(String message, Throwable exception) { } public void redirect(String url) throws IOException { } } public static final class BasicFacesContextFactory extends FacesContextFactory { private FacesContextFactory delegate; // -------------------------------------------------------- Constructors public BasicFacesContextFactory(FacesContextFactory delegate) { this.delegate = delegate; } // ------------------------------------------- Methods from FacesWrapper @Override public FacesContextFactory getWrapped() { return delegate; } // ------------------------------------ Methods from FacesContextFactory public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle) throws FacesException { FacesContext fcdelegate = delegate.getFacesContext(context, request, response, lifecycle); return new BasicFacesContext(fcdelegate); } } // END BasicFacesContextFactory public static final class BasicFacesContext extends FacesContext { FacesContext delegate; public BasicFacesContext(FacesContext delegate) { this.delegate = delegate; } public Application getApplication() { return null; } public Iterator<String> getClientIdsWithMessages() { return null; } public ExternalContext getExternalContext() { return delegate.getExternalContext(); } public FacesMessage.Severity getMaximumSeverity() { return null; } public Iterator<FacesMessage> getMessages() { return null; } public Iterator<FacesMessage> getMessages(String clientId) { return null; } public RenderKit getRenderKit() { return null; } public boolean getRenderResponse() { return false; } public boolean getResponseComplete() { return false; } public ResponseStream getResponseStream() { return null; } public void setResponseStream(ResponseStream responseStream) { } public ResponseWriter getResponseWriter() { return null; } public void setResponseWriter(ResponseWriter responseWriter) { } public UIViewRoot getViewRoot() { return null; } public void setViewRoot(UIViewRoot root) { } public void addMessage(String clientId, FacesMessage message) { } public void release() { delegate.release(); } public void renderResponse() { } public void responseComplete() { } boolean validationFailed; @Override public boolean isValidationFailed() { return validationFailed; } @Override public void validationFailed() { this.validationFailed = true; } } // END BasicFacesContext public static final class BasicApplicationFactory extends ApplicationFactory { private ApplicationFactory delegate; // -------------------------------------------------------- Constructors public BasicApplicationFactory(ApplicationFactory delegate) { this.delegate = delegate; } // ------------------------------------------- Methods from FacesWrapper @Override public ApplicationFactory getWrapped() { return delegate; } // ------------------------------------- Methods from ApplicationFactory public Application getApplication() { return new BasicApplication(); } public void setApplication(Application application) { //To change body of implemented methods use File | Settings | File Templates. } } // END BasicApplicationFactory public static final class BasicApplication extends Application { public ActionListener getActionListener() { return null; } public void setActionListener(ActionListener listener) { } public Locale getDefaultLocale() { return null; } public void setDefaultLocale(Locale locale) { } public String getDefaultRenderKitId() { return null; } public void setDefaultRenderKitId(String renderKitId) { } public String getMessageBundle() { return null; } public void setMessageBundle(String bundle) { } public NavigationHandler getNavigationHandler() { return null; } public void setNavigationHandler(NavigationHandler handler) { } public PropertyResolver getPropertyResolver() { return null; } public void setPropertyResolver(PropertyResolver resolver) { } public VariableResolver getVariableResolver() { return null; } public void setVariableResolver(VariableResolver resolver) { } public ViewHandler getViewHandler() { return null; } public void setViewHandler(ViewHandler handler) { } public StateManager getStateManager() { return null; } public void setStateManager(StateManager manager) { } public void addComponent(String componentType, String componentClass) { } public UIComponent createComponent(String componentType) throws FacesException { return null; } public UIComponent createComponent(ValueBinding componentBinding, FacesContext context, String componentType) throws FacesException { return null; } public Iterator<String> getComponentTypes() { return null; } public void addConverter(String converterId, String converterClass) { } public void addConverter(Class<?> targetClass, String converterClass) { } public Converter createConverter(String converterId) { return null; } public Converter createConverter(Class<?> targetClass) { return null; } public Iterator<String> getConverterIds() { return null; } public Iterator<Class<?>> getConverterTypes() { return null; } public MethodBinding createMethodBinding(String ref, Class<?>[] params) throws ReferenceSyntaxException { return null; } public Iterator<Locale> getSupportedLocales() { return null; } public void setSupportedLocales(Collection<Locale> locales) { } public void addValidator(String validatorId, String validatorClass) { } public Validator createValidator(String validatorId) throws FacesException { return null; } public Iterator<String> getValidatorIds() { return null; } public void addBehavior(String behaviorId, String behaviorClass) { } public Behavior createBehavior(String behaviorId) throws FacesException { return null; } public Iterator<String> getBehaviorIds() { return null; } public ValueBinding createValueBinding(String ref) throws ReferenceSyntaxException { return null; } } // END BasicApplication }