View Javadoc
1   /**
2    * Copyright 2004-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.test.lifecycles;
17  
18  import java.net.BindException;
19  import java.util.HashMap;
20  
21  import org.apache.log4j.Logger;
22  import org.kuali.rice.core.api.config.property.Config;
23  import org.kuali.rice.core.api.config.property.ConfigContext;
24  import org.kuali.rice.core.api.lifecycle.Lifecycle;
25  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
26  import org.kuali.rice.core.api.resourceloader.ResourceLoader;
27  import org.kuali.rice.core.api.util.RiceUtilities;
28  import org.kuali.rice.test.launch.JettyLauncher;
29  
30  
31  /**
32   * A lifecycle for running a jetty web server.
33   * @author Kuali Rice Team (rice.collab@kuali.org)
34   */
35  public class JettyServerLifecycle implements Lifecycle {
36      private static final Logger LOG = Logger.getLogger(JettyServerLifecycle.class);
37  
38      private static final HashMap<Integer, Config> WEBAPP_CONFIGS = new HashMap<Integer, Config>();
39  
40      public static Config getWebappConfig(int port) {
41          return WEBAPP_CONFIGS.get(port);
42      }
43  
44      /**
45       * Enum for dealing with the webapp's Config
46       */
47      public static enum ConfigMode {
48          /**
49           * Do nothing
50           */
51          NONE,
52          /**
53           * Override the Config for the context class loader
54           */
55          OVERRIDE,
56          /**
57           * Merge the webapp's Config into the existing context class loader config
58           */
59          MERGE
60      }
61  
62      /**
63       * By default we set the JettyServer to test mode
64       */
65      private boolean testMode = true;
66      private boolean started;
67      private ConfigMode configMode = ConfigMode.OVERRIDE;
68      private boolean addWebappResourceLoaders = true;
69  
70  
71  	protected JettyLauncher jettyServer;
72  
73  	public JettyServerLifecycle() {
74  		this(8080, null);
75  	}
76  
77  	public JettyServerLifecycle(int port) {
78  		this(port, null, null);
79  	}
80  
81  	public JettyServerLifecycle(int port, String contextName) {
82  		this(port, contextName, null);
83  	}
84  
85  	public JettyServerLifecycle(int port, String contextName, String relativeWebappRoot) {
86  		jettyServer = new JettyLauncher(port, contextName, relativeWebappRoot);
87          jettyServer.setFailOnContextFailure(true);
88  		jettyServer.setTestMode(testMode);
89  	}
90  
91      public void setTestMode(boolean t) {
92          this.testMode = t;
93      }
94  
95      public boolean isTestMode() {
96          return testMode;
97      }
98  
99      public ConfigMode getConfigMode() {
100         return this.configMode;
101     }
102 
103     public void setConfigMode(ConfigMode configMode) {
104         this.configMode = configMode;
105     }
106 
107     public boolean isAddWebappResourceLoaders() {
108         return this.addWebappResourceLoaders;
109     }
110 
111     public void setAddWebappResourceLoaders(boolean addWebappResourceLoaders) {
112         this.addWebappResourceLoaders = addWebappResourceLoaders;
113     }
114 
115 	public boolean isStarted() {
116 		return started;
117 	}
118 
119 	public void start() throws Exception {
120 	    try {
121 	        jettyServer.start();
122 
123 	    } catch (RuntimeException re) {
124 	        // add some handling to make port conflicts more easily identified
125 	        if (RiceUtilities.findExceptionInStack(re, BindException.class) != null) {
126 	            LOG.error("JettyServerLifecycle encountered BindException on port: " + jettyServer.getPort() + "; check logs for test junit.framework.Assert.failures or and the config for duplicate port specifications.");
127 	        }
128 	        throw re;
129 	    }
130 
131 	    ClassLoader webappClassLoader = jettyServer.getContext().getClassLoader();
132 	    if (addWebappResourceLoaders) {
133 	        ResourceLoader rl = GlobalResourceLoader.getResourceLoader(webappClassLoader);
134             if (rl == null) {
135                 throw new RuntimeException("Could not find resource loader for workflow test harness web app for: " + webappClassLoader);
136             }
137             //GlobalResourceLoader.addResourceLoaderFirst();
138             GlobalResourceLoader.addResourceLoader(rl);
139 	    }
140 	    //org.kuali.rice.core.api.config.property.Config webappConfig = ConfigContext.getCurrentContextConfig();
141         org.kuali.rice.core.api.config.property.Config webappConfig = ConfigContext.getConfig(webappClassLoader);
142 	    WEBAPP_CONFIGS.put(new Integer(jettyServer.getPort()), webappConfig);
143 	    if (ConfigMode.OVERRIDE == configMode) {
144             // this overrides the test harness classloader config with the webapp's config...
145 
146 
147             ConfigContext.overrideConfig(Thread.currentThread().getContextClassLoader(), webappConfig);
148         } else if (ConfigMode.MERGE == configMode) {
149             Config curCtxConfig = ConfigContext.getCurrentContextConfig();
150             if (webappConfig != null) {
151                 curCtxConfig.putProperties(webappConfig.getProperties());
152                 curCtxConfig.putObjects(webappConfig.getObjects());
153             }
154         }
155 
156 		started = true;
157 	}
158 
159 	public void stop() throws Exception {
160 	    LOG.info("Shutting down jetty: " + jettyServer);
161 	    try {
162 	    	if (jettyServer != null && jettyServer.isStarted()) {
163 	    		jettyServer.stop();
164 	    		WEBAPP_CONFIGS.remove(jettyServer.getPort());
165 	    	}
166 	    } catch (Exception e) {
167 	        LOG.error("Error shutting down Jetty " + jettyServer.getContextName(), e);
168 	    }
169 		started = false;
170 	}
171 }