View Javadoc
1   /**
2    * Copyright 2005-2013 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  }