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