001/**
002 * Copyright 2005-2015 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.impl.bus;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.cxf.Bus;
020import org.apache.cxf.frontend.ClientProxyFactoryBean;
021import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
022import org.kuali.rice.core.api.config.property.ConfigContext;
023import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
024import org.kuali.rice.core.api.exception.RiceRuntimeException;
025import org.kuali.rice.ksb.api.registry.RemoveAndPublishResult;
026import org.kuali.rice.ksb.api.registry.ServiceDescriptor;
027import org.kuali.rice.ksb.api.registry.ServiceEndpoint;
028import org.kuali.rice.ksb.api.registry.ServiceEndpointStatus;
029import org.kuali.rice.ksb.api.registry.ServiceInfo;
030import org.kuali.rice.ksb.api.registry.ServiceRegistry;
031import org.kuali.rice.ksb.impl.cxf.interceptors.ImmutableCollectionsInInterceptor;
032import org.kuali.rice.ksb.security.soap.CXFWSS4JInInterceptor;
033import org.kuali.rice.ksb.security.soap.CXFWSS4JOutInterceptor;
034import org.kuali.rice.ksb.util.KSBConstants;
035
036import javax.xml.namespace.QName;
037import java.util.List;
038
039/**
040 * TODO... 
041 * 
042 * @author Kuali Rice Team (rice.collab@kuali.org)
043 *
044 */
045public class LazyRemoteServiceRegistryConnector implements ServiceRegistry {
046
047    private static final String SERVICE_REGISTRY_SECURITY_CONFIG = "rice.ksb.serviceRegistry.security";
048
049        private final Object initLock = new Object();
050        private volatile ServiceRegistry delegate;
051        
052        // injected
053        private Bus cxfBus;
054        
055        public void setCxfBus(Bus cxfBus) {
056                this.cxfBus = cxfBus;
057        }
058        
059        @Override
060        public List<ServiceInfo> getOnlineServicesByName(QName serviceName)
061                        throws RiceIllegalArgumentException {
062                return getDelegate().getOnlineServicesByName(serviceName);
063        }
064
065        @Override
066        public List<ServiceInfo> getAllOnlineServices() {
067                return getDelegate().getAllOnlineServices();
068        }
069
070        @Override
071        public List<ServiceInfo> getAllServices() {
072                return getDelegate().getAllServices();
073        }
074        
075        @Override
076        public List<ServiceInfo> getAllServicesForInstance(String instanceId) {
077                return getDelegate().getAllServicesForInstance(instanceId);
078        }
079
080    @Override
081    public List<ServiceInfo> getAllServicesForApplication(String applicationId) {
082        return getDelegate().getAllServicesForApplication(applicationId);
083    }
084
085        @Override
086        public ServiceDescriptor getServiceDescriptor(String serviceDescriptorId)
087                        throws RiceIllegalArgumentException {
088                return getDelegate().getServiceDescriptor(serviceDescriptorId);
089        }
090
091        @Override
092        public List<ServiceDescriptor> getServiceDescriptors(
093                        List<String> serviceDescriptorIds)
094                        throws RiceIllegalArgumentException {
095                return getDelegate().getServiceDescriptors(serviceDescriptorIds);
096        }
097
098        @Override
099        public ServiceEndpoint publishService(ServiceEndpoint serviceEndpoint)
100                        throws RiceIllegalArgumentException {
101                return getDelegate().publishService(serviceEndpoint);
102        }
103
104        @Override
105        public List<ServiceEndpoint> publishServices(List<ServiceEndpoint> serviceEndpoints)
106                        throws RiceIllegalArgumentException {
107                return getDelegate().publishServices(serviceEndpoints);
108        }
109
110        @Override
111        public ServiceEndpoint removeServiceEndpoint(String serviceId)
112                        throws RiceIllegalArgumentException {
113                return getDelegate().removeServiceEndpoint(serviceId);
114        }
115
116        @Override
117        public List<ServiceEndpoint> removeServiceEndpoints(List<String> serviceIds)
118                        throws RiceIllegalArgumentException {
119                return getDelegate().removeServiceEndpoints(serviceIds);
120        }
121
122        @Override
123        public RemoveAndPublishResult removeAndPublish(List<String> removeServiceIds,
124                        List<ServiceEndpoint> publishServiceEndpoints) {
125                return getDelegate().removeAndPublish(removeServiceIds, publishServiceEndpoints);
126        }
127
128        @Override
129        public boolean updateStatus(String serviceId, ServiceEndpointStatus status) throws RiceIllegalArgumentException {
130                return getDelegate().updateStatus(serviceId, status);
131        }
132
133        @Override
134        public List<String> updateStatuses(List<String> serviceIds, ServiceEndpointStatus status) throws RiceIllegalArgumentException {
135                return getDelegate().updateStatuses(serviceIds, status);
136        }
137
138        @Override
139        public void takeInstanceOffline(String instanceId)
140                        throws RiceIllegalArgumentException {
141        // if Service Registry has not been initialized by this point, do not shutdown
142        if (this.delegate != null) {
143                    getDelegate().takeInstanceOffline(instanceId);
144        }
145        }
146        
147        private ServiceRegistry getDelegate() {
148                // double-checked locking idiom - see Effective Java, Item 71
149                ServiceRegistry internalDelegate = this.delegate;
150                if (internalDelegate == null) {
151                        synchronized (initLock) {
152                                internalDelegate = this.delegate;
153                                if (internalDelegate == null) {
154                                        this.delegate = internalDelegate = initializeRemoteServiceRegistry();
155                                }
156                        }
157                }
158                return internalDelegate;
159        }
160        
161        protected ServiceRegistry initializeRemoteServiceRegistry() {
162                String registryBootstrapUrl = ConfigContext.getCurrentContextConfig().getProperty(KSBConstants.Config.REGISTRY_SERVICE_URL);
163                if (StringUtils.isBlank(registryBootstrapUrl)) {
164                        throw new RiceRuntimeException("Failed to load registry bootstrap service from url: " + registryBootstrapUrl);
165                }
166                ClientProxyFactoryBean clientFactory = new JaxWsProxyFactoryBean();
167                clientFactory.setServiceClass(ServiceRegistry.class);
168                clientFactory.setBus(cxfBus);
169                clientFactory.setAddress(registryBootstrapUrl);
170
171        boolean registrySecurity = ConfigContext.getCurrentContextConfig().getBooleanProperty(SERVICE_REGISTRY_SECURITY_CONFIG, true);
172
173                // Set security interceptors
174                clientFactory.getOutInterceptors().add(new CXFWSS4JOutInterceptor(registrySecurity));
175                clientFactory.getInInterceptors().add(new CXFWSS4JInInterceptor(registrySecurity));
176
177        //Set transformation interceptors
178        clientFactory.getInInterceptors().add(new ImmutableCollectionsInInterceptor());
179                
180                Object service = clientFactory.create();
181                if (!(service instanceof ServiceRegistry)) {
182                        throw new RiceRuntimeException("Endpoint to service registry at URL '" + registryBootstrapUrl + "' was not an instance of ServiceRegistry, instead was: " + service);
183                }
184                return (ServiceRegistry)service;
185        }
186        
187}