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.api.bus.support;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.commons.lang.builder.EqualsBuilder;
020import org.apache.commons.lang.builder.HashCodeBuilder;
021import org.apache.commons.lang.builder.ReflectionToStringBuilder;
022import org.apache.log4j.Logger;
023import org.kuali.rice.core.api.CoreConstants;
024import org.kuali.rice.core.api.config.ConfigurationException;
025import org.kuali.rice.core.api.config.CoreConfigHelper;
026import org.kuali.rice.core.api.config.property.ConfigContext;
027import org.kuali.rice.core.api.security.credentials.CredentialsType;
028import org.kuali.rice.core.api.util.ClassLoaderUtils;
029import org.kuali.rice.ksb.api.bus.Endpoint;
030import org.kuali.rice.ksb.api.bus.ServiceConfiguration;
031import org.kuali.rice.ksb.api.bus.ServiceDefinition;
032
033import javax.xml.namespace.QName;
034import java.net.URL;
035
036
037/**
038 * The definition of a service on the service bus.
039 * 
040 * @author Kuali Rice Team (rice.collab@kuali.org)
041 */
042public abstract class AbstractServiceDefinition implements ServiceDefinition {
043
044        private static final Logger LOG = Logger.getLogger(AbstractServiceDefinition.class);
045                
046        // used internally to construct the service name
047        private String localServiceName;
048        private String serviceNameSpaceURI;
049        
050        private Object service;
051        private QName serviceName;
052        private boolean queue;
053        private Integer priority;
054        private Integer retryAttempts;
055        private Long millisToLive;
056        private String messageExceptionHandler;
057        private String servicePath;
058        private URL endpointUrl;
059        private Boolean busSecurity;
060        private CredentialsType credentialsType;
061        private String serviceVersion;
062        private String applicationId;
063    private String instanceId;
064
065        // if the service is exported from a plugin, we need to ensure it's invoked within the proper classloading context!
066        private ClassLoader serviceClassLoader;
067
068        protected AbstractServiceDefinition() {
069                this.busSecurity = Boolean.TRUE;
070                this.queue = true;
071                this.serviceClassLoader = ClassLoaderUtils.getDefaultClassLoader();
072        }
073
074        private boolean basicAuthentication = false;
075
076        /**
077         * @return the basicAuthentication
078         */
079        public boolean isBasicAuthentication() {
080                return this.basicAuthentication;
081        }
082
083        /**
084         * @param basicAuthentication the basicAuthentication to set
085         */
086        public void setBasicAuthentication(boolean basicAuthentication) {
087                this.basicAuthentication = basicAuthentication;
088        }
089
090        public Object getService() {
091                return this.service;
092        }
093        public void setService(Object service) {
094                this.service = service;
095        }
096        
097        public String getLocalServiceName() {
098                return this.localServiceName;
099        }
100        
101        public void setLocalServiceName(String serviceName) {
102                this.localServiceName = serviceName;
103        }
104        
105        public String getMessageExceptionHandler() {
106                return this.messageExceptionHandler;
107        }
108        
109        public void setMessageExceptionHandler(String messageExceptionHandler) {
110                this.messageExceptionHandler = messageExceptionHandler;
111        }
112        
113        public Integer getPriority() {
114                return this.priority;
115        }
116        
117        public void setPriority(Integer priority) {
118                this.priority = priority;
119        }
120        
121        public boolean isQueue() {
122                return this.queue;
123        }
124        
125        public void setQueue(boolean queue) {
126                this.queue = queue;
127        }
128        
129        public Integer getRetryAttempts() {
130                return this.retryAttempts;
131        }
132        
133        public void setRetryAttempts(Integer retryAttempts) {
134                this.retryAttempts = retryAttempts;
135        }
136
137        public QName getServiceName() {
138                if (this.serviceName == null) {
139                        if (this.serviceNameSpaceURI == null) {
140                            return new QName(this.applicationId, this.localServiceName);        
141                        } else {
142                            return new QName(this.serviceNameSpaceURI, this.localServiceName);
143                        }
144                        
145                }
146                return this.serviceName;
147        }
148        public void setServiceName(QName serviceName) {
149                this.serviceName = serviceName;
150        }
151        
152        @Override
153        public URL getEndpointUrl() {
154                return this.endpointUrl;
155        }
156        public void setEndpointUrl(URL endpointUrl) {
157                this.endpointUrl = endpointUrl;
158        }
159        
160        public void setCredentialsType(CredentialsType credentialsType) {
161            this.credentialsType = credentialsType;
162        }
163        
164        public CredentialsType getCredentialsType() {
165            return this.credentialsType;
166        }
167        
168        public String getServiceVersion() {
169                return serviceVersion;
170        }
171
172        public void setServiceVersion(String serviceVersion) {
173                this.serviceVersion = serviceVersion;
174        }
175
176        public String getApplicationId() {
177                return applicationId;
178        }
179        
180        public void setApplicationId(String applicationId) {
181                this.applicationId = applicationId;
182        }
183
184    @Override
185    public String getInstanceId() {
186        return instanceId;
187    }
188
189    public void setInstanceId(String instanceId) {
190        this.instanceId = instanceId;
191    }
192
193    @Override
194        public ClassLoader getServiceClassLoader() {
195                return this.serviceClassLoader;
196        }
197        
198        public void setServiceClassLoader(ClassLoader serviceClassLoader) {
199                this.serviceClassLoader = serviceClassLoader;
200        }
201
202        @Override
203        public void validate() {
204                
205                if (this.serviceName == null && this.localServiceName == null) {
206                        throw new ConfigurationException("Must give a serviceName or localServiceName");
207                }
208
209                if (this.applicationId == null) {
210                        String applicationId = CoreConfigHelper.getApplicationId();
211                        if (applicationId == null) {
212                                throw new ConfigurationException("Must have an applicationId");
213                        }       
214                        this.applicationId = applicationId;
215                }
216
217        if (this.instanceId == null) {
218                        String instanceId = CoreConfigHelper.getInstanceId();
219                        if (instanceId == null) {
220                                throw new ConfigurationException("Must have an instanceId");
221                        }
222                        this.instanceId = instanceId;
223                }
224                
225                if (this.serviceName != null && this.localServiceName == null) {
226                        this.localServiceName = this.getServiceName().getLocalPart();
227                }
228                        
229                if (this.servicePath != null){
230                        if (this.servicePath.endsWith("/")){
231                                this.servicePath = StringUtils.chop(servicePath);
232                        }
233                        if (!this.servicePath.startsWith("/")){
234                                this.servicePath = "/" + this.servicePath;
235                        }
236                } else {
237            // default the serivce path to namespace
238                        this.servicePath = "/";
239                }
240                
241                // default to 'unspecified' service version
242                if (StringUtils.isBlank(serviceVersion)) {
243                        setServiceVersion(CoreConstants.Versions.UNSPECIFIED);
244                }
245
246                LOG.debug("Validating service " + this.serviceName);
247                
248                
249                if (this.endpointUrl == null) {
250                        String endPointURL = ConfigContext.getCurrentContextConfig().getEndPointUrl();
251                        if (endPointURL == null) {
252                                throw new ConfigurationException("Must provide a serviceEndPoint or serviceServletURL");
253                        }
254                        if (! endPointURL.endsWith("/")) {
255                                endPointURL += servicePath;
256                        } else {
257                                endPointURL = StringUtils.chop(endPointURL) + servicePath;
258                        }
259                        try {
260                                if (servicePath.equals("/")){
261                                        this.endpointUrl = new URL(endPointURL + this.getServiceName().getLocalPart());
262                                } else {
263                                        this.endpointUrl = new URL(endPointURL + "/" + this.getServiceName().getLocalPart());
264                                }
265            } catch (Exception e) {
266                                throw new ConfigurationException("Service Endpoint URL creation failed.", e);
267                        }
268                        
269                }
270                                
271                if (this.priority == null) {
272                        setPriority(5);
273                }
274                
275                if (this.retryAttempts == null) {
276                        setRetryAttempts(0);
277                }
278                
279                if (this.millisToLive == null) {
280                        setMillisToLive(new Long(-1));
281                }
282
283        }
284        
285        @Override
286        public Endpoint establishEndpoint() {
287                return BasicEndpoint.newEndpoint(configure(), getService());
288        }
289        
290        protected abstract ServiceConfiguration configure();
291        
292        public String getServiceNameSpaceURI() {
293                return this.serviceNameSpaceURI;
294        }
295        public void setServiceNameSpaceURI(String serviceNameSpaceURI) {
296                this.serviceNameSpaceURI = serviceNameSpaceURI;
297        }
298        public Long getMillisToLive() {
299                return this.millisToLive;
300        }
301        public void setMillisToLive(Long millisToLive) {
302                this.millisToLive = millisToLive;
303        }
304        public Boolean getBusSecurity() {
305                return this.busSecurity;
306        }
307        public void setBusSecurity(Boolean busSecurity) {
308                this.busSecurity = busSecurity;
309        }
310        
311        /**
312         * @return the servicePath
313         */
314        public String getServicePath() {
315                return this.servicePath;
316        }
317
318        /**
319         * @param servicePath the servicePath to set
320         */
321        public void setServicePath(String servicePath) {
322                this.servicePath = servicePath;
323        }
324        
325        public String toString() {
326            return ReflectionToStringBuilder.toString(this);
327        }
328        
329        @Override
330    public boolean equals(Object object) {
331                return EqualsBuilder.reflectionEquals(object, this);
332    }
333
334        @Override
335    public int hashCode() {
336        return HashCodeBuilder.reflectionHashCode(this);
337    }
338
339        
340}