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 }