View Javadoc

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