001/**
002 * Copyright 2005-2016 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 javax.xml.namespace.QName;
019
020import org.apache.commons.lang.StringUtils;
021import org.kuali.rice.ksb.api.bus.Endpoint;
022import org.kuali.rice.ksb.api.bus.ServiceConfiguration;
023import org.kuali.rice.ksb.api.registry.ServiceDescriptor;
024import org.kuali.rice.ksb.api.registry.ServiceInfo;
025import org.kuali.rice.ksb.api.registry.ServiceRegistry;
026
027public final class RemoteService {
028        
029        private final ServiceInfo serviceInfo;
030        private final ServiceRegistry serviceRegistry;
031        
032        private final Object endpointAcquisitionLock = new Object();
033        private volatile Endpoint endpoint;
034        
035        public RemoteService(ServiceInfo serviceInfo, ServiceRegistry serviceRegistry) {
036                validateServiceInfo(serviceInfo);
037                if (serviceRegistry == null) {
038                        throw new IllegalArgumentException("serviceRegistry cannot be null");
039                }
040                this.serviceInfo = serviceInfo;
041                this.serviceRegistry = serviceRegistry;
042        }
043        
044        private static void validateServiceInfo(ServiceInfo serviceInfo) {
045                if (serviceInfo == null) {
046                        throw new IllegalArgumentException("serviceInfo cannot be null");
047                }
048                if (serviceInfo.getServiceId() == null) {
049                        throw new IllegalArgumentException("serviceInfo must have a serviceId but was null");
050                }
051        }
052        
053        public QName getServiceName() {
054                return serviceInfo.getServiceName();
055        }
056                
057        public ServiceInfo getServiceInfo() {
058                return serviceInfo;
059        }
060        
061        public Endpoint getEndpoint() {
062                // double-checked locking idiom - see Effective Java, Item 71
063                Endpoint internalEndpoint = this.endpoint;
064                if (internalEndpoint == null) {
065                        synchronized (endpointAcquisitionLock) {
066                                internalEndpoint = this.endpoint;
067                                if (internalEndpoint == null) {
068                                        this.endpoint = internalEndpoint = new LazyEndpoint(constructServiceConfiguration()); 
069                                }
070                        }
071                }
072                return internalEndpoint;
073        }
074        
075        protected ServiceConfiguration constructServiceConfiguration() {
076                ServiceDescriptor serviceDescriptor = serviceRegistry.getServiceDescriptor(serviceInfo.getServiceDescriptorId());
077                if (serviceDescriptor == null) {
078                        throw new IllegalStateException("Failed to locate ServiceDescriptor for ServiceInfo with serviceDescriptorId=" + serviceInfo.getServiceDescriptorId());
079                } else if (StringUtils.isBlank(serviceDescriptor.getDescriptor())) {
080                        throw new IllegalStateException("ServiceDescriptor descriptor value is blank or null for descriptor with serviceEndpointId=" + serviceInfo.getServiceId());
081                }
082                return ServiceConfigurationSerializationHandler.unmarshallFromXml(serviceDescriptor.getDescriptor());
083        }
084        
085        @Override
086    public boolean equals(Object obj) {
087                if (!(obj instanceof RemoteService)) {
088                        return false;
089                }
090                return serviceInfo.equals(((RemoteService)obj).getServiceInfo());
091    }
092
093        @Override
094    public int hashCode() {
095        return serviceInfo.hashCode();
096    }
097        
098}