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.authentication.AuthN;
34 import org.collectionspace.services.common.ClientType;
35 import org.collectionspace.services.common.ServiceMain;
36 import org.collectionspace.services.common.config.PropertyItemUtils;
37 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
38 import org.collectionspace.services.common.document.DocumentHandler;
39 import org.collectionspace.services.common.document.DocumentFilter;
40 import org.collectionspace.services.common.document.ValidatorHandler;
41 import org.collectionspace.services.common.security.SecurityContext;
42 import org.collectionspace.services.common.security.SecurityContextImpl;
43 import org.collectionspace.services.common.security.UnauthorizedException;
44 import org.collectionspace.services.common.service.ObjectPartType;
45 import org.collectionspace.services.common.service.ServiceBindingType;
46 import org.collectionspace.services.common.tenant.TenantBindingType;
47 import org.collectionspace.services.common.types.PropertyItemType;
48 import org.collectionspace.services.common.types.PropertyType;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * AbstractServiceContext
55 * $LastChangedRevision: $
70 public abstract class AbstractServiceContextImpl<IT, OT>
71 implements ServiceContext<IT, OT> {
74 final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
75 /** The properties. */
76 Map<String, Object> properties = new HashMap<String, Object>();
77 /** The object part map. */
78 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
79 /** The service binding. */
80 private ServiceBindingType serviceBinding;
81 /** The tenant binding. */
82 private TenantBindingType tenantBinding;
83 /** The override document type. */
84 private String overrideDocumentType = null;
85 /** The val handlers. */
86 private List<ValidatorHandler> valHandlers = null;
87 /** The doc handler. */
88 private DocumentHandler docHandler = null;
89 /** security context */
90 private SecurityContext securityContext;
92 private AbstractServiceContextImpl() {
93 } // private constructor for singleton pattern
94 // request query params
95 private MultivaluedMap<String, String> queryParams;
98 * Instantiates a new abstract service context impl.
100 * @param serviceName the service name
102 * @throws UnauthorizedException the unauthorized exception
104 protected AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
106 //establish security context
107 securityContext = new SecurityContextImpl();
108 //make sure tenant context exists
109 checkTenantContext();
111 //retrieve service bindings
112 TenantBindingConfigReaderImpl tReader =
113 ServiceMain.getInstance().getTenantBindingConfigReader();
114 String tenantId = securityContext.getCurrentTenantId();
115 tenantBinding = tReader.getTenantBinding(tenantId);
116 if (tenantBinding == null) {
117 String msg = "No tenant binding found for tenantId=" + tenantId
118 + " while processing request for service= " + serviceName;
120 throw new IllegalStateException(msg);
122 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
123 if (serviceBinding == null) {
124 String msg = "No service binding found while processing request for "
125 + serviceName + " for tenant id=" + getTenantId()
126 + " name=" + getTenantName();
128 throw new IllegalStateException(msg);
130 if (logger.isDebugEnabled()) {
131 logger.debug("tenantId=" + tenantId
132 + " service binding=" + serviceBinding.getName());
137 * getCommonPartLabel get common part label
141 public String getCommonPartLabel() {
142 return getCommonPartLabel(getServiceName());
146 * getCommonPartLabel get common part label
149 public String getCommonPartLabel(String schemaName) {
150 return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
154 * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
157 public Map<String, ObjectPartType> getPartsMetadata() {
158 if (objectPartMap.size() != 0) {
159 return objectPartMap;
161 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
162 return objectPartMap;
166 * Gets the properties for part.
168 * @param partLabel the part label
170 * @return the properties for part
172 public List<PropertyItemType> getPropertiesForPart(String partLabel) {
173 Map<String, ObjectPartType> partMap = getPartsMetadata();
174 ObjectPartType part = partMap.get(partLabel);
176 throw new RuntimeException("No such part found: " + partLabel);
178 List<PropertyType> propNodeList = part.getProperties();
179 return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
183 * @param partLabel The name of the scehma part to search in
184 * @param propName The name of the property (or properties) to find
185 * @param qualified Whether the returned values should be qualified with the
186 * partLabel. This is when the property values are schema field references.
187 * @return List of property values for the matched property on the named schema part.
189 public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
190 List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
191 return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
192 (qualified ? (partLabel + ":") : null));
196 * @param propName The name of the property (or properties) to find
197 * @param qualified Whether the returned values should be qualified with the
198 * partLabel. This is when the property values are schema field references.
199 * @return List of property values for the matched property on any schema part.
201 public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
202 return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
206 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
208 public String getServiceBindingPropertyValue(String propName) {
209 return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
213 * Gets the common part properties.
215 * @return the common part properties
217 public List<PropertyItemType> getCommonPartProperties() {
218 return getPropertiesForPart(getCommonPartLabel());
222 * @param propName The name of the property (or properties) to find
223 * @param qualified Whether the returned values should be qualified with the
224 * partLabel. This is when the property values are schema field references.
225 * @return List of property values for the matched property on the common schema part.
227 public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
228 return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
232 * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
235 public String getQualifiedServiceName() {
236 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
240 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
243 public String getRepositoryClientName() {
244 if (serviceBinding.getRepositoryClient() == null) {
247 return serviceBinding.getRepositoryClient().trim();
251 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
254 public ClientType getRepositoryClientType() {
255 //assumption: there is only one repository client configured
256 return ServiceMain.getInstance().getClientType();
260 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
263 public String getRepositoryDomainName() {
264 return tenantBinding.getRepositoryDomain();
268 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
271 public String getRepositoryWorkspaceId() {
272 TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
273 return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
277 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
280 public String getRepositoryWorkspaceName() {
281 //service name is workspace name by convention
282 return serviceBinding.getName();
286 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
289 public ServiceBindingType getServiceBinding() {
290 return serviceBinding;
294 * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
297 public String getServiceName() {
298 return serviceBinding.getName();
302 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
305 public String getDocumentType() {
306 // If they have not overridden the setting, use the type of the service
308 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
312 * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
315 public void setDocumentType(String docType) {
316 overrideDocumentType = docType;
320 public SecurityContext getSecurityContext() {
321 return securityContext;
325 public String getUserId() {
326 return securityContext.getUserId();
330 * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
333 public String getTenantId() {
334 return securityContext.getCurrentTenantId();
338 * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
341 public String getTenantName() {
342 return securityContext.getCurrentTenantName();
346 * @see org.collectionspace.services.common.context.ServiceContext#getInput()
349 public abstract IT getInput();
352 * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
355 public abstract void setInput(IT input);
358 * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
361 public abstract OT getOutput();
364 * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
367 public abstract void setOutput(OT output);
370 * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
373 public Map<String, Object> getProperties() {
378 * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
381 public void setProperties(Map<String, Object> props) {
382 properties.putAll(props);
386 * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
388 public Object getProperty(String name) {
389 return properties.get(name);
393 * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
395 public void setProperty(String name, Object o) {
396 properties.put(name, o);
400 * checkTenantContext makss sure tenant context exists
404 * @throws UnauthorizedException the unauthorized exception
406 private void checkTenantContext() throws UnauthorizedException {
408 String tenantId = securityContext.getCurrentTenantId();
409 if (tenantId == null) {
410 String msg = "Could not find tenant context";
412 throw new UnauthorizedException(msg);
417 * Creates the document handler instance.
419 * @return the document handler
421 * @throws Exception the exception
423 private DocumentHandler createDocumentHandlerInstance() throws Exception {
424 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
425 Class c = tccl.loadClass(getDocumentHandlerClass());
426 if (DocumentHandler.class.isAssignableFrom(c)) {
427 docHandler = (DocumentHandler) c.newInstance();
429 throw new IllegalArgumentException("Not of type "
430 + DocumentHandler.class.getCanonicalName());
433 // create a default document filter with pagination if the context
434 // was created with query params
436 docHandler.setServiceContext(this);
437 DocumentFilter docFilter = docHandler.createDocumentFilter();
438 docFilter.setPagination(this.getQueryParams());
439 docHandler.setDocumentFilter(docFilter);
445 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
448 public DocumentHandler getDocumentHandler() throws Exception {
449 DocumentHandler result = docHandler;
450 // create a new instance if one does not yet exist
451 if (result == null) {
452 result = createDocumentHandlerInstance();
458 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
461 public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
462 DocumentHandler result = getDocumentHandler();
463 DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
464 documentFilter.setPagination(queryParams);
469 * Gets the document handler class.
471 * @return the document handler class
473 private String getDocumentHandlerClass() {
474 if (serviceBinding.getDocumentHandler() == null
475 || serviceBinding.getDocumentHandler().isEmpty()) {
476 String msg = "Missing documentHandler in service binding for "
477 + getServiceName() + " for tenant id=" + getTenantId()
478 + " name=" + getTenantName();
480 throw new IllegalStateException(msg);
482 return serviceBinding.getDocumentHandler().trim();
486 * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
489 public List<ValidatorHandler> getValidatorHandlers() throws Exception {
490 if (valHandlers != null) {
493 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
494 List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
495 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
496 for (String clazz : handlerClazzes) {
497 clazz = clazz.trim();
498 Class c = tccl.loadClass(clazz);
499 if (ValidatorHandler.class.isAssignableFrom(c)) {
500 handlers.add((ValidatorHandler) c.newInstance());
503 valHandlers = handlers;
508 * @see java.lang.Object#toString()
511 public String toString() {
512 StringBuilder msg = new StringBuilder();
513 msg.append("AbstractServiceContext [");
514 msg.append("service name=" + serviceBinding.getName() + " ");
515 msg.append("service version=" + serviceBinding.getVersion() + " ");
516 msg.append("tenant id=" + tenantBinding.getId() + " ");
517 msg.append("tenant name=" + tenantBinding.getName() + " ");
518 msg.append(tenantBinding.getDisplayName() + " ");
519 msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
520 for (Map.Entry<String, Object> entry : properties.entrySet()) {
521 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
524 return msg.toString();
528 public MultivaluedMap<String, String> getQueryParams() {
529 return this.queryParams;
533 public void setQueryParams(MultivaluedMap<String, String> queryParams) {
534 this.queryParams = queryParams;