001/** 002 * Copyright 2005-2017 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.ksb.messaging.serviceconnectors; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.log4j.Logger; 020import org.kuali.rice.core.api.config.property.Config; 021import org.kuali.rice.core.api.config.property.ConfigContext; 022import org.kuali.rice.core.api.exception.RiceRuntimeException; 023import org.kuali.rice.core.api.security.credentials.CredentialsSource; 024import org.kuali.rice.core.api.security.credentials.CredentialsSourceFactory; 025import org.kuali.rice.ksb.api.bus.ServiceConfiguration; 026import org.kuali.rice.ksb.api.bus.ServiceDefinition; 027import org.kuali.rice.ksb.api.bus.support.JavaServiceConfiguration; 028import org.kuali.rice.ksb.api.bus.support.RestServiceConfiguration; 029import org.kuali.rice.ksb.api.bus.support.SoapServiceConfiguration; 030import org.kuali.rice.ksb.messaging.AlternateEndpoint; 031import org.kuali.rice.ksb.messaging.AlternateEndpointLocation; 032import org.kuali.rice.ksb.util.KSBConstants; 033 034import java.net.MalformedURLException; 035import java.net.URL; 036import java.util.List; 037import java.util.regex.Matcher; 038import java.util.regex.Pattern; 039 040/** 041 * Constructs a ServiceConnector based on the provided 042 * ServiceInfo/ServiceDefinition. Connects that ServiceConnector to the 043 * appropriate CredentialsSource. 044 * <p> 045 * ServiceConnector will fail if a CredentialsSource for the Service Definition 046 * cannot be located. 047 * 048 * @author Kuali Rice Team (rice.collab@kuali.org) 049 * 050 * @since 0.9 051 * @see ServiceConnector 052 * @see ServiceDefinition 053 * @see CredentialsSource 054 */ 055public class ServiceConnectorFactory { 056 057 private static final Logger LOG = Logger.getLogger(ServiceConnectorFactory.class); 058 059 public static ServiceConnector getServiceConnector( 060 final ServiceConfiguration serviceConfiguration) { 061 final CredentialsSourceFactory credentialsSourceFactory = (CredentialsSourceFactory) ConfigContext 062 .getCurrentContextConfig().getObjects() 063 .get(Config.CREDENTIALS_SOURCE_FACTORY); 064 final CredentialsSource credentialsSource = credentialsSourceFactory != null ? credentialsSourceFactory 065 .getCredentialsForType(serviceConfiguration.getCredentialsType()) : null; 066 ServiceConnector serviceConnector = null; 067 068 if (serviceConfiguration.getCredentialsType() != null && credentialsSource == null) { 069 throw new RiceRuntimeException("Service requires credentials but no factory or CredentialsSource could be located."); 070 } 071 072 String alternateEndpoint = determineAlternateEndpoint(serviceConfiguration); 073 URL alternateEndpointUrl = null; 074 if (!StringUtils.isBlank(alternateEndpoint)) { 075 try { 076 alternateEndpointUrl = new URL(alternateEndpoint); 077 } catch (MalformedURLException e) { 078 throw new IllegalStateException("Encountered invalid alternate endpoint url: " + alternateEndpoint, e); 079 } 080 } 081 082 // TODO switch this to use serviceConfiguration.getType() at some point in the future and allow for 083 // this to be easily "pluggable" with new connector types 084 // 085 // if set in local mode then preempt any protocol connectors 086 if (ConfigContext.getCurrentContextConfig().getDevMode()) { 087 serviceConnector = new BusLocalConnector(serviceConfiguration); 088 } else if (serviceConfiguration instanceof JavaServiceConfiguration) { 089 serviceConnector = new HttpInvokerConnector((JavaServiceConfiguration) serviceConfiguration, alternateEndpointUrl); 090 } else if (serviceConfiguration instanceof SoapServiceConfiguration) { 091 serviceConnector = new SOAPConnector((SoapServiceConfiguration) serviceConfiguration, alternateEndpointUrl); 092 } else if (serviceConfiguration instanceof RestServiceConfiguration) { 093 serviceConnector = new RESTConnector((RestServiceConfiguration) serviceConfiguration, alternateEndpointUrl); 094 } 095 096 if (serviceConnector == null) { 097 throw new RiceRuntimeException("Don't support service type of " + serviceConfiguration); 098 } 099 serviceConnector.setCredentialsSource(credentialsSource); 100 101 return serviceConnector; 102 } 103 104 public static String determineAlternateEndpoint(ServiceConfiguration serviceConfiguration) { 105 String alternateEndpointUrl = null; 106 List<AlternateEndpointLocation> alternateEndpointLocations = (List<AlternateEndpointLocation>) ConfigContext.getCurrentContextConfig().getObject(KSBConstants.Config.KSB_ALTERNATE_ENDPOINT_LOCATIONS); 107 if (alternateEndpointLocations != null) { 108 for (AlternateEndpointLocation alternateEndpointLocation : alternateEndpointLocations) { 109 if (Pattern.matches(".*" + alternateEndpointLocation.getEndpointHostReplacementPattern() + ".*", serviceConfiguration.getEndpointUrl().toExternalForm())) { 110 Pattern myPattern = Pattern.compile(alternateEndpointLocation.getEndpointHostReplacementPattern()); 111 Matcher myMatcher = myPattern.matcher(serviceConfiguration.getEndpointUrl().toExternalForm()); 112 String alternateEndpoint = myMatcher.replaceFirst(alternateEndpointLocation.getEndpointHostReplacementValue()); 113 if ( LOG.isInfoEnabled() ) { 114 LOG.info("Found an alternate url host value (" 115 + alternateEndpointLocation.getEndpointHostReplacementValue() + ") for endpoint: " 116 + serviceConfiguration.getEndpointUrl() + " -> instead using: " + alternateEndpoint); 117 } 118 alternateEndpointUrl = alternateEndpoint; 119 break; 120 } 121 } 122 } 123 List<AlternateEndpoint> alternateEndpoints = (List<AlternateEndpoint>) ConfigContext.getCurrentContextConfig().getObject(KSBConstants.Config.KSB_ALTERNATE_ENDPOINTS); 124 if (alternateEndpoints != null) { 125 for (AlternateEndpoint alternateEndpoint : alternateEndpoints) { 126 if (Pattern.matches(alternateEndpoint.getEndpointUrlPattern(), serviceConfiguration.getEndpointUrl().toExternalForm())) { 127 if ( LOG.isInfoEnabled() ) { 128 LOG.info("Found an alternate url for endpoint: " + serviceConfiguration.getEndpointUrl() + " -> instead using: " + alternateEndpoint.getActualEndpoint()); 129 } 130 alternateEndpointUrl = alternateEndpoint.getActualEndpoint(); 131 break; 132 } 133 } 134 } 135 return alternateEndpointUrl; 136 } 137 138}