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.cxf.aegis.databinding.AegisDatabinding;
019import org.apache.cxf.frontend.ClientProxyFactoryBean;
020import org.apache.cxf.interceptor.LoggingInInterceptor;
021import org.apache.cxf.interceptor.LoggingOutInterceptor;
022import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
023import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
024import org.apache.log4j.Logger;
025import org.apache.wss4j.dom.WSConstants;
026import org.apache.wss4j.dom.handler.WSHandlerConstants;
027import org.kuali.rice.core.api.exception.RiceRuntimeException;
028import org.kuali.rice.ksb.api.bus.support.SoapServiceConfiguration;
029import org.kuali.rice.ksb.impl.cxf.interceptors.ImmutableCollectionsInInterceptor;
030import org.kuali.rice.ksb.messaging.servicehandlers.BasicAuthenticationPasswordHandler;
031import org.kuali.rice.ksb.security.soap.CXFWSS4JInInterceptor;
032import org.kuali.rice.ksb.security.soap.CXFWSS4JOutInterceptor;
033import org.kuali.rice.ksb.security.soap.CredentialsOutHandler;
034import org.kuali.rice.ksb.service.BasicAuthenticationCredentials;
035import org.kuali.rice.ksb.service.KSBServiceLocator;
036
037import java.net.URL;
038import java.util.HashMap;
039import java.util.Map;
040
041/**
042 *
043 * @author Kuali Rice Team (rice.collab@kuali.org)
044 * @since 0.9
045 */
046public class SOAPConnector extends AbstractServiceConnector {
047
048    private static final Logger LOG = Logger.getLogger(SOAPConnector.class);
049
050        public SOAPConnector(final SoapServiceConfiguration serviceConfiguration, final URL alternateEndpointUrl) {
051                super(serviceConfiguration, alternateEndpointUrl);
052        }
053
054    @Override
055        public SoapServiceConfiguration getServiceConfiguration() {
056                return (SoapServiceConfiguration) super.getServiceConfiguration();
057        }
058        
059        /**
060         * This overridden method returns a CXF client praoxy for web service.
061         * 
062         * @see org.kuali.rice.ksb.messaging.serviceconnectors.ServiceConnector#getService()
063         */
064        public Object getService() {
065                ClientProxyFactoryBean clientFactory;
066                
067                //Use the correct bean factory depending on pojo service or jaxws service
068                if (getServiceConfiguration().isJaxWsService()){
069                        clientFactory = new JaxWsProxyFactoryBean();
070                } else {
071                        clientFactory = new ClientProxyFactoryBean();
072                        clientFactory.getServiceFactory().setDataBinding(new AegisDatabinding());
073                }               
074
075                try {
076                        clientFactory.setServiceClass(Class.forName(getServiceConfiguration().getServiceInterface()));
077                } catch (ClassNotFoundException e) {
078                        throw new RiceRuntimeException("Failed to connect to soap service " + getServiceConfiguration().getServiceName() + " because failed to load interface class: " + getServiceConfiguration().getServiceInterface(), e);
079                }
080                clientFactory.setBus(KSBServiceLocator.getCXFBus());
081                clientFactory.setServiceName(getServiceConfiguration().getServiceName());
082                clientFactory.setAddress(getActualEndpointUrl().toExternalForm());
083                
084                //Set logging, transformation, and security interceptors
085        clientFactory.getOutInterceptors().add(new LoggingOutInterceptor());
086        clientFactory.getOutFaultInterceptors().add(new LoggingOutInterceptor());
087        CXFWSS4JOutInterceptor outSecurityInterceptor = new CXFWSS4JOutInterceptor(getServiceConfiguration().getBusSecurity());
088        clientFactory.getOutInterceptors().add(outSecurityInterceptor);
089        clientFactory.getOutFaultInterceptors().add(outSecurityInterceptor);
090        if (getCredentialsSource() != null) {
091                        clientFactory.getOutInterceptors().add(new CredentialsOutHandler(getCredentialsSource(), getServiceConfiguration()));
092                }
093
094                /**
095                 * Check the basic authentication service for credentials when connecting to a service which requires basic
096                 * authentication.  If credentials are found in the service then this populates the WSSecurity header with
097                 * the correct information.
098                 */
099                SoapServiceConfiguration soapServiceConfiguration = this.getServiceConfiguration();
100
101                if (soapServiceConfiguration.isBasicAuthentication()) {
102                        BasicAuthenticationCredentials credentials =
103                                        KSBServiceLocator.getBasicAuthenticationService().getConnectionCredentials(
104                                                        soapServiceConfiguration.getServiceName().getNamespaceURI(),
105                                                        soapServiceConfiguration.getServiceName().getLocalPart());
106                        if (credentials != null) {
107                                Map<String, Object> outProps = new HashMap<String, Object>();
108                                outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
109                                outProps.put(WSHandlerConstants.USER, credentials.getUsername());
110                                outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
111                                outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new BasicAuthenticationPasswordHandler(
112                                                credentials.getPassword()));
113                                WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
114                                clientFactory.getOutInterceptors().add(wssOut);
115                                clientFactory.getOutFaultInterceptors().add(wssOut);
116                        }
117                }
118
119            clientFactory.getInInterceptors().add(new LoggingInInterceptor());
120        clientFactory.getInFaultInterceptors().add(new LoggingInInterceptor());
121        CXFWSS4JInInterceptor inSecurityInterceptor = new CXFWSS4JInInterceptor(getServiceConfiguration().getBusSecurity());
122        clientFactory.getInInterceptors().add(inSecurityInterceptor);
123        clientFactory.getInFaultInterceptors().add(inSecurityInterceptor);
124        clientFactory.getInInterceptors().add(new ImmutableCollectionsInInterceptor());
125
126                
127                Object service = clientFactory.create();                
128                return getServiceProxyWithFailureMode(service, getServiceConfiguration());
129        }       
130}