View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.common.test.spring;
17  
18  import java.lang.reflect.Field;
19  import java.util.EventListener;
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import javax.jws.WebService;
24  import javax.servlet.Servlet;
25  import javax.xml.namespace.QName;
26  
27  import org.junit.internal.runners.InitializationError;
28  import org.junit.internal.runners.JUnit4ClassRunner;
29  import org.junit.runner.notification.RunNotifier;
30  import org.kuali.student.common.ws.beans.JaxWsClientFactory;
31  import org.mortbay.jetty.Server;
32  import org.mortbay.jetty.servlet.Context;
33  import org.mortbay.jetty.servlet.ServletHandler;
34  import org.mortbay.jetty.servlet.ServletHolder;
35  import org.mortbay.jetty.servlet.ServletMapping;
36  import org.springframework.web.context.ContextLoaderListener;
37  
38  public class ServiceTestClassRunner extends JUnit4ClassRunner {
39  	private final Class<?> testImplClass;
40  	private Server server;
41  
42  	public ServiceTestClassRunner(Class<?> klass) throws InitializationError {
43  		super(klass);
44  		testImplClass = klass;
45  
46  	}
47  
48  	/**
49  	 * Creates a client and injects it into the test class based on the
50  	 * &#064;Client annotations
51  	 */
52  	/*
53  	 * (non-Javadoc)
54  	 * 
55  	 * @see org.junit.internal.runners.JUnit4ClassRunner#createTest()
56  	 */
57  	@Override
58  	protected Object createTest() throws Exception {
59  		Object instance = super.createTest();
60  		try {
61  			for (Field f : instance.getClass().getDeclaredFields()) {
62  				if (f.isAnnotationPresent(Client.class)) {
63  					Client a = f.getAnnotation(Client.class);
64  					String port = System.getProperty("ks.test.port");
65  					
66  					Class<?> serviceImplClass = Class.forName(a.value());
67  					String serviceName = "";
68  					String serviceNamespaceURI = "";
69  					String serviceWsdlLocation = "http://localhost:" + port
70  							+ "/Service/Service" + (a.secure() ? "Secure" : "")
71  							+ "?wsdl";
72  					String serviceAddress = "http://localhost:" + port
73  							+ "/Service/Service" + (a.secure() ? "Secure" : "");
74  
75  					if (serviceImplClass.isAnnotationPresent(WebService.class)) {
76  						WebService wsAnnotation = serviceImplClass
77  								.getAnnotation(WebService.class);
78  						serviceName = wsAnnotation.serviceName();
79  						serviceNamespaceURI = wsAnnotation.targetNamespace();
80  					}
81  
82  					Class<?> clientImplClass = Class
83  							.forName("org.kuali.student.common.ws.beans.JaxWsClientFactoryBean");
84  
85  					if (a.secure()) {
86  						try {
87  							clientImplClass = Class
88  									.forName("org.kuali.student.common.cxf.security.SecureJaxWsProxyFactoryBean");
89  						} catch (ClassNotFoundException cnfe) {
90  						}
91  					}
92  
93  					JaxWsClientFactory clientFactory = (JaxWsClientFactory) clientImplClass
94  							.newInstance();
95  
96  					clientFactory.setServiceEndpointInterface(f.getType());
97  					clientFactory.setServiceName(new QName(serviceNamespaceURI,
98  							serviceName));
99  					clientFactory.setWsdlLocation(serviceWsdlLocation);
100 					clientFactory.setAddress(serviceAddress);
101 
102 					f.setAccessible(true);
103 					f.set(instance, clientFactory.getObject());
104 				}
105 			}
106 		} catch (Exception e) {
107 			throw new RuntimeException(e);
108 		}
109 		return instance;
110 	}
111 
112 	/**
113 	 * Start a server based on the service Impl &#064;WebService annotaions and
114 	 * the test class &#064;
115 	 */
116 	private void startServer() {
117 		try {
118 			// Set the default Port
119 			if (System.getProperty("ks.test.default.port")==null||System.getProperty("ks.test.default.port").isEmpty()){
120 				System.setProperty("ks.test.port", "9191");
121 			} else {
122 				System.setProperty("ks.test.port", System.getProperty("ks.test.default.port"));
123 			}
124 
125 			// Grab the client annotation and set the service implementation and
126 			// port as system properties
127 			for (Field f : testImplClass.getDeclaredFields()) {
128 				if (f.isAnnotationPresent(Client.class)) {
129 					Client a = f.getAnnotation(Client.class);
130 					if (a.secure()) {
131 						System.setProperty("ks.test.serviceImplSecure", a
132 								.value());
133 					} else {
134 						System.setProperty("ks.test.serviceImplClass", a
135 								.value());
136 					}
137 					if(a.port()!=null&&!a.port().isEmpty()){
138 						System.setProperty("ks.test.port", a.port());
139 					}
140 					if(!"".equals(a.additionalContextFile())){
141 						System.setProperty("ks.test.additionalContextFile", a.additionalContextFile());
142 					}else{
143 						System.setProperty("ks.test.additionalContextFile", "classpath:*noSuchContextFile.xml");
144 					}
145 				}
146 			}
147 
148 			// If no secure client defined, set secure service endpoint impl
149 			// to be same as non-secure endpoint impl
150 			if (System.getProperty("ks.test.serviceImplSecure") == null) {
151 				System.setProperty("ks.test.serviceImplSecure", System
152 						.getProperty("ks.test.serviceImplClass"));
153 			}
154 
155 			// Grab the persistence context loacation or set a default value
156 			if (testImplClass
157 					.isAnnotationPresent(PersistenceFileLocation.class)) {
158 				PersistenceFileLocation a = testImplClass
159 						.getAnnotation(PersistenceFileLocation.class);
160 				System.setProperty("ks.test.persistenceLocation", a.value());
161 			} else {
162 				System.setProperty("ks.test.persistenceLocation",
163 						"classpath:META-INF/persistence.xml");
164 			}
165 
166 			// Grab the Dao information and pass it to a System variable
167 			Daos daos = testImplClass.getAnnotation(Daos.class);
168 
169 			String daoImpls = "";
170 			if (daos != null) {
171 				int i = 1;
172 				for (Dao dao : daos.value()) {
173 					daoImpls += dao.value() + "|" + dao.testDataFile() +"|" + dao.testSqlFile()  ;
174 					if (i < daos.value().length) {
175 						daoImpls += ",";
176 					}
177 					i++;
178 				}
179 			}
180 			System.setProperty("ks.test.daoImplClasses", daoImpls);
181 			
182 			server = new Server(Integer.valueOf(System
183 					.getProperty("ks.test.port")));
184 
185 			Context context = new Context();
186 			ServletHandler servletHandler = new ServletHandler();
187 			ServletHolder servletHolder = new ServletHolder();
188 			ServletMapping servletMapping = new ServletMapping();
189 			ContextLoaderListener contextLoaderListener = new ContextLoaderListener();
190 
191 			
192             Class<?> servletClass;
193 			String wsEngine;
194 			try{
195 			    servletClass = Class.forName("org.apache.cxf.transport.servlet.CXFServlet");		    
196 			    wsEngine = "cxf";
197 			} catch (ClassNotFoundException e) {
198 	            servletClass = Class.forName("com.sun.xml.ws.transport.http.servlet.WSSpringServlet");
199 				wsEngine = "jaxws";
200 			}
201 
202 			Servlet servlet = (Servlet) servletClass.newInstance();
203 
204 			servletHolder.setName("Service");
205 			servletHolder.setServlet(servlet);
206 			servletHandler.setServlets(new ServletHolder[] { servletHolder });
207 
208 			servletMapping.setPathSpec("/*");
209 			servletMapping.setServletName("Service");
210 			servletHandler
211 					.setServletMappings(new ServletMapping[] { servletMapping });
212 
213 			context.setContextPath("/Service");
214 			context.setResourceBase("src/test/resources");
215 
216 			Map<String, String> initParams = new HashMap<String, String>();
217 			
218 			//Set the context config location
219 			String contextConfigLocation = "classpath:META-INF/" + wsEngine + "-context.xml";
220 			if(!"".equals(daoImpls)){
221 				//If there are Daos defined, add the dao context file
222 				contextConfigLocation +="\nclasspath:META-INF/default-dao-context-test.xml";
223 			}
224 			
225 			initParams.put("contextConfigLocation", contextConfigLocation);
226 			initParams.put("log4jConfigLocation", "log4j.properties");
227 			context.setInitParams(initParams);
228 			context
229 					.setEventListeners(new EventListener[] { contextLoaderListener });
230 			context.setServletHandler(servletHandler);
231 
232 			server.setHandler(context);
233 
234 			server.start();
235 		} catch (Exception e) {
236 			throw new RuntimeException(e);
237 		}
238 
239 	}
240 
241 	/*
242 	 * (non-Javadoc)
243 	 * 
244 	 * @see org.junit.internal.runners.JUnit4ClassRunner#run(org.junit.runner.notification.RunNotifier)
245 	 */
246 	@Override
247 	public void run(RunNotifier notifier) {
248 		startServer();
249 		super.run(notifier);
250 		stopServer();
251 	}
252 
253 	private void stopServer() {
254 		try {
255 			server.stop();
256 		} catch (Exception e) {
257 			throw new RuntimeException(e);
258 		}
259 	}
260 
261 }