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