]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
f5c0c0d95cbcffc722840857d48b87e1d9d49986
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.common.context;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Properties;
31
32 import javax.ws.rs.core.MultivaluedMap;
33 import javax.ws.rs.core.UriInfo;
34
35 import org.collectionspace.authentication.spi.AuthNContext;
36 import org.collectionspace.services.client.AuthorityClient;
37 import org.collectionspace.services.client.CollectionSpaceClient;
38 import org.collectionspace.services.client.IClientQueryParams;
39 import org.collectionspace.services.client.IQueryManager;
40 import org.collectionspace.services.client.workflow.WorkflowClient;
41 import org.collectionspace.services.common.ServiceMain;
42 import org.collectionspace.services.common.api.Tools;
43 import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
44 import org.collectionspace.services.common.config.PropertyItemUtils;
45 import org.collectionspace.services.common.config.ServiceConfigUtils;
46 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
47 import org.collectionspace.services.common.document.DocumentHandler;
48 import org.collectionspace.services.common.document.DocumentFilter;
49 import org.collectionspace.services.common.document.ValidatorHandler;
50 import org.collectionspace.services.common.security.SecurityContext;
51 import org.collectionspace.services.common.security.SecurityContextImpl;
52 import org.collectionspace.services.common.security.UnauthorizedException;
53 import org.collectionspace.services.config.ClientType;
54 import org.collectionspace.services.config.service.ObjectPartType;
55 import org.collectionspace.services.config.service.ServiceBindingType;
56 import org.collectionspace.services.config.tenant.RemoteClientConfig;
57 import org.collectionspace.services.config.tenant.RepositoryDomainType;
58 import org.collectionspace.services.config.tenant.TenantBindingType;
59 import org.collectionspace.services.config.types.PropertyItemType;
60 import org.collectionspace.services.config.types.PropertyType;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 /**
65  * AbstractServiceContext
66  *
67  * $LastChangedRevision: $
68  * $LastChangedDate: $
69  */
70 /**
71  * @author pschmitz
72  *
73  * @param <IT>
74  * @param <OT>
75  */
76 /**
77  * @author pschmitz
78  *
79  * @param <IT>
80  * @param <OT>
81  */
82 @SuppressWarnings("rawtypes")
83 public abstract class AbstractServiceContextImpl<IT, OT>
84         implements ServiceContext<IT, OT> {
85
86     /** The logger. */
87     final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
88     
89     /** The properties. */
90     Map<String, Object> properties = new HashMap<String, Object>();
91     /** The object part map. */
92     Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
93     /** The service binding. */
94     protected ServiceBindingType serviceBinding;
95     /** The tenant binding. */
96     private TenantBindingType tenantBinding;
97     /** repository domain used by the service */
98     private RepositoryDomainType repositoryDomain;
99         /** The override document type. */
100     private String overrideDocumentType = null;
101     /** The val handlers. */
102     private List<ValidatorHandler<IT, OT>> valHandlers = null;
103     /** The authority client -use for shared authority server */
104     private AuthorityClient authorityClient = null;
105     /** The doc handler. */
106     private DocumentHandler docHandler = null;
107     /** security context */
108     private SecurityContext securityContext;
109     /** The sessions JAX-RS URI information */
110     private UriInfo uriInfo;
111     /** The current repository session */
112     private Object currentRepositorySession;
113     /** A reference count for the current repository session */
114     private int currentRepoSesssionRefCount = 0;
115         
116     /**
117      * Instantiates a new abstract service context impl.
118      */
119     private AbstractServiceContextImpl() {
120         // private constructor for singleton pattern
121     }
122     // request query params
123     /** The query params. */
124     private MultivaluedMap<String, String> queryParams;
125
126     /**
127      * Instantiates a new abstract service context impl.
128      * 
129      * @param serviceName the service name
130      * 
131      * @throws UnauthorizedException the unauthorized exception
132      */
133     protected AbstractServiceContextImpl(String serviceName, UriInfo uriInfo) throws UnauthorizedException {
134
135         //establish security context
136         securityContext = new SecurityContextImpl(uriInfo);
137         //make sure tenant context exists
138         checkTenantContext();
139
140         String tenantId = securityContext.getCurrentTenantId();
141         if (AuthorizationCommon.ALL_TENANTS_MANAGER_TENANT_ID.equals(tenantId) ||
142                         AuthNContext.ANONYMOUS_TENANT_ID.equals(tenantId)) {
143                 // Tenant Manager has no tenant binding, so don't bother...
144                 tenantBinding = null;
145                 serviceBinding = null;
146                 repositoryDomain = null;
147         } else {
148                 //retrieve service bindings
149                 TenantBindingConfigReaderImpl tReader =
150                         ServiceMain.getInstance().getTenantBindingConfigReader();
151                 tenantBinding = tReader.getTenantBinding(tenantId);
152                 if (tenantBinding == null) {
153                     String msg = "No tenant binding found for tenantId=" + tenantId
154                             + " while processing request for service= " + serviceName;
155                     logger.error(msg);
156                     throw new IllegalStateException(msg);
157                 }
158                 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
159                 if (serviceBinding == null) {
160                     String msg = "No service binding found while processing request for "
161                             + serviceName + " for tenant id=" + getTenantId()
162                             + " name=" + getTenantName();
163                     logger.error(msg);
164                     throw new IllegalStateException(msg);
165                 }
166                 if (logger.isDebugEnabled()) {
167                     logger.debug("tenantId=" + tenantId
168                             + " service binding=" + serviceBinding.getName());
169                 }
170                 repositoryDomain = tReader.getRepositoryDomain(tenantId, serviceName);
171                 if (repositoryDomain != null) {
172                     if (logger.isDebugEnabled()) {
173                         logger.debug("tenantId=" + tenantId
174                                 + " repository doamin=" + repositoryDomain.getName());
175                     }
176                 }
177         }
178     }
179     
180     public int getTimeoutParam(UriInfo ui) {
181                 int result = DEFAULT_TX_TIMEOUT;
182
183                 MultivaluedMap<String, String> queryParams = (ui == null) ? null : ui.getQueryParameters();
184                 if (queryParams != null) {
185                         String timeoutString = queryParams.getFirst(IClientQueryParams.IMPORT_TIMEOUT_PARAM);
186                         if (timeoutString != null)
187                                 try {
188                                         result = Integer.parseInt(timeoutString);
189                                 } catch (NumberFormatException e) {
190                                         logger.warn("Transaction timeout period parameter could not be parsed.  The characters in the parameter string must all be decimal digits.  The Import service will use the default timeout period instead.",
191                                                         e);
192                                 }
193                 }
194
195                 return result;
196         }
197     
198     @Override
199     public int getTimeoutSecs() {
200         UriInfo uriInfo = this.getUriInfo();
201         return this.getTimeoutParam(uriInfo);
202     }
203
204     /* (non-Javadoc)
205      * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
206      */
207     @Override
208     public String getCommonPartLabel() {
209         return getCommonPartLabel(getServiceName());
210     }
211
212     /* (non-Javadoc)
213      * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel(java.lang.String)
214      */
215     public String getCommonPartLabel(String schemaName) {
216         return schemaName.toLowerCase() + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
217     }
218
219     /* (non-Javadoc)
220      * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
221      */
222     @Override
223     public Map<String, ObjectPartType> getPartsMetadata() {
224         if (objectPartMap.size() != 0) {
225             return objectPartMap;
226         }
227         ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
228         return objectPartMap;
229     }
230
231     /**
232      * Gets the properties for part.
233      * 
234      * @param partLabel the part label
235      * 
236      * @return the properties for part
237      */
238     public List<PropertyItemType> getPropertiesForPart(String partLabel) {
239         Map<String, ObjectPartType> partMap = getPartsMetadata();
240         ObjectPartType part = partMap.get(partLabel);
241         if (part == null) {
242             throw new RuntimeException("No such part found: " + partLabel);
243         }
244         List<PropertyType> propNodeList = part.getProperties();
245         return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
246     }
247
248     /**
249      * @param partLabel The name of the scehma part to search in
250      * @param propName The name of the property (or properties) to find
251      * @param qualified Whether the returned values should be qualified with the
252      *          partLabel. This is when the property values are schema field references.
253      * @return List of property values for the matched property on the named schema part.
254      */
255     public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
256         List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
257         return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
258                 (qualified ? (partLabel + ":") : null));
259     }
260
261     /**
262      * @param propName The name of the property (or properties) to find
263      * @param qualified Whether the returned values should be qualified with the
264      *          partLabel. This is when the property values are schema field references.
265      * @return List of property values for the matched property on any schema part.
266      */
267     public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
268         return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
269     }
270
271     /* (non-Javadoc)
272      * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
273      */
274     public String getServiceBindingPropertyValue(String propName) {
275         return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
276     }
277
278     /**
279      * Gets the common part properties.
280      * 
281      * @return the common part properties
282      */
283     public List<PropertyItemType> getCommonPartProperties() {
284         return getPropertiesForPart(getCommonPartLabel());
285     }
286
287     /**
288      * @param propName The name of the property (or properties) to find
289      * @param qualified Whether the returned values should be qualified with the
290      *          partLabel. This is when the property values are schema field references.
291      * @return List of property values for the matched property on the common schema part.
292      */
293     public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
294         return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
295     }
296
297     /* (non-Javadoc)
298      * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
299      */
300     @Override
301     public String getQualifiedServiceName() {
302         return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
303     }
304
305     /* (non-Javadoc)
306      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
307      */
308     @Override
309     public String getRepositoryClientName() {
310         if (repositoryDomain == null) {
311             return null;
312         }
313         return repositoryDomain.getRepositoryClient();
314     }
315
316     /* (non-Javadoc)
317      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
318      */
319     @Override
320     public ClientType getRepositoryClientType() {
321         //assumption: there is only one repository client configured
322         return ServiceMain.getInstance().getClientType();
323     }
324
325     /* (non-Javadoc)
326      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
327      */
328     @Override
329     public String getRepositoryDomainName() {
330         if (repositoryDomain == null) {
331             return null;
332         }
333         return repositoryDomain.getName();
334     }
335
336     /* (non-Javadoc)
337      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
338      */
339     @Override
340     public String getRepositoryDomainStorageName() {
341         if (repositoryDomain == null) {
342             return null;
343         }
344         return repositoryDomain.getStorageName();
345     }
346
347     /* (non-Javadoc)
348      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
349      */
350     @Override
351     public String getRepositoryWorkspaceId() {
352         return ServiceMain.getInstance().getWorkspaceId(getTenantId(), getServiceName());
353     }
354
355     /* (non-Javadoc)
356      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
357      */
358     @Override
359     public String getRepositoryWorkspaceName() {
360         //service name is workspace name by convention
361         return serviceBinding.getName();
362     }
363
364     /* (non-Javadoc)
365      * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
366      */
367     @Override
368     public ServiceBindingType getServiceBinding() {
369         return serviceBinding;
370     }
371
372     /* (non-Javadoc)
373      * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
374      */
375     @Override
376     public String getServiceName() {
377         return serviceBinding.getName();
378     }
379
380     /* (non-Javadoc)
381      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
382      */
383     @Override
384     public String getDocumentType() {
385         // If they have not overridden the setting, use the type of the service
386         // object.
387         return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
388     }
389     
390     @Override
391     public String getTenantQualifiedDoctype(String docType) {
392         // If they have not overridden the setting, use the type of the service
393         // object.
394         String result = ServiceBindingUtils.getTenantQualifiedDocType(this.getTenantId(), docType);
395         
396         return result;
397     }
398     
399     @Override
400     public String getTenantQualifiedDoctype() {
401         String docType = (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
402         return getTenantQualifiedDoctype(docType);
403     }
404
405     /* (non-Javadoc)
406      * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
407      */
408     @Override
409     public void setDocumentType(String docType) {
410         overrideDocumentType = docType;
411     }
412
413     /* (non-Javadoc)
414      * @see org.collectionspace.services.common.context.ServiceContext#getSecurityContext()
415      */
416     @Override
417     public SecurityContext getSecurityContext() {
418         return securityContext;
419     }
420
421     /* (non-Javadoc)
422      * @see org.collectionspace.services.common.context.ServiceContext#getUserId()
423      */
424     @Override
425     public String getUserId() {
426         return securityContext.getUserId();
427     }
428
429     /* (non-Javadoc)
430      * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
431      */
432     @Override
433     public String getTenantId() {
434         return securityContext.getCurrentTenantId();
435     }
436
437     /* (non-Javadoc)
438      * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
439      */
440     @Override
441     public String getTenantName() {
442         return securityContext.getCurrentTenantName();
443     }
444
445     /* (non-Javadoc)
446      * @see org.collectionspace.services.common.context.ServiceContext#getInput()
447      */
448     @Override
449     public abstract IT getInput();
450
451     /* (non-Javadoc)
452      * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
453      */
454     @Override
455     public abstract void setInput(IT input);
456
457     /* (non-Javadoc)
458      * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
459      */
460     @Override
461     public abstract OT getOutput();
462
463     /* (non-Javadoc)
464      * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
465      */
466     @Override
467     public abstract void setOutput(OT output);
468
469     /* (non-Javadoc)
470      * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
471      */
472     @Override
473     public Map<String, Object> getProperties() {
474         return properties;
475     }
476
477     /* (non-Javadoc)
478      * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
479      */
480     @Override
481     public void setProperties(Map<String, Object> props) {
482         properties.putAll(props);
483     }
484
485     /* (non-Javadoc)
486      * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
487      */
488     public Object getProperty(String name) {
489         return properties.get(name);
490     }
491
492     /* (non-Javadoc)
493      * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
494      */
495     public void setProperty(String name, Object o) {
496         properties.put(name, o);
497     }
498
499     /**
500      * checkTenantContext makss sure tenant context exists
501      *
502      * @return the string
503      *
504      * @throws UnauthorizedException the unauthorized exception
505      */
506     private void checkTenantContext() throws UnauthorizedException {
507
508         String tenantId = securityContext.getCurrentTenantId();
509         if (tenantId == null) {
510             String msg = "Could not find tenant context";
511             logger.error(msg);
512             throw new UnauthorizedException(msg);
513         }
514     }
515
516     /**
517      * Helps to filter for queries that either want to include or exclude documents in deleted workflow states.
518      * 
519      * @param queryParams
520      * @return
521      */
522     private static String buildWorkflowWhereClause(MultivaluedMap<String, String> queryParams) {
523         String result = null;
524         
525         String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
526         String includeOnlyDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED);
527
528         if (includeDeleted != null && includeDeleted.equalsIgnoreCase(Boolean.FALSE.toString())) {      
529                 result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
530                                 WorkflowClient.WORKFLOWSTATE_DELETED, WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED, WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
531         } else if (includeOnlyDeleted != null && includeOnlyDeleted.equalsIgnoreCase(Boolean.TRUE.toString())) {
532                 result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
533                                 WorkflowClient.WORKFLOWSTATE_PROJECT, WorkflowClient.WORKFLOWSTATE_LOCKED, WorkflowClient.WORKFLOWSTATE_REPLICATED);
534         }
535         
536         return result;
537     }
538     
539     /**
540      * Creates the document handler instance.
541      * 
542      * @return the document handler
543      * 
544      * @throws Exception the exception
545      */
546     private DocumentHandler createDocumentHandlerInstance() throws Exception {
547         docHandler = ServiceConfigUtils.createDocumentHandlerInstance(tenantBinding, serviceBinding);
548         //
549         // Create a default document filter
550         //
551         docHandler.setServiceContext(this);
552         DocumentFilter docFilter = docHandler.createDocumentFilter();
553         //
554         // If the context was created with query parameters,
555         // reflect the values of those parameters in the document filter
556         // to specify sort ordering, pagination, etc.
557         //
558         MultivaluedMap<String, String> queryParameters = this.getQueryParams();
559         if (queryParameters != null) {
560           docFilter.setSortOrder(queryParameters);
561           docFilter.setPagination(queryParameters);
562           String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
563           if (workflowWhereClause != null) {
564                   docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);                 
565           }            
566
567         }
568         docHandler.setDocumentFilter(docFilter);
569
570         return docHandler;
571     }
572
573     /* (non-Javadoc)
574      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
575      */
576     @Override
577     public DocumentHandler getDocumentHandler() throws Exception {
578         DocumentHandler result = docHandler;
579         // create a new instance if one does not yet exist
580         if (result == null) {
581             result = createDocumentHandlerInstance();
582         }
583         return result;
584     }
585
586     @Override
587     public void setDocumentHandler(DocumentHandler handler) throws Exception {
588         if (handler != null) {
589                 docHandler = handler;
590         }
591     }
592
593     /* (non-Javadoc)
594      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
595      */
596     @Override
597     public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
598         DocumentHandler result = getDocumentHandler();
599         DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
600         documentFilter.setPagination(queryParams);
601         return result;
602     }
603     
604     /*
605      * If this element is set in the service binding then use it otherwise
606      * assume that asserts are NOT disabled.
607      */
608     private boolean disableValidationAsserts() {
609         boolean result;
610         Boolean disableAsserts = getServiceBinding().isDisableAsserts();
611         result = (disableAsserts != null) ? disableAsserts : false;
612         return result;
613     }
614     
615     /* (non-Javadoc)
616      * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
617      */
618     @Override
619     public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
620         if (valHandlers != null) {
621             return valHandlers;
622         }
623         List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
624         List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
625         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
626         for (String clazz : handlerClazzes) {
627             clazz = clazz.trim();
628             try {
629                     Class<?> c = tccl.loadClass(clazz);
630                     if (disableValidationAsserts() == false) {
631                         // enable validation assertions
632                         tccl.setClassAssertionStatus(clazz, true);
633                     }
634                     if (ValidatorHandler.class.isAssignableFrom(c)) {
635                         handlers.add((ValidatorHandler) c.newInstance());
636                     }
637             } catch (ClassNotFoundException e) {
638                 String msg = String.format("Missing document validation handler: '%s'.", clazz);
639                 logger.warn(msg);
640                 logger.trace(msg, e);
641             }
642         }
643         valHandlers = handlers;
644         return valHandlers;
645     }
646     
647     /**
648      * If one doesn't already exist, use the default properties filename to load a set of properties that
649      * will be used to create an HTTP client to a CollectionSpace instance.
650      */
651     @Override
652     public AuthorityClient getClient() throws Exception {
653         AuthorityClient result = authorityClient;
654
655         if (authorityClient == null) {
656                 result = authorityClient = getClient(CollectionSpaceClient.DEFAULT_CLIENT_PROPERTIES_FILENAME);
657         }
658         
659         return result;
660     }
661     
662     /*
663      * Use the properties filename passed in to load the URL and credentials that will be used
664      * to create a new HTTP client.
665      * 
666      * Never uses or resets the this.authorityClient member.  Always creates a new HTTP client using
667      * the loaded properties.
668      * 
669      * (non-Javadoc)
670      * @see org.collectionspace.services.common.context.ServiceContext#getClient(java.lang.String)
671      */
672         @Override
673     public AuthorityClient getClient(String clientPropertiesFilename) throws Exception {
674         AuthorityClient result = null;
675         
676         Properties inProperties = Tools.loadProperties(clientPropertiesFilename, true);
677         result = getClient(inProperties);
678         
679         return result;
680     }
681     
682     public AuthorityClient getClient(Properties inProperties) throws Exception {
683         AuthorityClient result = null;
684         
685         String authorityClientClazz = getServiceBinding().getClientHandler();
686         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
687         authorityClientClazz = authorityClientClazz.trim();
688         try {
689             Class<?> c = tccl.loadClass(authorityClientClazz);
690             if (AuthorityClient.class.isAssignableFrom(c)) {
691                 result = authorityClient = ((AuthorityClient) c.newInstance());
692                 result.setClientProperties(inProperties);
693             } else {
694                 logger.error(String.format("The service binding clientHandler class '%s' for '%s' service was not of type AuthorityClient.",
695                                 authorityClientClazz, this.getServiceName()));
696             }
697         } catch (ClassNotFoundException e) {
698                 String msg = String.format("Missing document validation handler: '%s'.", authorityClientClazz);
699                 logger.warn(msg);
700                 logger.trace(msg, e);
701         }
702         
703         return result;
704     }
705     
706     @Override
707     public AuthorityClient getClient(RemoteClientConfig remoteClientConfig) throws Exception {
708         AuthorityClient result = null;
709         
710         Properties properties = new Properties();
711         properties.setProperty(AuthorityClient.URL_PROPERTY, remoteClientConfig.getUrl());
712         properties.setProperty(AuthorityClient.USER_PROPERTY, remoteClientConfig.getUser());
713         properties.setProperty(AuthorityClient.PASSWORD_PROPERTY, remoteClientConfig.getPassword());
714         properties.setProperty(AuthorityClient.SSL_PROPERTY, remoteClientConfig.getSsl());
715         properties.setProperty(AuthorityClient.AUTH_PROPERTY, remoteClientConfig.getAuth());
716         //
717         // Optional values
718         String tenantId = remoteClientConfig.getTenantId();
719         if (tenantId != null) {
720                 properties.setProperty(AuthorityClient.TENANT_ID_PROPERTY, tenantId);
721         }
722         String tenantName = remoteClientConfig.getTenantName();
723         if (tenantName != null) {
724                 properties.setProperty(AuthorityClient.TENANT_NAME_PROPERTY, tenantName);
725         }
726         
727         result = getClient(properties);
728         
729         return result;
730     }
731     
732     @Override
733     public void addValidatorHandler(ValidatorHandler<IT, OT> validator) throws Exception {
734         if (valHandlers == null) {
735             valHandlers = new ArrayList<ValidatorHandler<IT, OT>>();
736         }
737         valHandlers.add(validator);
738     }
739
740     /* (non-Javadoc)
741      * @see java.lang.Object#toString()
742      */
743     @Override
744     public String toString() {
745         StringBuilder msg = new StringBuilder();
746         msg.append("AbstractServiceContext [");
747         msg.append("service name=" + serviceBinding.getName() + " ");
748         msg.append("service version=" + serviceBinding.getVersion() + " ");
749         msg.append("tenant id=" + tenantBinding.getId() + " ");
750         msg.append("tenant name=" + tenantBinding.getName() + " ");
751         msg.append(tenantBinding.getDisplayName() + " ");
752         if (repositoryDomain != null) {
753             msg.append("tenant repository domain=" + repositoryDomain.getName());
754         }
755         for (Map.Entry<String, Object> entry : properties.entrySet()) {
756             msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
757         }
758         msg.append("]");
759         return msg.toString();
760     }
761
762     /* (non-Javadoc)
763      * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
764      */
765     @Override
766     public MultivaluedMap<String, String> getQueryParams() {
767
768          if (queryParams == null){
769               if (this.uriInfo != null){
770                 queryParams = this.uriInfo.getQueryParameters();
771             }
772          }
773          if (queryParams == null){
774              queryParams = new org.jboss.resteasy.specimpl.MultivaluedMapImpl<String,String>();
775         }
776         return this.queryParams;
777     }
778
779     @Override
780      public MultivaluedMap<String, String> getQueryParamsPtr() {
781            return this.queryParams;
782     }
783
784     /* (non-Javadoc)
785      * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
786      */
787     @Override
788     public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
789         this.queryParams = theQueryParams;
790     }
791
792     @Override
793     public void setUriInfo(UriInfo ui){
794         this.uriInfo = ui;
795     }
796
797         @Override
798         public UriInfo getUriInfo() {
799                 return this.uriInfo;
800         }
801         
802         /*
803          * We expect the 'currentRepositorySession' member to be set only once per instance.  Also, we expect only one open repository session
804          * per HTTP request.  We'll log an error if we see more than one attempt to set a service context's current repo session.
805          * (non-Javadoc)
806          * @see org.collectionspace.services.common.context.ServiceContext#setCurrentRepositorySession(java.lang.Object)
807          */
808         @Override
809         public void setCurrentRepositorySession(Object repoSession) throws Exception {
810                 if (repoSession == null) {
811                         String errMsg = "Setting a service context's repository session to null is not allowed.";
812                         logger.error(errMsg);
813                         throw new Exception(errMsg);
814                 } else if (currentRepositorySession != null && currentRepositorySession != repoSession) {
815                         String errMsg = "The current service context's repository session was replaced.  This may cause unexpected behavior and/or data loss.";
816                         logger.error(errMsg);
817                         throw new Exception(errMsg);
818                 }
819                 
820                 currentRepositorySession = repoSession;
821                 this.currentRepoSesssionRefCount++;
822         }
823         
824         @Override
825         public void clearCurrentRepositorySession() {
826                 if (this.currentRepoSesssionRefCount > 0) {
827                         currentRepoSesssionRefCount--;
828                 }
829                 
830                 if (currentRepoSesssionRefCount == 0) {
831                         this.currentRepositorySession = null;
832                 }
833         }
834         
835         @Override
836         public Object getCurrentRepositorySession() {
837                 // TODO Auto-generated method stub
838                 return currentRepositorySession;
839         }       
840
841         @Override       
842         public RepositoryDomainType getRepositoryDomain() {
843                 return repositoryDomain;
844         }
845
846         @Override       
847         public void setRepositoryDomain(RepositoryDomainType repositoryDomain) {
848                 this.repositoryDomain = repositoryDomain;
849         }
850 }