View Javadoc
1   /**
2    * Copyright 2005-2016 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.ksb.messaging.serviceconnectors;
17  
18  import org.apache.commons.collections.MapUtils;
19  import org.apache.cxf.binding.BindingFactoryManager;
20  import org.apache.cxf.interceptor.LoggingInInterceptor;
21  import org.apache.cxf.interceptor.LoggingOutInterceptor;
22  import org.apache.cxf.jaxrs.JAXRSBindingFactory;
23  import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
24  import org.apache.log4j.Logger;
25  import org.kuali.rice.core.api.exception.RiceRuntimeException;
26  import org.kuali.rice.core.api.security.credentials.CredentialsSource;
27  import org.kuali.rice.ksb.api.bus.support.RestServiceConfiguration;
28  import org.kuali.rice.ksb.api.messaging.ResourceFacade;
29  import org.kuali.rice.ksb.messaging.BusClientFailureProxy;
30  import org.kuali.rice.ksb.messaging.bam.BAMClientProxy;
31  import org.kuali.rice.ksb.security.soap.CredentialsOutHandler;
32  import org.kuali.rice.ksb.service.KSBServiceLocator;
33  
34  import java.net.URL;
35  import java.util.Map;
36  
37  /**
38   * implementation of {@link ResourceFacade}
39   *
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   *
42   */
43  public class ResourceFacadeImpl implements ResourceFacade {
44  
45  	private static final Logger LOG = Logger.getLogger(ResourceFacadeImpl.class);
46  
47  	private final RestServiceConfiguration serviceConfiguration;
48  	private CredentialsSource credentialsSource;
49  	private URL actualEndpointUrl;
50  
51  	public ResourceFacadeImpl(final RestServiceConfiguration serviceConfiguration, URL actualEndpointUrl) {
52  		if (serviceConfiguration == null) {
53  			throw new IllegalArgumentException("serviceConfiguration cannot be null");
54  		}
55  		if (actualEndpointUrl == null) {
56  			throw new IllegalArgumentException("actual endpoint url cannot be null");
57  		}
58  		this.serviceConfiguration = serviceConfiguration;
59  		this.actualEndpointUrl = actualEndpointUrl;
60  	}
61  	
62  	/**
63  	 * This overridden method ...
64  	 *
65  	 * @see org.kuali.rice.ksb.api.messaging.ResourceFacade#getResource(java.lang.Class)
66  	 */
67  	public <R> R getResource(Class<R> resourceClass) {
68  		if (resourceClass == null) throw new IllegalArgumentException("resourceClass argument must not be null");
69  
70  		if (!serviceConfiguration.hasClass(resourceClass.getName())) {
71  			throw new IllegalArgumentException("Service " + serviceConfiguration.getServiceName() +
72  					" does not contain an implementation of type " + resourceClass.getName());
73  		}
74  
75  		return getServiceProxy(resourceClass);
76  	}
77  
78  	/**
79  	 * This overridden method ...
80  	 *
81  	 * @see org.kuali.rice.ksb.api.messaging.ResourceFacade#getResource(java.lang.String)
82  	 */
83  	public <R> R getResource(String resourceName) {
84  
85  		String resourceClassName = null;
86  
87  		Map<String, String> resourceToClassNameMap = serviceConfiguration.getResourceToClassNameMap();
88  
89  		if (resourceName != null && resourceToClassNameMap != null)
90  			resourceClassName = resourceToClassNameMap.get(resourceName);
91  		else
92  			resourceClassName = serviceConfiguration.getResourceClass();
93  
94  		if (resourceClassName == null)
95  			throw new RiceRuntimeException("No resource class name was found for the specified resourceName: " + resourceName);
96  
97  		Class<?> resourceClass = null;
98  
99  		try {
100 			resourceClass = Class.forName(resourceClassName);
101 		} catch (ClassNotFoundException e) {
102 			throw new RiceRuntimeException("Configured resource class " + resourceClassName +
103 					" in service " + serviceConfiguration.getServiceName() + " is not loadable", e);
104 		}
105 
106 		
107 		// allow this to class cast if the types don't match, up to the caller to ensure this is correct
108 		@SuppressWarnings("unchecked")
109         R serviceProxy = (R)getServiceProxy(resourceClass);
110 		return serviceProxy;
111 	}
112 
113 	/**
114 	 * This method ...
115 	 *
116 	 * @param resourceClass
117 	 * @return
118 	 */
119 	private <R> R getServiceProxy(Class<R> resourceClass) {
120 		JAXRSClientFactoryBean clientFactory;
121 
122         clientFactory = new JAXRSClientFactoryBean();
123         clientFactory.setBus(KSBServiceLocator.getCXFBus());
124 
125         clientFactory.setResourceClass(resourceClass);
126         clientFactory.setAddress(actualEndpointUrl.toString());
127         BindingFactoryManager bindingFactoryManager = KSBServiceLocator.getCXFBus().getExtension(BindingFactoryManager.class);
128         JAXRSBindingFactory bindingFactory = new JAXRSBindingFactory();
129         bindingFactory.setBus(KSBServiceLocator.getCXFBus());
130 
131         bindingFactoryManager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, bindingFactory);
132 
133         //Set logging interceptors
134         if (LOG.isDebugEnabled()) {
135         	clientFactory.getOutInterceptors().add(new LoggingOutInterceptor());
136         }
137 
138         if (getCredentialsSource() != null) {
139             clientFactory.getOutInterceptors().add(new CredentialsOutHandler(getCredentialsSource(), serviceConfiguration));
140         }
141 
142         if (LOG.isDebugEnabled()) {
143         	clientFactory.getInInterceptors().add(new LoggingInInterceptor());
144         }
145 
146         Object service = clientFactory.create();
147         return getServiceProxyWithFailureMode(resourceClass, service, serviceConfiguration);
148 	}
149 	
150 	public boolean isSingleResourceService() {
151 		return MapUtils.isEmpty(serviceConfiguration.getResourceToClassNameMap());
152 	}
153 
154 	public void setCredentialsSource(final CredentialsSource credentialsSource) {
155 		this.credentialsSource = credentialsSource;
156 	}
157 
158 	protected CredentialsSource getCredentialsSource() {
159 		return this.credentialsSource;
160 	}
161 
162 	protected <R> R getServiceProxyWithFailureMode(final Class<R> resourceClass, final Object service, final RestServiceConfiguration serviceConfiguration) {
163 		Object bamWrappedClientProxy = BAMClientProxy.wrap(service, serviceConfiguration);
164 		Object proxy = BusClientFailureProxy.wrap(bamWrappedClientProxy, serviceConfiguration);
165 		if (!resourceClass.isInstance(proxy)) {
166 			throw new IllegalArgumentException("Wrapped proxy is of the wrong type " + proxy.getClass() + ", expected " + resourceClass);
167 		}
168 		return resourceClass.cast(proxy);
169 	}
170 
171 }