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 javax.ws.rs.core.MultivaluedMap;
31 import javax.ws.rs.core.UriInfo;
33 import org.collectionspace.services.client.IQueryManager;
34 import org.collectionspace.services.client.workflow.WorkflowClient;
35 import org.collectionspace.services.common.ServiceMain;
36 import org.collectionspace.services.common.config.PropertyItemUtils;
37 import org.collectionspace.services.common.config.ServiceConfigUtils;
38 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
39 import org.collectionspace.services.common.document.DocumentHandler;
40 import org.collectionspace.services.common.document.DocumentFilter;
41 import org.collectionspace.services.common.document.ValidatorHandler;
42 import org.collectionspace.services.common.security.SecurityContext;
43 import org.collectionspace.services.common.security.SecurityContextImpl;
44 import org.collectionspace.services.common.security.UnauthorizedException;
45 import org.collectionspace.services.config.ClientType;
46 import org.collectionspace.services.config.service.ObjectPartType;
47 import org.collectionspace.services.config.service.ServiceBindingType;
48 import org.collectionspace.services.config.tenant.RepositoryDomainType;
49 import org.collectionspace.services.config.tenant.TenantBindingType;
50 import org.collectionspace.services.config.types.PropertyItemType;
51 import org.collectionspace.services.config.types.PropertyType;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 * AbstractServiceContext
58 * $LastChangedRevision: $
73 public abstract class AbstractServiceContextImpl<IT, OT>
74 implements ServiceContext<IT, OT> {
77 final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
78 /** The properties. */
79 Map<String, Object> properties = new HashMap<String, Object>();
80 /** The object part map. */
81 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
82 /** The service binding. */
83 protected ServiceBindingType serviceBinding;
84 /** The tenant binding. */
85 private TenantBindingType tenantBinding;
86 /** repository domain used by the service */
87 private RepositoryDomainType repositoryDomain;
88 /** The override document type. */
89 private String overrideDocumentType = null;
90 /** The val handlers. */
91 private List<ValidatorHandler<IT, OT>> valHandlers = null;
92 /** The doc handler. */
93 private DocumentHandler docHandler = null;
94 /** security context */
95 private SecurityContext securityContext;
97 private UriInfo uriInfo;
100 * Instantiates a new abstract service context impl.
102 private AbstractServiceContextImpl() {
103 // private constructor for singleton pattern
105 // request query params
106 /** The query params. */
107 private MultivaluedMap<String, String> queryParams;
110 * Instantiates a new abstract service context impl.
112 * @param serviceName the service name
114 * @throws UnauthorizedException the unauthorized exception
116 protected AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
118 //establish security context
119 securityContext = new SecurityContextImpl();
120 //make sure tenant context exists
121 checkTenantContext();
123 //retrieve service bindings
124 TenantBindingConfigReaderImpl tReader =
125 ServiceMain.getInstance().getTenantBindingConfigReader();
126 String tenantId = securityContext.getCurrentTenantId();
127 tenantBinding = tReader.getTenantBinding(tenantId);
128 if (tenantBinding == null) {
129 String msg = "No tenant binding found for tenantId=" + tenantId
130 + " while processing request for service= " + serviceName;
132 throw new IllegalStateException(msg);
134 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
135 if (serviceBinding == null) {
136 String msg = "No service binding found while processing request for "
137 + serviceName + " for tenant id=" + getTenantId()
138 + " name=" + getTenantName();
140 throw new IllegalStateException(msg);
142 if (logger.isDebugEnabled()) {
143 logger.debug("tenantId=" + tenantId
144 + " service binding=" + serviceBinding.getName());
146 repositoryDomain = tReader.getRepositoryDomain(tenantId, serviceName);
147 if (repositoryDomain != null) {
148 if (logger.isDebugEnabled()) {
149 logger.debug("tenantId=" + tenantId
150 + " repository doamin=" + repositoryDomain.getName());
156 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
159 public String getCommonPartLabel() {
160 return getCommonPartLabel(getServiceName());
164 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel(java.lang.String)
166 public String getCommonPartLabel(String schemaName) {
167 return schemaName.toLowerCase() + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
171 * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
174 public Map<String, ObjectPartType> getPartsMetadata() {
175 if (objectPartMap.size() != 0) {
176 return objectPartMap;
178 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
179 return objectPartMap;
183 * Gets the properties for part.
185 * @param partLabel the part label
187 * @return the properties for part
189 public List<PropertyItemType> getPropertiesForPart(String partLabel) {
190 Map<String, ObjectPartType> partMap = getPartsMetadata();
191 ObjectPartType part = partMap.get(partLabel);
193 throw new RuntimeException("No such part found: " + partLabel);
195 List<PropertyType> propNodeList = part.getProperties();
196 return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
200 * @param partLabel The name of the scehma part to search in
201 * @param propName The name of the property (or properties) to find
202 * @param qualified Whether the returned values should be qualified with the
203 * partLabel. This is when the property values are schema field references.
204 * @return List of property values for the matched property on the named schema part.
206 public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
207 List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
208 return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
209 (qualified ? (partLabel + ":") : null));
213 * @param propName The name of the property (or properties) to find
214 * @param qualified Whether the returned values should be qualified with the
215 * partLabel. This is when the property values are schema field references.
216 * @return List of property values for the matched property on any schema part.
218 public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
219 return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
223 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
225 public String getServiceBindingPropertyValue(String propName) {
226 return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
230 * Gets the common part properties.
232 * @return the common part properties
234 public List<PropertyItemType> getCommonPartProperties() {
235 return getPropertiesForPart(getCommonPartLabel());
239 * @param propName The name of the property (or properties) to find
240 * @param qualified Whether the returned values should be qualified with the
241 * partLabel. This is when the property values are schema field references.
242 * @return List of property values for the matched property on the common schema part.
244 public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
245 return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
249 * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
252 public String getQualifiedServiceName() {
253 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
257 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
260 public String getRepositoryClientName() {
261 if (repositoryDomain == null) {
264 return repositoryDomain.getRepositoryClient();
268 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
271 public ClientType getRepositoryClientType() {
272 //assumption: there is only one repository client configured
273 return ServiceMain.getInstance().getClientType();
277 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
280 public String getRepositoryDomainName() {
281 if (repositoryDomain == null) {
284 return repositoryDomain.getName();
288 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
291 public String getRepositoryDomainStorageName() {
292 if (repositoryDomain == null) {
295 return repositoryDomain.getStorageName();
299 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
302 public String getRepositoryWorkspaceId() {
303 return ServiceMain.getInstance().getWorkspaceId(getTenantId(), getServiceName());
307 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
310 public String getRepositoryWorkspaceName() {
311 //service name is workspace name by convention
312 return serviceBinding.getName();
316 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
319 public ServiceBindingType getServiceBinding() {
320 return serviceBinding;
324 * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
327 public String getServiceName() {
328 return serviceBinding.getName();
332 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
335 public String getDocumentType() {
336 // If they have not overridden the setting, use the type of the service
338 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
342 public String getTenantQualifiedDoctype(String docType) {
343 // If they have not overridden the setting, use the type of the service
345 String result = ServiceBindingUtils.getTenantQualifiedDocType(this.getTenantId(), docType);
351 public String getTenantQualifiedDoctype() {
352 String docType = (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
353 return getTenantQualifiedDoctype(docType);
357 * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
360 public void setDocumentType(String docType) {
361 overrideDocumentType = docType;
365 * @see org.collectionspace.services.common.context.ServiceContext#getSecurityContext()
368 public SecurityContext getSecurityContext() {
369 return securityContext;
373 * @see org.collectionspace.services.common.context.ServiceContext#getUserId()
376 public String getUserId() {
377 return securityContext.getUserId();
381 * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
384 public String getTenantId() {
385 return securityContext.getCurrentTenantId();
389 * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
392 public String getTenantName() {
393 return securityContext.getCurrentTenantName();
397 * @see org.collectionspace.services.common.context.ServiceContext#getInput()
400 public abstract IT getInput();
403 * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
406 public abstract void setInput(IT input);
409 * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
412 public abstract OT getOutput();
415 * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
418 public abstract void setOutput(OT output);
421 * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
424 public Map<String, Object> getProperties() {
429 * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
432 public void setProperties(Map<String, Object> props) {
433 properties.putAll(props);
437 * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
439 public Object getProperty(String name) {
440 return properties.get(name);
444 * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
446 public void setProperty(String name, Object o) {
447 properties.put(name, o);
451 * checkTenantContext makss sure tenant context exists
455 * @throws UnauthorizedException the unauthorized exception
457 private void checkTenantContext() throws UnauthorizedException {
459 String tenantId = securityContext.getCurrentTenantId();
460 if (tenantId == null) {
461 String msg = "Could not find tenant context";
463 throw new UnauthorizedException(msg);
467 private static String buildWorkflowWhereClause(MultivaluedMap<String, String> queryParams) {
468 String result = null;
470 String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
471 if (includeDeleted != null && includeDeleted.equalsIgnoreCase(Boolean.FALSE.toString())) {
472 result = "ecm:currentLifeCycleState <> 'deleted'";
479 * Creates the document handler instance.
481 * @return the document handler
483 * @throws Exception the exception
485 private DocumentHandler createDocumentHandlerInstance() throws Exception {
486 docHandler = ServiceConfigUtils.createDocumentHandlerInstance(tenantBinding, serviceBinding);
488 // Create a default document filter
490 docHandler.setServiceContext(this);
491 DocumentFilter docFilter = docHandler.createDocumentFilter();
493 // If the context was created with query parameters,
494 // reflect the values of those parameters in the document filter
495 // to specify sort ordering, pagination, etc.
497 if (this.getQueryParams() != null) {
498 docFilter.setSortOrder(this.getQueryParams());
499 docFilter.setPagination(this.getQueryParams());
500 String workflowWhereClause = buildWorkflowWhereClause(queryParams);
501 if (workflowWhereClause != null) {
502 docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
506 docHandler.setDocumentFilter(docFilter);
512 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
515 public DocumentHandler getDocumentHandler() throws Exception {
516 DocumentHandler result = docHandler;
517 // create a new instance if one does not yet exist
518 if (result == null) {
519 result = createDocumentHandlerInstance();
525 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
528 public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
529 DocumentHandler result = getDocumentHandler();
530 DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
531 documentFilter.setPagination(queryParams);
536 * If this element is set in the service binding then use it otherwise
537 * assume that asserts are NOT disabled.
539 private boolean disableValidationAsserts() {
541 Boolean disableAsserts = getServiceBinding().isDisableAsserts();
542 result = (disableAsserts != null) ? disableAsserts : false;
547 * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
550 public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
551 if (valHandlers != null) {
554 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
555 List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
556 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
557 for (String clazz : handlerClazzes) {
558 clazz = clazz.trim();
559 Class<?> c = tccl.loadClass(clazz);
560 if (disableValidationAsserts() == false) {
561 // enable validation assertions
562 tccl.setClassAssertionStatus(clazz, true);
564 if (ValidatorHandler.class.isAssignableFrom(c)) {
565 handlers.add((ValidatorHandler) c.newInstance());
568 valHandlers = handlers;
573 * @see java.lang.Object#toString()
576 public String toString() {
577 StringBuilder msg = new StringBuilder();
578 msg.append("AbstractServiceContext [");
579 msg.append("service name=" + serviceBinding.getName() + " ");
580 msg.append("service version=" + serviceBinding.getVersion() + " ");
581 msg.append("tenant id=" + tenantBinding.getId() + " ");
582 msg.append("tenant name=" + tenantBinding.getName() + " ");
583 msg.append(tenantBinding.getDisplayName() + " ");
584 if (repositoryDomain != null) {
585 msg.append("tenant repository domain=" + repositoryDomain.getName());
587 for (Map.Entry<String, Object> entry : properties.entrySet()) {
588 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
591 return msg.toString();
595 * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
598 public MultivaluedMap<String, String> getQueryParams() {
600 if (queryParams == null){
601 if (this.uriInfo != null){
602 queryParams = this.uriInfo.getQueryParameters();
605 if (queryParams == null){
606 queryParams = new org.jboss.resteasy.specimpl.MultivaluedMapImpl<String,String>();
608 return this.queryParams;
612 public MultivaluedMap<String, String> getQueryParamsPtr() {
613 return this.queryParams;
617 * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
620 public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
621 this.queryParams = theQueryParams;
625 public void setUriInfo(UriInfo ui){
630 public UriInfo getUriInfo(){