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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.common.context;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Properties;
32 import javax.ws.rs.core.MultivaluedMap;
33 import javax.ws.rs.core.Request;
34 import javax.ws.rs.core.UriInfo;
36 import org.collectionspace.authentication.AuthN;
37 import org.collectionspace.authentication.spi.AuthNContext;
38 import org.collectionspace.services.client.AuthorityClient;
39 import org.collectionspace.services.client.CollectionSpaceClient;
40 import org.collectionspace.services.client.IClientQueryParams;
41 import org.collectionspace.services.client.IQueryManager;
42 import org.collectionspace.services.client.workflow.WorkflowClient;
43 import org.collectionspace.services.common.ServiceMain;
44 import org.collectionspace.services.common.api.Tools;
45 import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
46 import org.collectionspace.services.common.config.PropertyItemUtils;
47 import org.collectionspace.services.common.config.ServiceConfigUtils;
48 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
49 import org.collectionspace.services.common.document.DocumentHandler;
50 import org.collectionspace.services.common.document.DocumentFilter;
51 import org.collectionspace.services.common.document.ValidatorHandler;
52 import org.collectionspace.services.common.security.SecurityContext;
53 import org.collectionspace.services.common.security.SecurityContextImpl;
54 import org.collectionspace.services.common.security.UnauthorizedException;
55 import org.collectionspace.services.config.ClientType;
56 import org.collectionspace.services.config.service.ObjectPartType;
57 import org.collectionspace.services.config.service.ServiceBindingType;
58 import org.collectionspace.services.config.tenant.RemoteClientConfig;
59 import org.collectionspace.services.config.tenant.RepositoryDomainType;
60 import org.collectionspace.services.config.tenant.TenantBindingType;
61 import org.collectionspace.services.config.types.PropertyItemType;
62 import org.collectionspace.services.config.types.PropertyType;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
67 * AbstractServiceContext
69 * $LastChangedRevision: $
84 @SuppressWarnings("rawtypes")
85 public abstract class AbstractServiceContextImpl<IT, OT>
86 implements ServiceContext<IT, OT> {
89 final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
91 /** The properties. */
92 Map<String, Object> properties = new HashMap<String, Object>();
93 /** The object part map. */
94 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
95 /** The service binding. */
96 protected ServiceBindingType serviceBinding;
97 /** The tenant binding. */
98 private TenantBindingType tenantBinding;
99 /** repository domain used by the service */
100 private RepositoryDomainType repositoryDomain;
101 /** The override document type. */
102 private String overrideDocumentType = null;
103 /** The val handlers. */
104 private List<ValidatorHandler<IT, OT>> valHandlers = null;
105 /** The authority client -use for shared authority server */
106 private AuthorityClient authorityClient = null;
107 /** The doc handler. */
108 private DocumentHandler docHandler = null;
109 /** security context */
110 private SecurityContext securityContext;
111 /** The sessions JAX-RS URI information */
112 private UriInfo uriInfo;
113 /** The JAX-RS request information */
114 private Request requestInfo;
115 /** The current repository session */
116 private Object currentRepositorySession;
117 /** A reference count for the current repository session */
118 private int currentRepoSesssionRefCount = 0;
121 * Instantiates a new abstract service context impl.
123 private AbstractServiceContextImpl() {
124 // private constructor for singleton pattern
126 // request query params
127 /** The query params. */
128 private MultivaluedMap<String, String> queryParams;
131 * Instantiates a new abstract service context impl.
133 * @param serviceName the service name
135 * @throws UnauthorizedException the unauthorized exception
137 protected AbstractServiceContextImpl(String serviceName, UriInfo uriInfo) throws UnauthorizedException {
139 //establish security context
140 securityContext = new SecurityContextImpl(uriInfo);
141 //make sure tenant context exists
142 checkTenantContext();
144 String tenantId = securityContext.getCurrentTenantId();
145 if (AuthN.ALL_TENANTS_MANAGER_TENANT_ID.equals(tenantId) ||
146 AuthN.ANONYMOUS_TENANT_ID.equals(tenantId)) {
147 // Tenant Manager has no tenant binding, so don't bother...
148 tenantBinding = null;
149 serviceBinding = null;
150 repositoryDomain = null;
152 //retrieve service bindings
153 TenantBindingConfigReaderImpl tReader =
154 ServiceMain.getInstance().getTenantBindingConfigReader();
155 tenantBinding = tReader.getTenantBinding(tenantId);
156 if (tenantBinding == null) {
157 String msg = "No tenant binding found for tenantId=" + tenantId
158 + " while processing request for service= " + serviceName;
160 throw new IllegalStateException(msg);
162 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
163 if (serviceBinding == null) {
164 String msg = "No service binding found while processing request for "
165 + serviceName + " for tenant id=" + getTenantId()
166 + " name=" + getTenantName();
168 throw new IllegalStateException(msg);
170 if (logger.isDebugEnabled()) {
171 logger.debug("tenantId=" + tenantId
172 + " service binding=" + serviceBinding.getName());
174 repositoryDomain = tReader.getRepositoryDomain(tenantId, serviceName);
175 if (repositoryDomain != null) {
176 if (logger.isDebugEnabled()) {
177 logger.debug("tenantId=" + tenantId
178 + " repository doamin=" + repositoryDomain.getName());
184 public int getTimeoutParam(UriInfo ui) {
185 int result = DEFAULT_TX_TIMEOUT;
187 MultivaluedMap<String, String> queryParams = (ui == null) ? null : ui.getQueryParameters();
188 if (queryParams != null) {
189 String timeoutString = queryParams.getFirst(IClientQueryParams.IMPORT_TIMEOUT_PARAM);
190 if (timeoutString == null) {
191 timeoutString = queryParams.getFirst(IClientQueryParams.IMPORT_TIMOUT_PARAM);
194 if (timeoutString != null) {
196 result = Integer.parseInt(timeoutString);
197 } catch (NumberFormatException e) {
198 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.",
208 public int getTimeoutSecs() {
209 UriInfo uriInfo = this.getUriInfo();
210 return this.getTimeoutParam(uriInfo);
214 * Returns TRUE unless the "recordUpdates" query param is set with a value of either "false", "FALSE", or "0"
218 public boolean shouldUpdateCoreValues() {
219 boolean recordUpdates = true;
221 MultivaluedMap<String, String> queryParams = getQueryParams();
222 String paramValue = queryParams.getFirst(IClientQueryParams.UPDATE_CORE_VALUES);
223 if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.FALSE.toString())) { // Find our if the caller wants us to record updates
224 recordUpdates = false;
225 } else if (paramValue != null && paramValue.equals(Long.toString(0))) {
226 recordUpdates = false;
229 return recordUpdates;
233 * Default value is 'FALSE'
234 * If this returns true, it means that the refname values in referencing objects (records that reference authority or vocabulary terms) will be updated
235 * regardless of their current value. This is sometimes needed when refname values become stale for one of several reasons.
239 public boolean shouldForceUpdateRefnameReferences() {
240 boolean forceUpdates = false;
242 MultivaluedMap<String, String> queryParams = getQueryParams();
243 String paramValue = queryParams.getFirst(IClientQueryParams.FORCE_REFNAME_UPDATES);
244 if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.TRUE.toString())) { // Find our if the caller wants us to force refname updates
246 } else if (paramValue != null && paramValue.equals(Long.toString(1))) {
255 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
258 public String getCommonPartLabel() {
259 return getCommonPartLabel(getServiceName());
263 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel(java.lang.String)
265 public String getCommonPartLabel(String schemaName) {
266 return schemaName.toLowerCase() + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
270 * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
273 public Map<String, ObjectPartType> getPartsMetadata() {
274 if (objectPartMap.size() != 0) {
275 return objectPartMap;
277 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
278 return objectPartMap;
282 * Gets the properties for part.
284 * @param partLabel the part label
286 * @return the properties for part
288 public List<PropertyItemType> getPropertiesForPart(String partLabel) {
289 Map<String, ObjectPartType> partMap = getPartsMetadata();
290 ObjectPartType part = partMap.get(partLabel);
292 throw new RuntimeException("No such part found: " + partLabel);
294 List<PropertyType> propNodeList = part.getProperties();
295 return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
299 * @param partLabel The name of the scehma part to search in
300 * @param propName The name of the property (or properties) to find
301 * @param qualified Whether the returned values should be qualified with the
302 * partLabel. This is when the property values are schema field references.
303 * @return List of property values for the matched property on the named schema part.
305 public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
306 List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
307 return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
308 (qualified ? (partLabel + ":") : null));
312 * @param propName The name of the property (or properties) to find
313 * @param qualified Whether the returned values should be qualified with the
314 * partLabel. This is when the property values are schema field references.
315 * @return List of property values for the matched property on any schema part.
317 public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
318 return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
322 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
324 public String getServiceBindingPropertyValue(String propName) {
325 return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
329 * Gets the common part properties.
331 * @return the common part properties
333 public List<PropertyItemType> getCommonPartProperties() {
334 return getPropertiesForPart(getCommonPartLabel());
338 * @param propName The name of the property (or properties) to find
339 * @param qualified Whether the returned values should be qualified with the
340 * partLabel. This is when the property values are schema field references.
341 * @return List of property values for the matched property on the common schema part.
343 public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
344 return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
348 * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
351 public String getQualifiedServiceName() {
352 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
356 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
359 public String getRepositoryClientName() {
360 if (repositoryDomain == null) {
363 return repositoryDomain.getRepositoryClient();
367 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
370 public ClientType getRepositoryClientType() {
371 //assumption: there is only one repository client configured
372 return ServiceMain.getInstance().getClientType();
376 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
379 public String getRepositoryDomainName() {
380 if (repositoryDomain == null) {
383 return repositoryDomain.getName();
387 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
390 public String getRepositoryDomainStorageName() {
391 if (repositoryDomain == null) {
394 return repositoryDomain.getStorageName();
398 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
401 public String getRepositoryWorkspaceId() {
402 return ServiceMain.getInstance().getWorkspaceId(getTenantId(), getServiceName());
406 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
409 public String getRepositoryWorkspaceName() {
410 //service name is workspace name by convention
411 return serviceBinding.getName();
415 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
418 public ServiceBindingType getServiceBinding() {
419 return serviceBinding;
423 * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
426 public String getServiceName() {
427 return serviceBinding.getName();
431 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
434 public String getDocumentType() {
435 // If they have not overridden the setting, use the type of the service
437 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
441 public String getTenantQualifiedDoctype(String docType) {
442 // If they have not overridden the setting, use the type of the service
444 String result = ServiceBindingUtils.getTenantQualifiedDocType(this.getTenantId(), docType);
450 public String getTenantQualifiedDoctype() {
451 String docType = (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
452 return getTenantQualifiedDoctype(docType);
456 * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
459 public void setDocumentType(String docType) {
460 overrideDocumentType = docType;
464 * @see org.collectionspace.services.common.context.ServiceContext#getSecurityContext()
467 public SecurityContext getSecurityContext() {
468 return securityContext;
472 * @see org.collectionspace.services.common.context.ServiceContext#getUserId()
475 public String getUserId() {
476 return securityContext.getUserId();
480 * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
483 public String getTenantId() {
484 return securityContext.getCurrentTenantId();
488 * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
491 public String getTenantName() {
492 return securityContext.getCurrentTenantName();
496 * @see org.collectionspace.services.common.context.ServiceContext#getInput()
499 public abstract IT getInput();
502 * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
505 public abstract void setInput(IT input);
508 * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
511 public abstract OT getOutput();
514 * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
517 public abstract void setOutput(OT output);
520 * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
523 public Map<String, Object> getProperties() {
528 * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
531 public void setProperties(Map<String, Object> props) {
532 properties.putAll(props);
536 * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
538 public Object getProperty(String name) {
539 return properties.get(name);
543 * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
545 public void setProperty(String name, Object o) {
546 properties.put(name, o);
550 * checkTenantContext makss sure tenant context exists
554 * @throws UnauthorizedException the unauthorized exception
556 private void checkTenantContext() throws UnauthorizedException {
558 String tenantId = securityContext.getCurrentTenantId();
559 if (tenantId == null) {
560 String msg = "Could not find tenant context";
562 throw new UnauthorizedException(msg);
567 * Helps to filter for queries that either want to include or exclude documents in deleted workflow states.
572 private static String buildWorkflowWhereClause(MultivaluedMap<String, String> queryParams) {
573 String result = null;
575 String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
576 String includeOnlyDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED);
578 if (includeDeleted != null && includeDeleted.equalsIgnoreCase(Boolean.FALSE.toString())) {
579 result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
580 WorkflowClient.WORKFLOWSTATE_DELETED, WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED, WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
581 } else if (includeOnlyDeleted != null && includeOnlyDeleted.equalsIgnoreCase(Boolean.TRUE.toString())) {
582 result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
583 WorkflowClient.WORKFLOWSTATE_PROJECT, WorkflowClient.WORKFLOWSTATE_LOCKED, WorkflowClient.WORKFLOWSTATE_REPLICATED);
590 * Creates the document handler instance.
592 * @return the document handler
594 * @throws Exception the exception
596 private DocumentHandler createDocumentHandlerInstance() throws Exception {
597 docHandler = ServiceConfigUtils.createDocumentHandlerInstance(tenantBinding, serviceBinding);
599 // Create a default document filter
601 docHandler.setServiceContext(this);
602 DocumentFilter docFilter = docHandler.createDocumentFilter();
604 // If the context was created with query parameters,
605 // reflect the values of those parameters in the document filter
606 // to specify sort ordering, pagination, etc.
608 MultivaluedMap<String, String> queryParameters = this.getQueryParams();
609 if (queryParameters != null) {
610 docFilter.setSortOrder(queryParameters);
611 docFilter.setPagination(queryParameters);
612 String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
613 if (workflowWhereClause != null) {
614 docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
618 docHandler.setDocumentFilter(docFilter);
624 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
627 public DocumentHandler getDocumentHandler() throws Exception {
628 DocumentHandler result = docHandler;
629 // create a new instance if one does not yet exist
630 if (result == null) {
631 result = createDocumentHandlerInstance();
637 public void setDocumentHandler(DocumentHandler handler) throws Exception {
638 if (handler != null) {
639 docHandler = handler;
644 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
647 public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
648 DocumentHandler result = getDocumentHandler();
649 DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
650 documentFilter.setPagination(queryParams);
655 * If this element is set in the service binding then use it otherwise
656 * assume that asserts are NOT disabled.
658 private boolean disableValidationAsserts() {
660 Boolean disableAsserts = getServiceBinding().isDisableAsserts();
661 result = (disableAsserts != null) ? disableAsserts : false;
666 * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
669 public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
670 if (valHandlers != null) {
673 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
674 List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
675 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
676 for (String clazz : handlerClazzes) {
677 clazz = clazz.trim();
679 Class<?> c = tccl.loadClass(clazz);
680 if (disableValidationAsserts() == false) {
681 // enable validation assertions
682 tccl.setClassAssertionStatus(clazz, true);
684 if (ValidatorHandler.class.isAssignableFrom(c)) {
685 handlers.add((ValidatorHandler) c.newInstance());
687 } catch (ClassNotFoundException e) {
688 String msg = String.format("Missing document validation handler: '%s'.", clazz);
690 logger.trace(msg, e);
693 valHandlers = handlers;
698 * If one doesn't already exist, use the default properties filename to load a set of properties that
699 * will be used to create an HTTP client to a CollectionSpace instance.
702 public AuthorityClient getClient() throws Exception {
703 AuthorityClient result = authorityClient;
705 if (authorityClient == null) {
706 result = authorityClient = getClient(CollectionSpaceClient.DEFAULT_CLIENT_PROPERTIES_FILENAME);
713 * Use the properties filename passed in to load the URL and credentials that will be used
714 * to create a new HTTP client.
716 * Never uses or resets the this.authorityClient member. Always creates a new HTTP client using
717 * the loaded properties.
720 * @see org.collectionspace.services.common.context.ServiceContext#getClient(java.lang.String)
723 public AuthorityClient getClient(String clientPropertiesFilename) throws Exception {
724 AuthorityClient result = null;
726 Properties inProperties = Tools.loadProperties(clientPropertiesFilename, true);
727 result = getClient(inProperties);
732 public AuthorityClient getClient(Properties inProperties) throws Exception {
733 AuthorityClient result = null;
735 String authorityClientClazz = getServiceBinding().getClientHandler();
736 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
737 authorityClientClazz = authorityClientClazz.trim();
739 Class<?> c = tccl.loadClass(authorityClientClazz);
740 if (AuthorityClient.class.isAssignableFrom(c)) {
741 result = authorityClient = ((AuthorityClient) c.newInstance());
742 result.setClientProperties(inProperties);
744 logger.error(String.format("The service binding clientHandler class '%s' for '%s' service was not of type AuthorityClient.",
745 authorityClientClazz, this.getServiceName()));
747 } catch (ClassNotFoundException e) {
748 String msg = String.format("Missing document validation handler: '%s'.", authorityClientClazz);
750 logger.trace(msg, e);
757 public AuthorityClient getClient(RemoteClientConfig remoteClientConfig) throws Exception {
758 AuthorityClient result = null;
760 Properties properties = new Properties();
761 properties.setProperty(AuthorityClient.URL_PROPERTY, remoteClientConfig.getUrl());
762 properties.setProperty(AuthorityClient.USER_PROPERTY, remoteClientConfig.getUser());
763 properties.setProperty(AuthorityClient.PASSWORD_PROPERTY, remoteClientConfig.getPassword());
764 properties.setProperty(AuthorityClient.SSL_PROPERTY, remoteClientConfig.getSsl());
765 properties.setProperty(AuthorityClient.AUTH_PROPERTY, remoteClientConfig.getAuth());
768 String tenantId = remoteClientConfig.getTenantId();
769 if (tenantId != null) {
770 properties.setProperty(AuthorityClient.TENANT_ID_PROPERTY, tenantId);
772 String tenantName = remoteClientConfig.getTenantName();
773 if (tenantName != null) {
774 properties.setProperty(AuthorityClient.TENANT_NAME_PROPERTY, tenantName);
777 result = getClient(properties);
783 public void addValidatorHandler(ValidatorHandler<IT, OT> validator) throws Exception {
784 if (valHandlers == null) {
785 valHandlers = new ArrayList<ValidatorHandler<IT, OT>>();
787 valHandlers.add(validator);
791 * @see java.lang.Object#toString()
794 public String toString() {
795 StringBuilder msg = new StringBuilder();
796 msg.append("AbstractServiceContext [");
797 msg.append("service name=" + serviceBinding.getName() + " ");
798 msg.append("service version=" + serviceBinding.getVersion() + " ");
799 msg.append("tenant id=" + tenantBinding.getId() + " ");
800 msg.append("tenant name=" + tenantBinding.getName() + " ");
801 msg.append(tenantBinding.getDisplayName() + " ");
802 if (repositoryDomain != null) {
803 msg.append("tenant repository domain=" + repositoryDomain.getName());
805 for (Map.Entry<String, Object> entry : properties.entrySet()) {
806 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
809 return msg.toString();
813 * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
815 * When we first created these services, the RESTEasy query parameters used to be a modifiable map. That changed in a
816 * more recent version of RESTEasy, so we need to make a copy of the params into a modifiable map and return it instead.
819 public MultivaluedMap<String, String> getQueryParams() {
821 if (queryParams == null){
822 if (this.uriInfo != null){
823 queryParams = this.uriInfo.getQueryParameters();
826 if (queryParams == null){
827 queryParams = new org.jboss.resteasy.specimpl.MultivaluedMapImpl<String,String>();
829 return this.queryParams;
833 public MultivaluedMap<String, String> getQueryParamsPtr() {
834 return this.queryParams;
838 * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
841 public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
842 this.queryParams = theQueryParams;
846 public void setUriInfo(UriInfo ui){
851 public UriInfo getUriInfo() {
856 public Request getRequestInfo() {
857 return this.requestInfo;
861 public void setRequestInfo(Request requestInfo) {
862 this.requestInfo = requestInfo;
866 * We expect the 'currentRepositorySession' member to be set only once per instance. Also, we expect only one open repository session
867 * per HTTP request. We'll log an error if we see more than one attempt to set a service context's current repo session.
869 * @see org.collectionspace.services.common.context.ServiceContext#setCurrentRepositorySession(java.lang.Object)
872 public void setCurrentRepositorySession(Object repoSession) throws Exception {
873 if (repoSession == null) {
874 String errMsg = "Setting a service context's repository session to null is not allowed.";
875 logger.error(errMsg);
876 throw new Exception(errMsg);
877 } else if (currentRepositorySession != null && currentRepositorySession != repoSession) {
878 String errMsg = "The current service context's repository session was replaced. This may cause unexpected behavior and/or data loss.";
879 logger.error(errMsg);
880 throw new Exception(errMsg);
883 currentRepositorySession = repoSession;
884 this.currentRepoSesssionRefCount++;
888 public void clearCurrentRepositorySession() {
889 if (this.currentRepoSesssionRefCount > 0) {
890 currentRepoSesssionRefCount--;
893 if (currentRepoSesssionRefCount == 0) {
894 this.currentRepositorySession = null;
897 if (currentRepoSesssionRefCount < 0) {
898 throw new RuntimeException("Attempted to clear/close a repository session that has already been cleared/closed.");
903 public Object getCurrentRepositorySession() {
904 // TODO Auto-generated method stub
905 return currentRepositorySession;
909 public RepositoryDomainType getRepositoryDomain() {
910 return repositoryDomain;
914 public void setRepositoryDomain(RepositoryDomainType repositoryDomain) {
915 this.repositoryDomain = repositoryDomain;
919 * Check for a query parameter that indicates if we should force a sync even if the revision numbers indicate otherwise.
923 public boolean shouldForceSync() {
924 boolean forceSync = false;
926 MultivaluedMap<String, String> queryParams = getQueryParams();
927 String paramValue = queryParams.getFirst(IClientQueryParams.FORCE_SYCN);
928 if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.TRUE.toString())) { // Find our if the caller wants us to force refname updates
930 } else if (paramValue != null && paramValue.equals(Long.toString(1))) {