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);
600 // The docHandler for a Service can be null, but usually is not.
602 if (docHandler != null) {
604 // Create a default document filter
606 docHandler.setServiceContext(this);
607 DocumentFilter docFilter = docHandler.createDocumentFilter();
609 // If the context was created with query parameters,
610 // reflect the values of those parameters in the document filter
611 // to specify sort ordering, pagination, etc.
613 MultivaluedMap<String, String> queryParameters = this.getQueryParams();
614 if (queryParameters != null) {
615 docFilter.setSortOrder(queryParameters);
616 docFilter.setPagination(queryParameters);
617 String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
618 if (workflowWhereClause != null) {
619 docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
623 docHandler.setDocumentFilter(docFilter);
630 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
633 public DocumentHandler getDocumentHandler() throws Exception {
634 DocumentHandler result = docHandler;
635 // create a new instance if one does not yet exist
636 if (result == null) {
637 result = createDocumentHandlerInstance();
643 public void setDocumentHandler(DocumentHandler handler) throws Exception {
644 if (handler != null) {
645 docHandler = handler;
650 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
653 public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
654 DocumentHandler result = getDocumentHandler();
655 DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
656 documentFilter.setPagination(queryParams);
661 * If this element is set in the service binding then use it otherwise
662 * assume that asserts are NOT disabled.
664 private boolean disableValidationAsserts() {
666 Boolean disableAsserts = getServiceBinding().isDisableAsserts();
667 result = (disableAsserts != null) ? disableAsserts : false;
672 * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
675 public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
676 if (valHandlers != null) {
679 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
680 List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
681 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
682 for (String clazz : handlerClazzes) {
683 clazz = clazz.trim();
685 Class<?> c = tccl.loadClass(clazz);
686 if (disableValidationAsserts() == false) {
687 // enable validation assertions
688 tccl.setClassAssertionStatus(clazz, true);
690 if (ValidatorHandler.class.isAssignableFrom(c)) {
691 handlers.add((ValidatorHandler) c.newInstance());
693 } catch (ClassNotFoundException e) {
694 String msg = String.format("Missing document validation handler: '%s'.", clazz);
696 logger.trace(msg, e);
699 valHandlers = handlers;
704 * If one doesn't already exist, use the default properties filename to load a set of properties that
705 * will be used to create an HTTP client to a CollectionSpace instance.
708 public AuthorityClient getClient() throws Exception {
709 AuthorityClient result = authorityClient;
711 if (authorityClient == null) {
712 result = authorityClient = getClient(CollectionSpaceClient.DEFAULT_CLIENT_PROPERTIES_FILENAME);
719 * Use the properties filename passed in to load the URL and credentials that will be used
720 * to create a new HTTP client.
722 * Never uses or resets the this.authorityClient member. Always creates a new HTTP client using
723 * the loaded properties.
726 * @see org.collectionspace.services.common.context.ServiceContext#getClient(java.lang.String)
729 public AuthorityClient getClient(String clientPropertiesFilename) throws Exception {
730 AuthorityClient result = null;
732 Properties inProperties = Tools.loadProperties(clientPropertiesFilename, true);
733 result = getClient(inProperties);
738 public AuthorityClient getClient(Properties inProperties) throws Exception {
739 AuthorityClient result = null;
741 String authorityClientClazz = getServiceBinding().getClientHandler();
742 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
743 authorityClientClazz = authorityClientClazz.trim();
745 Class<?> c = tccl.loadClass(authorityClientClazz);
746 if (AuthorityClient.class.isAssignableFrom(c)) {
747 result = authorityClient = ((AuthorityClient) c.newInstance());
748 result.setClientProperties(inProperties);
750 logger.error(String.format("The service binding clientHandler class '%s' for '%s' service was not of type AuthorityClient.",
751 authorityClientClazz, this.getServiceName()));
753 } catch (ClassNotFoundException e) {
754 String msg = String.format("Missing document validation handler: '%s'.", authorityClientClazz);
756 logger.trace(msg, e);
763 public AuthorityClient getClient(RemoteClientConfig remoteClientConfig) throws Exception {
764 AuthorityClient result = null;
766 Properties properties = new Properties();
767 properties.setProperty(AuthorityClient.URL_PROPERTY, remoteClientConfig.getUrl());
768 properties.setProperty(AuthorityClient.USER_PROPERTY, remoteClientConfig.getUser());
769 properties.setProperty(AuthorityClient.PASSWORD_PROPERTY, remoteClientConfig.getPassword());
770 properties.setProperty(AuthorityClient.SSL_PROPERTY, remoteClientConfig.getSsl());
771 properties.setProperty(AuthorityClient.AUTH_PROPERTY, remoteClientConfig.getAuth());
774 String tenantId = remoteClientConfig.getTenantId();
775 if (tenantId != null) {
776 properties.setProperty(AuthorityClient.TENANT_ID_PROPERTY, tenantId);
778 String tenantName = remoteClientConfig.getTenantName();
779 if (tenantName != null) {
780 properties.setProperty(AuthorityClient.TENANT_NAME_PROPERTY, tenantName);
783 result = getClient(properties);
789 public void addValidatorHandler(ValidatorHandler<IT, OT> validator) throws Exception {
790 if (valHandlers == null) {
791 valHandlers = new ArrayList<ValidatorHandler<IT, OT>>();
793 valHandlers.add(validator);
797 * @see java.lang.Object#toString()
800 public String toString() {
801 StringBuilder msg = new StringBuilder();
802 msg.append("AbstractServiceContext [");
803 msg.append("service name=" + serviceBinding.getName() + " ");
804 msg.append("service version=" + serviceBinding.getVersion() + " ");
805 msg.append("tenant id=" + tenantBinding.getId() + " ");
806 msg.append("tenant name=" + tenantBinding.getName() + " ");
807 msg.append(tenantBinding.getDisplayName() + " ");
808 if (repositoryDomain != null) {
809 msg.append("tenant repository domain=" + repositoryDomain.getName());
811 for (Map.Entry<String, Object> entry : properties.entrySet()) {
812 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
815 return msg.toString();
819 * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
821 * When we first created these services, the RESTEasy query parameters used to be a modifiable map. That changed in a
822 * more recent version of RESTEasy, so we need to make a copy of the params into a modifiable map and return it instead.
825 public MultivaluedMap<String, String> getQueryParams() {
827 if (queryParams == null){
828 if (this.uriInfo != null){
829 queryParams = this.uriInfo.getQueryParameters();
832 if (queryParams == null){
833 queryParams = new org.jboss.resteasy.specimpl.MultivaluedMapImpl<String,String>();
835 return this.queryParams;
839 public MultivaluedMap<String, String> getQueryParamsPtr() {
840 return this.queryParams;
844 * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
847 public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
848 this.queryParams = theQueryParams;
852 public void setUriInfo(UriInfo ui){
857 public UriInfo getUriInfo() {
862 public Request getRequestInfo() {
863 return this.requestInfo;
867 public void setRequestInfo(Request requestInfo) {
868 this.requestInfo = requestInfo;
872 * We expect the 'currentRepositorySession' member to be set only once per instance. Also, we expect only one open repository session
873 * per HTTP request. We'll log an error if we see more than one attempt to set a service context's current repo session.
875 * @see org.collectionspace.services.common.context.ServiceContext#setCurrentRepositorySession(java.lang.Object)
878 public void setCurrentRepositorySession(Object repoSession) throws Exception {
879 if (repoSession == null) {
880 String errMsg = "Setting a service context's repository session to null is not allowed.";
881 logger.error(errMsg);
882 throw new Exception(errMsg);
883 } else if (currentRepositorySession != null && currentRepositorySession != repoSession) {
884 String errMsg = "The current service context's repository session was replaced. This may cause unexpected behavior and/or data loss.";
885 logger.error(errMsg);
886 throw new Exception(errMsg);
889 currentRepositorySession = repoSession;
890 this.currentRepoSesssionRefCount++;
894 public void clearCurrentRepositorySession() {
895 if (this.currentRepoSesssionRefCount > 0) {
896 currentRepoSesssionRefCount--;
899 if (currentRepoSesssionRefCount == 0) {
900 this.currentRepositorySession = null;
903 if (currentRepoSesssionRefCount < 0) {
904 throw new RuntimeException("Attempted to clear/close a repository session that has already been cleared/closed.");
909 public Object getCurrentRepositorySession() {
910 // TODO Auto-generated method stub
911 return currentRepositorySession;
915 public RepositoryDomainType getRepositoryDomain() {
916 return repositoryDomain;
920 public void setRepositoryDomain(RepositoryDomainType repositoryDomain) {
921 this.repositoryDomain = repositoryDomain;
925 * Check for a query parameter that indicates if we should force a sync even if the revision numbers indicate otherwise.
929 public boolean shouldForceSync() {
930 boolean forceSync = false;
932 MultivaluedMap<String, String> queryParams = getQueryParams();
933 String paramValue = queryParams.getFirst(IClientQueryParams.FORCE_SYCN);
934 if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.TRUE.toString())) { // Find our if the caller wants us to force refname updates
936 } else if (paramValue != null && paramValue.equals(Long.toString(1))) {