1 /**
2 * Copyright 2005-2011 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.remote;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.cxf.endpoint.Client;
21 import org.apache.cxf.frontend.ClientProxy;
22 import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
23 import org.kuali.rice.ksb.impl.cxf.interceptors.ImmutableCollectionsInInterceptor;
24
25 import javax.jws.WebService;
26 import javax.xml.ws.Endpoint;
27
28 /**
29 * Harness used to hold a reference to an endpoint that is published to support remote tests. Tests using
30 * this harness should pass in a @WebService annotated interface class and an object of an implementing class
31 * of that interface to the publishEndpointAndReturnProxy method in @Before or setUp methods used in tests.
32 * <p/>
33 * The endpoint will always be published at a URL like http://localhost:1025/service where the port number changes
34 * each time publishEndpointAndReturnProxy is called and guarantees that an open port is used.
35 * <p/
36 * After each test is run, stopEndPoint should be called in @After or tearDown methods in order to unpublish the
37 * endpoint.
38 * <p/>
39 *
40 */
41 public class RemoteTestHarness {
42
43 private static final Log LOG = LogFactory.getLog(RemoteTestHarness.class);
44
45 private static String ENDPOINT_ROOT = "http://localhost"; //Default URL
46 private static String ENDPOINT_PATH = "/service";
47
48 private Endpoint endpoint;
49
50 @SuppressWarnings("unchecked")
51 /**
52 * Creates a published endpoint from the passed in serviceImplementation and also returns a proxy implementation
53 * of the passed in interface for clients to use to hit the created endpoint.
54 */
55 public <T> T publishEndpointAndReturnProxy(Class<T> jaxWsAnnotatedInterface, T serviceImplementation) {
56 if (jaxWsAnnotatedInterface.isInterface() &&
57 jaxWsAnnotatedInterface.getAnnotation(WebService.class) != null &&
58 jaxWsAnnotatedInterface.isInstance(serviceImplementation)) {
59
60 String endpointUrl = getAvailableEndpointUrl();
61 LOG.info("Publishing service to: " + endpointUrl);
62 endpoint = Endpoint.publish(endpointUrl, serviceImplementation);
63
64 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
65 factory.setServiceClass(jaxWsAnnotatedInterface);
66 factory.setAddress(endpointUrl);
67
68 T serviceProxy = (T) factory.create();
69
70 /* Add the ImmutableCollectionsInInterceptor to mimic interceptors added in the KSB */
71 Client cxfClient = ClientProxy.getClient(serviceProxy);
72 cxfClient.getInInterceptors().add(new ImmutableCollectionsInInterceptor());
73
74 return serviceProxy;
75 } else {
76 throw new IllegalArgumentException("Passed in interface class type must be annotated with @WebService " +
77 "and object reference must be an implementing class of that interface.");
78
79 }
80 }
81
82 /**
83 * Stops and makes an internal endpoint unpublished if it was previously published.
84 * Otherwise, this method is a no-op.
85 */
86 public void stopEndpoint() {
87 if (endpoint != null) {
88 endpoint.stop();
89 }
90 }
91
92 private String getAvailableEndpointUrl() {
93 String port = Integer.toString(AvailablePortFinder.getNextAvailable());
94 return ENDPOINT_ROOT + ":" + port + ENDPOINT_PATH;
95 }
96 }