001 /* 002 * Copyright 2007-2008 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.test; 017 018 import java.lang.reflect.Method; 019 import java.util.ArrayList; 020 import java.util.Arrays; 021 import java.util.HashSet; 022 import java.util.List; 023 import java.util.Set; 024 025 import org.apache.commons.lang.StringUtils; 026 import org.kuali.rice.core.api.config.property.ConfigContext; 027 import org.kuali.rice.core.api.lifecycle.Lifecycle; 028 import org.kuali.rice.test.lifecycles.JettyServerLifecycle; 029 import org.kuali.rice.test.server.JettyServer; 030 import org.kuali.rice.test.server.JettyServers; 031 032 /** 033 * A test case that supports declaratively defining a JettServer to run via annotations. 034 * Although this class supports running JettyServers on a per-suite and per-test basis, there is a 035 * pragmatic issue of concurrently running webapp contexts in the same classloader, so the webapp 036 * will have to support this (e.g. not rely on static singletons...) 037 * Another issue is that there is no suite "shutdown" per se, so a Jetty started up in a suite 038 * lifecycle will never get explicitly shut down. 039 * @author Kuali Rice Team (rice.collab@kuali.org) 040 */ 041 public abstract class JettyServerTestCase extends BaselineTestCase { 042 private static Set<String> classesHandled = new HashSet<String>(); 043 044 /** 045 * @see {@link BaselineTestCase#BaselineTestCase(String, Mode) 046 */ 047 public JettyServerTestCase(String moduleName, Mode mode) { 048 super(moduleName, mode); 049 } 050 051 /** 052 * @see {@link BaselineTestCase#BaselineTestCase(String) 053 */ 054 public JettyServerTestCase(String moduleName) { 055 super(moduleName); 056 } 057 058 private List<JettyServer> readPerTestDefinitions(Method method) { 059 return getJettyServerDefinitions((JettyServers) method.getAnnotation(JettyServers.class), (JettyServer) method.getAnnotation(JettyServer.class)); 060 } 061 062 private List<JettyServer> readSuiteServerDefinitions(Class clazz) { 063 return getJettyServerDefinitions((JettyServers) clazz.getAnnotation(JettyServers.class), (JettyServer) clazz.getAnnotation(JettyServer.class)); 064 } 065 066 private List<JettyServer> getJettyServerDefinitions(JettyServers servers, JettyServer server) { 067 List<JettyServer> defs = new ArrayList<JettyServer>(); 068 if (servers != null) { 069 if (servers.servers() != null) { 070 defs.addAll(Arrays.asList(servers.servers())); 071 } 072 } 073 if (server != null) { 074 defs.add(server); 075 } 076 return defs; 077 } 078 079 protected JettyServerLifecycle constructJettyServerLifecycle(JettyServer def) { 080 String portConfigParam = def.portConfigParam(); 081 if (StringUtils.isBlank(portConfigParam)) { 082 portConfigParam = null; 083 } 084 if (def.port() != JettyServer.CONFIG_PARAM_PORT && portConfigParam != null) { 085 throw new IllegalArgumentException("Either but not both of port or portConfigParam must be specified on JettyServer annotation"); 086 } 087 if (def.port() == JettyServer.CONFIG_PARAM_PORT && portConfigParam == null) { 088 portConfigParam = "unittest.jetty." + def.context() + ".port"; 089 } 090 JettyServerLifecycle lc; 091 if (def.port() != JettyServer.CONFIG_PARAM_PORT) { 092 lc = new RuntimePortJettyServerLifecycle(def.port(), "/" + def.context(), def.webapp()); 093 } else { 094 lc = new RuntimePortJettyServerLifecycle(def.portConfigParam(), "/" + def.context(), def.webapp()); 095 } 096 lc.setConfigMode(def.configMode()); 097 lc.setAddWebappResourceLoaders(def.addWebappResourceLoader()); 098 return lc; 099 } 100 101 @Override 102 protected List<Lifecycle> getSuiteLifecycles() { 103 List<Lifecycle> lifecycles = super.getSuiteLifecycles(); 104 List<Class> classesToHandle; 105 try { 106 classesToHandle = TestUtilities.getHierarchyClassesToHandle(this.getClass(), new Class[] { JettyServers.class, JettyServer.class }, classesHandled); 107 } catch (Exception e) { 108 throw new RuntimeException("Error determining classes to handle", e); 109 } 110 List<JettyServer> suiteDefs = new ArrayList<JettyServer>(); 111 for (Class c: classesToHandle) { 112 suiteDefs.addAll(readSuiteServerDefinitions(c)); 113 classesHandled.add(c.getName()); 114 } 115 // add all our jetties... 116 for (JettyServer def: suiteDefs) { 117 lifecycles.add(constructJettyServerLifecycle(def)); 118 } 119 return lifecycles; 120 } 121 122 @Override 123 protected List<Lifecycle> getPerTestLifecycles() { 124 List<Lifecycle> lifecycles = super.getPerTestLifecycles(); 125 List<JettyServer> defs = readPerTestDefinitions(method); 126 // add all our jetties... 127 for (JettyServer def: defs) { 128 lifecycles.add(constructJettyServerLifecycle(def)); 129 } 130 return lifecycles; 131 } 132 133 private static final class RuntimePortJettyServerLifecycle extends JettyServerLifecycle { 134 private String portConfigParam; 135 public RuntimePortJettyServerLifecycle(int port, String contextName, String relativeWebappRoot) { 136 super(port, contextName, relativeWebappRoot); 137 } 138 public RuntimePortJettyServerLifecycle(String portConfigParam, String contextName, String relativeWebappRoot) { 139 super(JettyServer.CONFIG_PARAM_PORT, contextName, relativeWebappRoot); 140 this.portConfigParam = portConfigParam; 141 } 142 public void start() throws Exception { 143 if (jettyServer.getPort() == JettyServer.CONFIG_PARAM_PORT) { 144 String val = ConfigContext.getCurrentContextConfig().getProperty(portConfigParam); 145 if (val == null) { 146 throw new RuntimeException("Jetty port not found in config param: " + portConfigParam); 147 } 148 jettyServer.setPort(Integer.parseInt(val)); 149 } 150 super.start(); 151 } 152 @Override 153 public void stop() throws Exception { 154 System.err.println("Shutting down jetty"); 155 super.stop(); 156 } 157 } 158 }