Coverage Report - org.kuali.rice.ksb.messaging.serviceexporters.ServiceExportManagerImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ServiceExportManagerImpl
0%
0/25
0%
0/4
1.625
ServiceExportManagerImpl$ExportedServiceHolder
0%
0/6
N/A
1.625
ServiceExportManagerImpl$ServiceNameFinder
0%
0/29
0%
0/12
1.625
 
 1  
 package org.kuali.rice.ksb.messaging.serviceexporters;
 2  
 
 3  
 import java.net.URI;
 4  
 import java.net.URL;
 5  
 import java.util.concurrent.ConcurrentHashMap;
 6  
 import java.util.concurrent.ConcurrentMap;
 7  
 
 8  
 import javax.xml.namespace.QName;
 9  
 
 10  
 import org.apache.commons.lang.StringUtils;
 11  
 import org.apache.cxf.Bus;
 12  
 import org.apache.cxf.endpoint.ServerRegistry;
 13  
 import org.kuali.rice.core.api.config.property.Config;
 14  
 import org.kuali.rice.core.api.config.property.ConfigContext;
 15  
 import org.kuali.rice.ksb.api.bus.ServiceDefinition;
 16  
 
 17  
 public class ServiceExportManagerImpl implements ServiceExportManager {
 18  
 
 19  
         private final ConcurrentMap<QName, ExportedServiceHolder> exportedServices;
 20  
         private final ServiceNameFinder serviceNameFinder;
 21  
         
 22  
         private Bus cxfBus;
 23  
         private ServerRegistry cxfServerRegistry;
 24  
         
 25  0
         public ServiceExportManagerImpl() {
 26  0
                 this.exportedServices = new ConcurrentHashMap<QName, ExportedServiceHolder>();
 27  0
                 this.serviceNameFinder = new ServiceNameFinder();
 28  0
         }
 29  
         
 30  
         @Override
 31  
         public QName getServiceName(String endpointUrl) {
 32  0
                 return getServiceNameFinder().lookup(endpointUrl);
 33  
         }
 34  
         
 35  
         protected ServiceNameFinder getServiceNameFinder() {
 36  0
                 return serviceNameFinder;
 37  
         }
 38  
         
 39  
         @Override
 40  
         public Object getService(QName serviceName) {
 41  0
                 ExportedServiceHolder holder = exportedServices.get(serviceName);
 42  0
                 if (holder == null) {
 43  0
                         return null;
 44  
                 }
 45  0
                 return holder.getExportedService();
 46  
         }
 47  
         
 48  
         @Override
 49  
         public void exportService(ServiceDefinition serviceDefinition) {
 50  0
                 if (serviceDefinition == null) {
 51  0
                         throw new IllegalArgumentException("serviceDefinition was null");
 52  
                 }
 53  0
                 ServiceExporter serviceExporter = ServiceExporterFactory.getServiceExporter(serviceDefinition, cxfBus, cxfServerRegistry);
 54  0
                 Object exportedService = serviceExporter.exportService(serviceDefinition);
 55  0
                 exportedServices.put(serviceDefinition.getServiceName(), new ExportedServiceHolder(exportedService, serviceDefinition));
 56  0
                 getServiceNameFinder().register(serviceDefinition);
 57  0
         }
 58  
 
 59  
         @Override
 60  
         public void removeService(QName serviceName) {
 61  0
                 ExportedServiceHolder exportedServiceHolder = exportedServices.remove(serviceName);
 62  0
                 getServiceNameFinder().remove(exportedServiceHolder.getServiceDefinition().getEndpointUrl());
 63  0
         }
 64  
                 
 65  
         protected ConcurrentMap<QName, ExportedServiceHolder> getExportedServices() {
 66  0
                 return exportedServices;
 67  
         }
 68  
         
 69  
         public void setCxfBus(Bus cxfBus) {
 70  0
                 this.cxfBus = cxfBus;
 71  0
         }
 72  
         
 73  
         public void setCxfServerRegistry(ServerRegistry cxfServerRegistry) {
 74  0
                 this.cxfServerRegistry = cxfServerRegistry;
 75  0
         }
 76  
         
 77  
         protected static class ExportedServiceHolder {
 78  
                 
 79  
                 private final Object exportedService;
 80  
                 private final ServiceDefinition serviceDefinition;
 81  
                 
 82  0
                 ExportedServiceHolder(Object exportedService, ServiceDefinition serviceDefinition) {
 83  0
                         this.exportedService = exportedService;
 84  0
                         this.serviceDefinition = serviceDefinition;
 85  0
                 }
 86  
                 
 87  
                 public Object getExportedService() {
 88  0
                         return exportedService;
 89  
                 }
 90  
                 
 91  
                 public ServiceDefinition getServiceDefinition() {
 92  0
                         return serviceDefinition;
 93  
                 }
 94  
                 
 95  
         }
 96  
         
 97  
         /**
 98  
          * Looks up service QNameS based on URL StringS.  API is Map-like, but non-service specific portions of the
 99  
          * URL are trimmed prior to accessing its internal Map.
 100  
          * 
 101  
          * @author Kuali Rice Team (rice.collab@kuali.org)
 102  
          *
 103  
          */
 104  0
         protected static class ServiceNameFinder {
 105  
             
 106  
                 /**
 107  
                  * A service path to service QName map
 108  
                  */
 109  0
                 private ConcurrentMap<String, QName> servicePathToQName = new ConcurrentHashMap<String, QName>();
 110  
                 
 111  
 
 112  
                 /**
 113  
                  * This method trims the endpoint url base ({@link Config#getEndPointUrl()}) base off of the full service URL, e.g.
 114  
                  * "http://kuali.edu/kr-dev/remoting/SomeService" -> "SomeService".  It makes an effort to do so even if the host
 115  
                  * and ip don't match what is in {@link Config#getEndPointUrl()} by stripping host/port info.
 116  
                  * 
 117  
                  * If the service URL contains the configured subpath for RESTful service, additional trimming is done to
 118  
                  * isolate the service name from the rest of the url.
 119  
                  * 
 120  
                  * @param url
 121  
                  * @return the service specific suffix.  If fullServiceUrl doesn't contain the endpoint url base,
 122  
                  * fullServiceUrl is returned unmodified.  
 123  
                  */
 124  
                 private String trimServiceUrlBase(String url) {
 125  0
                         String trimmedUrl = StringUtils.removeStart(url, ConfigContext.getCurrentContextConfig().getEndPointUrl());
 126  
                         
 127  0
                         if (trimmedUrl.length() == url.length()) { // it didn't contain the endpoint url base.
 128  
                                 // Perhaps the incoming url has a different host (or the ip) or a different port.
 129  
                                 // Trim off the host & port, then trim off the common base.
 130  0
                                 URI serviceUri = URI.create(url);
 131  0
                                 URI endpointUrlBase = URI.create(ConfigContext.getCurrentContextConfig().getEndPointUrl());
 132  
                                 
 133  0
                                 String reqPath = serviceUri.getPath();
 134  0
                                 String basePath = endpointUrlBase.getPath();
 135  
                                 
 136  0
                                 trimmedUrl = StringUtils.removeStart(reqPath, basePath);
 137  
                         }
 138  
                         
 139  0
                         return trimmedUrl;
 140  
                 }
 141  
                 
 142  
                 /**
 143  
                  * adds a mapping from the service specific portion of the service URL to the service name.
 144  
                  * 
 145  
                  * @param serviceUrl
 146  
                  * @param serviceName
 147  
                  */
 148  
                 public void register(ServiceDefinition serviceDefinition) {
 149  0
                         String serviceUrlBase = trimServiceUrlBase(serviceDefinition.getEndpointUrl().toExternalForm());
 150  0
                         if (serviceUrlBase.endsWith("/")) {
 151  0
                                 serviceUrlBase = StringUtils.chop(serviceUrlBase);
 152  
                         }
 153  0
                         servicePathToQName.put(serviceUrlBase, serviceDefinition.getServiceName());
 154  0
                 }
 155  
                 
 156  
                 /**
 157  
                  * removes the mapping (if one exists) for the service specific portion of this url.
 158  
                  * 
 159  
                  * @param serviceUrl
 160  
                  */
 161  
                 public void remove(URL endpointUrl) {
 162  0
                         servicePathToQName.remove(trimServiceUrlBase(endpointUrl.toExternalForm()));
 163  0
                 }
 164  
                 
 165  
                 /**
 166  
                  * gets the QName for the service
 167  
                  * 
 168  
                  * @param serviceUrl
 169  
                  * @return
 170  
                  */
 171  
                 public QName lookup(String serviceUrl) {
 172  0
                         String serviceUrlBase = trimServiceUrlBase(serviceUrl);
 173  
 
 174  
                         // First, make sure we don't have any query params
 175  0
                         if (serviceUrlBase.length() > 0 && serviceUrlBase.lastIndexOf('?') != -1) {
 176  0
                                 serviceUrlBase = serviceUrlBase.substring(0, serviceUrlBase.lastIndexOf('?'));
 177  
                         }
 178  
 
 179  0
                         QName qname = null;
 180  
                         // Now, iterate backwards through the url, stripping off pieces until you match -- this should work for rest too
 181  0
                         while (qname == null) {
 182  0
                                 qname = servicePathToQName.get(serviceUrlBase);
 183  
 
 184  0
                                 int lastSeparatorIndex = serviceUrlBase.lastIndexOf('/');
 185  0
                                 if (lastSeparatorIndex == -1)
 186  0
                                         break;
 187  0
                                 serviceUrlBase = serviceUrlBase.substring(0, lastSeparatorIndex);
 188  0
                         }
 189  
 
 190  0
                         return qname;
 191  
                 }
 192  
 
 193  
         }
 194  
 
 195  
 }