/* * JBoss, Home of Professional Open Source * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.jsfunit.arquillian.container; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import javax.servlet.http.HttpSession; import org.jboss.jsfunit.api.BasicAuthentication; import org.jboss.jsfunit.api.Browser; import org.jboss.jsfunit.api.BrowserVersion; import org.jboss.jsfunit.api.Cookies; import org.jboss.jsfunit.api.FormAuthentication; import org.jboss.jsfunit.api.InitialPage; import org.jboss.jsfunit.api.InitialRequest; import org.jboss.jsfunit.api.Proxy; import org.jboss.jsfunit.framework.BasicAuthenticationStrategy; import org.jboss.jsfunit.framework.FormAuthenticationStrategy; import org.jboss.jsfunit.framework.InitialRequestStrategy; import org.jboss.jsfunit.framework.WebClientSpec; import org.jboss.jsfunit.framework.WebConversationFactory; import org.jboss.jsfunit.jsfsession.JSFClientSession; import org.jboss.jsfunit.jsfsession.JSFServerSession; import org.jboss.jsfunit.jsfsession.JSFSession; /** * JSFUnitSessionFactory * * @author Stan Silvert * @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a> * @version $Revision: $ */ public class JSFUnitSessionFactory { private static final String JSFSESSION_FIELD_INJECTED = JSFUnitTestEnricher.class.getName() + ".JSFSESSION_FIELD_INJECTED"; private static final String JSFSESSION_METHOD_INJECTED = JSFUnitTestEnricher.class.getName() + ".JSFSESSION_METHOD_INJECTED"; //-------------------------------------------------------------------------------------|| // Internal API -----------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| public static JSFClientSession getJSFClientSession(AnnotatedElement injectionPoint) throws IOException { return findJSFSession(injectionPoint).getJSFClientSession(); } public static JSFServerSession getJSFServerSession(AnnotatedElement injectionPoint) throws IOException { return findJSFSession(injectionPoint).getJSFServerSession(); } public static JSFSession findJSFSession(AnnotatedElement injectionPoint) throws IOException { JSFUnitSessionFactory factory = new JSFUnitSessionFactory(); ElementType injectionType = factory.getElementType(injectionPoint); HttpSession httpSession = WebConversationFactory.getSessionFromThreadLocal(); JSFSession jsfSession = null; if (injectionType == ElementType.FIELD) { jsfSession = (JSFSession) httpSession.getAttribute(JSFSESSION_FIELD_INJECTED); } if (injectionType == ElementType.METHOD) { jsfSession = (JSFSession) httpSession.getAttribute(JSFSESSION_METHOD_INJECTED); } if (jsfSession != null) { return jsfSession; } jsfSession = factory.createJSFSession(injectionPoint, injectionType, httpSession); return jsfSession; } //-------------------------------------------------------------------------------------|| // Internal Helpers -------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| public JSFUnitSessionFactory() { } private JSFSession createJSFSession(AnnotatedElement injectionPoint, ElementType injectionType, HttpSession httpSession) throws IOException { JSFSession jsfSession = new JSFSession(createWebClientSpec(injectionPoint, injectionType)); if (injectionType == ElementType.FIELD) { httpSession.setAttribute(JSFSESSION_FIELD_INJECTED, jsfSession); } if (injectionType == ElementType.METHOD) { httpSession.setAttribute(JSFSESSION_METHOD_INJECTED, jsfSession); } return jsfSession; } private WebClientSpec createWebClientSpec(AnnotatedElement injectionPoint, ElementType injectionType) { InitialPage initialPage = getAnnotation(InitialPage.class, injectionPoint, injectionType); if (initialPage == null) { throw new IllegalArgumentException( "@InitialPage required for injection. Specify at class level for field injection or at method level for method injection."); } Browser browser = null; BrowserVersion browserAnno = getAnnotation(BrowserVersion.class, injectionPoint, injectionType); if (browserAnno == null) { browser = Browser.DEFAULT; } if (browserAnno != null) { browser = browserAnno.value(); } String host = null; int port = 0; Proxy proxyAnno = getAnnotation(Proxy.class, injectionPoint, injectionType); if (proxyAnno != null) { host = proxyAnno.host(); port = proxyAnno.port(); } WebClientSpec wcSpec = new WebClientSpec(initialPage.value(), browser.getVersion(), host, port); BasicAuthentication basicAuthAnno = getAnnotation(BasicAuthentication.class, injectionPoint, injectionType); FormAuthentication formAuthAnno = getAnnotation(FormAuthentication.class, injectionPoint, injectionType); InitialRequest initReqAnno = getAnnotation(InitialRequest.class, injectionPoint, injectionType); validateOneNonNullInitialRequest(injectionType, basicAuthAnno, formAuthAnno, initReqAnno); if (basicAuthAnno != null) { String userName = basicAuthAnno.userName(); String password = basicAuthAnno.password(); wcSpec.setInitialRequestStrategy(new BasicAuthenticationStrategy(userName, password)); } if (formAuthAnno != null) { String userName = formAuthAnno.userName(); String password = formAuthAnno.password(); String submitComponent = formAuthAnno.submitComponent(); String userNameComponent = formAuthAnno.userNameComponent(); String passwordComponent = formAuthAnno.passwordComponent(); wcSpec.setInitialRequestStrategy( new FormAuthenticationStrategy( userName, password, submitComponent, userNameComponent, passwordComponent)); } if (initReqAnno != null) { Class<? extends InitialRequestStrategy> clazz = initReqAnno.value(); InitialRequestStrategy initReq = newInstance(clazz); wcSpec.setInitialRequestStrategy(initReq); } setCookies(wcSpec, injectionPoint, injectionType); return wcSpec; } private void setCookies(WebClientSpec wcSpec, AnnotatedElement injectionPoint, ElementType injectionType) { Cookies cookiesAnno = getAnnotation(Cookies.class, injectionPoint, injectionType); if (cookiesAnno == null) { return; } String[] names = cookiesAnno.names(); String[] values = cookiesAnno.values(); if (names.length != values.length) { throw new IllegalArgumentException( "'names' and 'values' must have equal number of elements in @Cookies annotation."); } for (int i = 0; i < names.length; i++) { wcSpec.addCookie(names[i], values[i]); } } /** * Make sure that only one of the InitialRequest annotations was used. * * @throws IllegalArgumentException if more than one is null. */ private void validateOneNonNullInitialRequest(ElementType injectionType, Annotation... initRequests) { boolean found = false; for (Annotation anno : initRequests) { if ((anno != null) && found) { if (injectionType == ElementType.METHOD) { throw new IllegalArgumentException( "Only one of @BasicAuthentication, @FormAuthentication, or @InitialRequest is allowed per method."); } if (injectionType == ElementType.FIELD) { throw new IllegalArgumentException( "Only one of @BasicAuthentication, @FormAuthentication, or @InitialRequest is allowed at the class level."); } } if (anno != null) { found = true; } } } private ElementType getElementType(AnnotatedElement injectionPoint) { if (injectionPoint instanceof Method) { return ElementType.METHOD; } if (injectionPoint instanceof Field) { return ElementType.FIELD; } // should not really be possible unless the JSFUnitResource changes throw new IllegalArgumentException( "JSFUnit artifacts are only injectable at method parameters or field. Found InjectionPoint Member " + injectionPoint); } private <T extends Annotation> T getAnnotation(Class<T> annoClass, AnnotatedElement injectionPoint, ElementType injectionType) { if (injectionType == ElementType.METHOD) { return injectionPoint.getAnnotation(annoClass); } if (injectionType == ElementType.FIELD) { Class<?> clazz = ((Field)injectionPoint).getDeclaringClass(); return clazz.getAnnotation(annoClass); } return null; } private static <T> T newInstance(Class<T> clazz) { try { return clazz.newInstance(); } catch (InstantiationException e) { throw new IllegalArgumentException(e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } }