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;
32 import org.collectionspace.services.common.ClientType;
33 import org.collectionspace.services.common.ServiceMain;
34 import org.collectionspace.services.common.config.PropertyItemUtils;
35 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
36 import org.collectionspace.services.common.document.DocumentHandler;
37 import org.collectionspace.services.common.document.DocumentFilter;
38 import org.collectionspace.services.common.document.ValidatorHandler;
39 import org.collectionspace.services.common.security.SecurityContext;
40 import org.collectionspace.services.common.security.SecurityContextImpl;
41 import org.collectionspace.services.common.security.UnauthorizedException;
42 import org.collectionspace.services.common.service.ObjectPartType;
43 import org.collectionspace.services.common.service.ServiceBindingType;
44 import org.collectionspace.services.common.tenant.RepositoryDomainType;
45 import org.collectionspace.services.common.tenant.TenantBindingType;
46 import org.collectionspace.services.common.types.PropertyItemType;
47 import org.collectionspace.services.common.types.PropertyType;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
52 * AbstractServiceContext
54 * $LastChangedRevision: $
69 public abstract class AbstractServiceContextImpl<IT, OT>
70 implements ServiceContext<IT, OT> {
73 final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
74 /** The properties. */
75 Map<String, Object> properties = new HashMap<String, Object>();
76 /** The object part map. */
77 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
78 /** The service binding. */
79 protected ServiceBindingType serviceBinding;
80 /** The tenant binding. */
81 private TenantBindingType tenantBinding;
82 /** repository domain used by the service */
83 private RepositoryDomainType repositoryDomain;
84 /** The override document type. */
85 private String overrideDocumentType = null;
86 /** The val handlers. */
87 private List<ValidatorHandler<IT, OT>> valHandlers = null;
88 /** The doc handler. */
89 private DocumentHandler docHandler = null;
90 /** security context */
91 private SecurityContext securityContext;
94 * Instantiates a new abstract service context impl.
96 private AbstractServiceContextImpl() {
97 // private constructor for singleton pattern
99 // request query params
100 /** The query params. */
101 private MultivaluedMap<String, String> queryParams;
104 * Instantiates a new abstract service context impl.
106 * @param serviceName the service name
108 * @throws UnauthorizedException the unauthorized exception
110 protected AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
112 //establish security context
113 securityContext = new SecurityContextImpl();
114 //make sure tenant context exists
115 checkTenantContext();
117 //retrieve service bindings
118 TenantBindingConfigReaderImpl tReader =
119 ServiceMain.getInstance().getTenantBindingConfigReader();
120 String tenantId = securityContext.getCurrentTenantId();
121 tenantBinding = tReader.getTenantBinding(tenantId);
122 if (tenantBinding == null) {
123 String msg = "No tenant binding found for tenantId=" + tenantId
124 + " while processing request for service= " + serviceName;
126 throw new IllegalStateException(msg);
128 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
129 if (serviceBinding == null) {
130 String msg = "No service binding found while processing request for "
131 + serviceName + " for tenant id=" + getTenantId()
132 + " name=" + getTenantName();
134 throw new IllegalStateException(msg);
136 if (logger.isDebugEnabled()) {
137 logger.debug("tenantId=" + tenantId
138 + " service binding=" + serviceBinding.getName());
140 repositoryDomain = tReader.getRepositoryDomain(tenantId, serviceName);
141 if (repositoryDomain != null) {
142 if (logger.isDebugEnabled()) {
143 logger.debug("tenantId=" + tenantId
144 + " repository doamin=" + repositoryDomain.getName());
150 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
153 public String getCommonPartLabel() {
154 return getCommonPartLabel(getServiceName());
158 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel(java.lang.String)
160 public String getCommonPartLabel(String schemaName) {
161 return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
165 * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
168 public Map<String, ObjectPartType> getPartsMetadata() {
169 if (objectPartMap.size() != 0) {
170 return objectPartMap;
172 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
173 return objectPartMap;
177 * Gets the properties for part.
179 * @param partLabel the part label
181 * @return the properties for part
183 public List<PropertyItemType> getPropertiesForPart(String partLabel) {
184 Map<String, ObjectPartType> partMap = getPartsMetadata();
185 ObjectPartType part = partMap.get(partLabel);
187 throw new RuntimeException("No such part found: " + partLabel);
189 List<PropertyType> propNodeList = part.getProperties();
190 return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
194 * @param partLabel The name of the scehma part to search in
195 * @param propName The name of the property (or properties) to find
196 * @param qualified Whether the returned values should be qualified with the
197 * partLabel. This is when the property values are schema field references.
198 * @return List of property values for the matched property on the named schema part.
200 public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
201 List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
202 return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
203 (qualified ? (partLabel + ":") : null));
207 * @param propName The name of the property (or properties) to find
208 * @param qualified Whether the returned values should be qualified with the
209 * partLabel. This is when the property values are schema field references.
210 * @return List of property values for the matched property on any schema part.
212 public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
213 return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
217 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
219 public String getServiceBindingPropertyValue(String propName) {
220 return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
224 * Gets the common part properties.
226 * @return the common part properties
228 public List<PropertyItemType> getCommonPartProperties() {
229 return getPropertiesForPart(getCommonPartLabel());
233 * @param propName The name of the property (or properties) to find
234 * @param qualified Whether the returned values should be qualified with the
235 * partLabel. This is when the property values are schema field references.
236 * @return List of property values for the matched property on the common schema part.
238 public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
239 return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
243 * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
246 public String getQualifiedServiceName() {
247 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
251 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
254 public String getRepositoryClientName() {
255 if (repositoryDomain == null) {
258 return repositoryDomain.getRepositoryClient();
262 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
265 public ClientType getRepositoryClientType() {
266 //assumption: there is only one repository client configured
267 return ServiceMain.getInstance().getClientType();
271 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
274 public String getRepositoryDomainName() {
275 if (repositoryDomain == null) {
278 return repositoryDomain.getName();
282 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
285 public String getRepositoryWorkspaceId() {
286 return ServiceMain.getInstance().getWorkspaceId(getTenantId(), getServiceName());
290 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
293 public String getRepositoryWorkspaceName() {
294 //service name is workspace name by convention
295 return serviceBinding.getName();
299 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
302 public ServiceBindingType getServiceBinding() {
303 return serviceBinding;
307 * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
310 public String getServiceName() {
311 return serviceBinding.getName();
315 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
318 public String getDocumentType() {
319 // If they have not overridden the setting, use the type of the service
321 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
325 * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
328 public void setDocumentType(String docType) {
329 overrideDocumentType = docType;
333 * @see org.collectionspace.services.common.context.ServiceContext#getSecurityContext()
336 public SecurityContext getSecurityContext() {
337 return securityContext;
341 * @see org.collectionspace.services.common.context.ServiceContext#getUserId()
344 public String getUserId() {
345 return securityContext.getUserId();
349 * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
352 public String getTenantId() {
353 return securityContext.getCurrentTenantId();
357 * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
360 public String getTenantName() {
361 return securityContext.getCurrentTenantName();
365 * @see org.collectionspace.services.common.context.ServiceContext#getInput()
368 public abstract IT getInput();
371 * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
374 public abstract void setInput(IT input);
377 * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
380 public abstract OT getOutput();
383 * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
386 public abstract void setOutput(OT output);
389 * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
392 public Map<String, Object> getProperties() {
397 * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
400 public void setProperties(Map<String, Object> props) {
401 properties.putAll(props);
405 * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
407 public Object getProperty(String name) {
408 return properties.get(name);
412 * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
414 public void setProperty(String name, Object o) {
415 properties.put(name, o);
419 * checkTenantContext makss sure tenant context exists
423 * @throws UnauthorizedException the unauthorized exception
425 private void checkTenantContext() throws UnauthorizedException {
427 String tenantId = securityContext.getCurrentTenantId();
428 if (tenantId == null) {
429 String msg = "Could not find tenant context";
431 throw new UnauthorizedException(msg);
436 * Creates the document handler instance.
438 * @return the document handler
440 * @throws Exception the exception
442 private DocumentHandler createDocumentHandlerInstance() throws Exception {
443 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
444 Class<?> c = tccl.loadClass(getDocumentHandlerClass());
445 if (DocumentHandler.class.isAssignableFrom(c)) {
446 docHandler = (DocumentHandler) c.newInstance();
448 throw new IllegalArgumentException("Not of type "
449 + DocumentHandler.class.getCanonicalName());
452 // Create a default document filter
454 docHandler.setServiceContext(this);
455 DocumentFilter docFilter = docHandler.createDocumentFilter();
457 // If the context was created with query parameters,
458 // reflect the values of those parameters in the document filter
459 // to specify sort ordering, pagination, etc.
461 if (this.getQueryParams() != null) {
462 docFilter.setSortOrder(this.getQueryParams());
463 docFilter.setPagination(this.getQueryParams());
465 docHandler.setDocumentFilter(docFilter);
471 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
474 public DocumentHandler getDocumentHandler() throws Exception {
475 DocumentHandler result = docHandler;
476 // create a new instance if one does not yet exist
477 if (result == null) {
478 result = createDocumentHandlerInstance();
484 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
487 public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
488 DocumentHandler result = getDocumentHandler();
489 DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
490 documentFilter.setPagination(queryParams);
495 * Gets the document handler class.
497 * @return the document handler class
499 private String getDocumentHandlerClass() {
500 if (serviceBinding.getDocumentHandler() == null
501 || serviceBinding.getDocumentHandler().isEmpty()) {
502 String msg = "Missing documentHandler in service binding for "
503 + getServiceName() + " for tenant id=" + getTenantId()
504 + " name=" + getTenantName();
506 throw new IllegalStateException(msg);
508 return serviceBinding.getDocumentHandler().trim();
512 * If this element is set in the service binding then use it otherwise
513 * assume that asserts are NOT disabled.
515 private boolean disableValidationAsserts() {
517 Boolean disableAsserts = getServiceBinding().isDisableAsserts();
518 result = (disableAsserts != null) ? disableAsserts : false;
523 * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
526 public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
527 if (valHandlers != null) {
530 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
531 List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
532 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
533 for (String clazz : handlerClazzes) {
534 clazz = clazz.trim();
535 Class<?> c = tccl.loadClass(clazz);
536 if (disableValidationAsserts() == false) {
537 // enable validation assertions
538 tccl.setClassAssertionStatus(clazz, true);
540 if (ValidatorHandler.class.isAssignableFrom(c)) {
541 handlers.add((ValidatorHandler) c.newInstance());
544 valHandlers = handlers;
549 * @see java.lang.Object#toString()
552 public String toString() {
553 StringBuilder msg = new StringBuilder();
554 msg.append("AbstractServiceContext [");
555 msg.append("service name=" + serviceBinding.getName() + " ");
556 msg.append("service version=" + serviceBinding.getVersion() + " ");
557 msg.append("tenant id=" + tenantBinding.getId() + " ");
558 msg.append("tenant name=" + tenantBinding.getName() + " ");
559 msg.append(tenantBinding.getDisplayName() + " ");
560 if (repositoryDomain != null) {
561 msg.append("tenant repository domain=" + repositoryDomain.getName());
563 for (Map.Entry<String, Object> entry : properties.entrySet()) {
564 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
567 return msg.toString();
571 * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
574 public MultivaluedMap<String, String> getQueryParams() {
575 return this.queryParams;
579 * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
582 public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
583 this.queryParams = theQueryParams;