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.TenantBindingType;
45 import org.collectionspace.services.common.types.PropertyItemType;
46 import org.collectionspace.services.common.types.PropertyType;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 * AbstractServiceContext
53 * $LastChangedRevision: $
68 public abstract class AbstractServiceContextImpl<IT, OT>
69 implements ServiceContext<IT, OT> {
72 final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
73 /** The properties. */
74 Map<String, Object> properties = new HashMap<String, Object>();
75 /** The object part map. */
76 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
77 /** The service binding. */
78 private ServiceBindingType serviceBinding;
79 /** The tenant binding. */
80 private TenantBindingType tenantBinding;
81 /** The override document type. */
82 private String overrideDocumentType = null;
83 /** The val handlers. */
84 private List<ValidatorHandler> valHandlers = null;
85 /** The doc handler. */
86 private DocumentHandler docHandler = null;
87 /** security context */
88 private SecurityContext securityContext;
91 * Instantiates a new abstract service context impl.
93 private AbstractServiceContextImpl() {
94 // private constructor for singleton pattern
97 // request query params
98 /** The query params. */
99 private MultivaluedMap<String, String> queryParams;
102 * Instantiates a new abstract service context impl.
104 * @param serviceName the service name
106 * @throws UnauthorizedException the unauthorized exception
108 protected AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
110 //establish security context
111 securityContext = new SecurityContextImpl();
112 //make sure tenant context exists
113 checkTenantContext();
115 //retrieve service bindings
116 TenantBindingConfigReaderImpl tReader =
117 ServiceMain.getInstance().getTenantBindingConfigReader();
118 String tenantId = securityContext.getCurrentTenantId();
119 tenantBinding = tReader.getTenantBinding(tenantId);
120 if (tenantBinding == null) {
121 String msg = "No tenant binding found for tenantId=" + tenantId
122 + " while processing request for service= " + serviceName;
124 throw new IllegalStateException(msg);
126 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
127 if (serviceBinding == null) {
128 String msg = "No service binding found while processing request for "
129 + serviceName + " for tenant id=" + getTenantId()
130 + " name=" + getTenantName();
132 throw new IllegalStateException(msg);
134 if (logger.isDebugEnabled()) {
135 logger.debug("tenantId=" + tenantId
136 + " service binding=" + serviceBinding.getName());
141 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
144 public String getCommonPartLabel() {
145 return getCommonPartLabel(getServiceName());
149 * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel(java.lang.String)
151 public String getCommonPartLabel(String schemaName) {
152 return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
156 * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
159 public Map<String, ObjectPartType> getPartsMetadata() {
160 if (objectPartMap.size() != 0) {
161 return objectPartMap;
163 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
164 return objectPartMap;
168 * Gets the properties for part.
170 * @param partLabel the part label
172 * @return the properties for part
174 public List<PropertyItemType> getPropertiesForPart(String partLabel) {
175 Map<String, ObjectPartType> partMap = getPartsMetadata();
176 ObjectPartType part = partMap.get(partLabel);
178 throw new RuntimeException("No such part found: " + partLabel);
180 List<PropertyType> propNodeList = part.getProperties();
181 return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
185 * @param partLabel The name of the scehma part to search in
186 * @param propName The name of the property (or properties) to find
187 * @param qualified Whether the returned values should be qualified with the
188 * partLabel. This is when the property values are schema field references.
189 * @return List of property values for the matched property on the named schema part.
191 public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
192 List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
193 return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
194 (qualified ? (partLabel + ":") : null));
198 * @param propName The name of the property (or properties) to find
199 * @param qualified Whether the returned values should be qualified with the
200 * partLabel. This is when the property values are schema field references.
201 * @return List of property values for the matched property on any schema part.
203 public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
204 return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
208 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
210 public String getServiceBindingPropertyValue(String propName) {
211 return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
215 * Gets the common part properties.
217 * @return the common part properties
219 public List<PropertyItemType> getCommonPartProperties() {
220 return getPropertiesForPart(getCommonPartLabel());
224 * @param propName The name of the property (or properties) to find
225 * @param qualified Whether the returned values should be qualified with the
226 * partLabel. This is when the property values are schema field references.
227 * @return List of property values for the matched property on the common schema part.
229 public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
230 return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
234 * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
237 public String getQualifiedServiceName() {
238 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
242 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
245 public String getRepositoryClientName() {
246 if (serviceBinding.getRepositoryClient() == null) {
249 return serviceBinding.getRepositoryClient().trim();
253 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
256 public ClientType getRepositoryClientType() {
257 //assumption: there is only one repository client configured
258 return ServiceMain.getInstance().getClientType();
262 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
265 public String getRepositoryDomainName() {
266 return tenantBinding.getRepositoryDomain();
270 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
273 public String getRepositoryWorkspaceId() {
274 TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
275 return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
279 * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
282 public String getRepositoryWorkspaceName() {
283 //service name is workspace name by convention
284 return serviceBinding.getName();
288 * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
291 public ServiceBindingType getServiceBinding() {
292 return serviceBinding;
296 * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
299 public String getServiceName() {
300 return serviceBinding.getName();
304 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
307 public String getDocumentType() {
308 // If they have not overridden the setting, use the type of the service
310 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
314 * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
317 public void setDocumentType(String docType) {
318 overrideDocumentType = docType;
322 * @see org.collectionspace.services.common.context.ServiceContext#getSecurityContext()
325 public SecurityContext getSecurityContext() {
326 return securityContext;
330 * @see org.collectionspace.services.common.context.ServiceContext#getUserId()
333 public String getUserId() {
334 return securityContext.getUserId();
338 * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
341 public String getTenantId() {
342 return securityContext.getCurrentTenantId();
346 * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
349 public String getTenantName() {
350 return securityContext.getCurrentTenantName();
354 * @see org.collectionspace.services.common.context.ServiceContext#getInput()
357 public abstract IT getInput();
360 * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
363 public abstract void setInput(IT input);
366 * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
369 public abstract OT getOutput();
372 * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
375 public abstract void setOutput(OT output);
378 * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
381 public Map<String, Object> getProperties() {
386 * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
389 public void setProperties(Map<String, Object> props) {
390 properties.putAll(props);
394 * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
396 public Object getProperty(String name) {
397 return properties.get(name);
401 * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
403 public void setProperty(String name, Object o) {
404 properties.put(name, o);
408 * checkTenantContext makss sure tenant context exists
412 * @throws UnauthorizedException the unauthorized exception
414 private void checkTenantContext() throws UnauthorizedException {
416 String tenantId = securityContext.getCurrentTenantId();
417 if (tenantId == null) {
418 String msg = "Could not find tenant context";
420 throw new UnauthorizedException(msg);
425 * Creates the document handler instance.
427 * @return the document handler
429 * @throws Exception the exception
431 private DocumentHandler createDocumentHandlerInstance() throws Exception {
432 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
433 Class<?> c = tccl.loadClass(getDocumentHandlerClass());
434 if (DocumentHandler.class.isAssignableFrom(c)) {
435 docHandler = (DocumentHandler) c.newInstance();
437 throw new IllegalArgumentException("Not of type "
438 + DocumentHandler.class.getCanonicalName());
441 // create a default document filter with pagination if the context
442 // was created with query params
444 docHandler.setServiceContext(this);
445 DocumentFilter docFilter = docHandler.createDocumentFilter();
446 docFilter.setPagination(this.getQueryParams());
447 docHandler.setDocumentFilter(docFilter);
453 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
456 public DocumentHandler getDocumentHandler() throws Exception {
457 DocumentHandler result = docHandler;
458 // create a new instance if one does not yet exist
459 if (result == null) {
460 result = createDocumentHandlerInstance();
466 * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
469 public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
470 DocumentHandler result = getDocumentHandler();
471 DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
472 documentFilter.setPagination(queryParams);
477 * Gets the document handler class.
479 * @return the document handler class
481 private String getDocumentHandlerClass() {
482 if (serviceBinding.getDocumentHandler() == null
483 || serviceBinding.getDocumentHandler().isEmpty()) {
484 String msg = "Missing documentHandler in service binding for "
485 + getServiceName() + " for tenant id=" + getTenantId()
486 + " name=" + getTenantName();
488 throw new IllegalStateException(msg);
490 return serviceBinding.getDocumentHandler().trim();
494 * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
497 public List<ValidatorHandler> getValidatorHandlers() throws Exception {
498 if (valHandlers != null) {
501 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
502 List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
503 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
504 for (String clazz : handlerClazzes) {
505 clazz = clazz.trim();
506 Class<?> c = tccl.loadClass(clazz);
507 if (ValidatorHandler.class.isAssignableFrom(c)) {
508 handlers.add((ValidatorHandler) c.newInstance());
511 valHandlers = handlers;
516 * @see java.lang.Object#toString()
519 public String toString() {
520 StringBuilder msg = new StringBuilder();
521 msg.append("AbstractServiceContext [");
522 msg.append("service name=" + serviceBinding.getName() + " ");
523 msg.append("service version=" + serviceBinding.getVersion() + " ");
524 msg.append("tenant id=" + tenantBinding.getId() + " ");
525 msg.append("tenant name=" + tenantBinding.getName() + " ");
526 msg.append(tenantBinding.getDisplayName() + " ");
527 msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
528 for (Map.Entry<String, Object> entry : properties.entrySet()) {
529 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
532 return msg.toString();
536 * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
539 public MultivaluedMap<String, String> getQueryParams() {
540 return this.queryParams;
544 * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
547 public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
548 this.queryParams = theQueryParams;