001    /**
002     * Copyright 2005-2013 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     */
016    package org.kuali.rice.ksb.impl.bus;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.apache.cxf.Bus;
020    import org.apache.cxf.frontend.ClientProxyFactoryBean;
021    import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
022    import org.kuali.rice.core.api.config.property.ConfigContext;
023    import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
024    import org.kuali.rice.core.api.exception.RiceRuntimeException;
025    import org.kuali.rice.ksb.api.registry.RemoveAndPublishResult;
026    import org.kuali.rice.ksb.api.registry.ServiceDescriptor;
027    import org.kuali.rice.ksb.api.registry.ServiceEndpoint;
028    import org.kuali.rice.ksb.api.registry.ServiceEndpointStatus;
029    import org.kuali.rice.ksb.api.registry.ServiceInfo;
030    import org.kuali.rice.ksb.api.registry.ServiceRegistry;
031    import org.kuali.rice.ksb.impl.cxf.interceptors.ImmutableCollectionsInInterceptor;
032    import org.kuali.rice.ksb.security.soap.CXFWSS4JInInterceptor;
033    import org.kuali.rice.ksb.security.soap.CXFWSS4JOutInterceptor;
034    import org.kuali.rice.ksb.util.KSBConstants;
035    
036    import javax.xml.namespace.QName;
037    import java.util.List;
038    
039    /**
040     * TODO... 
041     * 
042     * @author Kuali Rice Team (rice.collab@kuali.org)
043     *
044     */
045    public 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    }