]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
c1465a2c7283bab071c1dc8b3338d670b06638b1
[tmp/jakarta-migration.git] /
1 /**
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:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
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.
23  */
24 package org.collectionspace.services.common.context;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import javax.ws.rs.core.MultivaluedMap;
31 import javax.ws.rs.core.UriInfo;
32
33 import org.collectionspace.services.client.IQueryManager;
34 import org.collectionspace.services.client.workflow.WorkflowClient;
35 import org.collectionspace.services.common.ClientType;
36 import org.collectionspace.services.common.ServiceMain;
37 import org.collectionspace.services.common.config.PropertyItemUtils;
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.common.service.ObjectPartType;
46 import org.collectionspace.services.common.service.ServiceBindingType;
47 import org.collectionspace.services.common.tenant.RepositoryDomainType;
48 import org.collectionspace.services.common.tenant.TenantBindingType;
49 import org.collectionspace.services.common.types.PropertyItemType;
50 import org.collectionspace.services.common.types.PropertyType;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  * AbstractServiceContext
56  *
57  * $LastChangedRevision: $
58  * $LastChangedDate: $
59  */
60 /**
61  * @author pschmitz
62  *
63  * @param <IT>
64  * @param <OT>
65  */
66 /**
67  * @author pschmitz
68  *
69  * @param <IT>
70  * @param <OT>
71  */
72 public abstract class AbstractServiceContextImpl<IT, OT>
73         implements ServiceContext<IT, OT> {
74
75     /** The logger. */
76     final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
77     /** The properties. */
78     Map<String, Object> properties = new HashMap<String, Object>();
79     /** The object part map. */
80     Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
81     /** The service binding. */
82     protected ServiceBindingType serviceBinding;
83     /** The tenant binding. */
84     private TenantBindingType tenantBinding;
85     /** repository domain used by the service */
86     private RepositoryDomainType repositoryDomain;
87     /** The override document type. */
88     private String overrideDocumentType = null;
89     /** The val handlers. */
90     private List<ValidatorHandler<IT, OT>> valHandlers = null;
91     /** The doc handler. */
92     private DocumentHandler docHandler = null;
93     /** security context */
94     private SecurityContext securityContext;
95
96     private UriInfo uriInfo;
97
98     /**
99      * Instantiates a new abstract service context impl.
100      */
101     private AbstractServiceContextImpl() {
102         // private constructor for singleton pattern
103     }
104     // request query params
105     /** The query params. */
106     private MultivaluedMap<String, String> queryParams;
107
108     /**
109      * Instantiates a new abstract service context impl.
110      * 
111      * @param serviceName the service name
112      * 
113      * @throws UnauthorizedException the unauthorized exception
114      */
115     protected AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
116
117         //establish security context
118         securityContext = new SecurityContextImpl();
119         //make sure tenant context exists
120         checkTenantContext();
121
122         //retrieve service bindings
123         TenantBindingConfigReaderImpl tReader =
124                 ServiceMain.getInstance().getTenantBindingConfigReader();
125         String tenantId = securityContext.getCurrentTenantId();
126         tenantBinding = tReader.getTenantBinding(tenantId);
127         if (tenantBinding == null) {
128             String msg = "No tenant binding found for tenantId=" + tenantId
129                     + " while processing request for service= " + serviceName;
130             logger.error(msg);
131             throw new IllegalStateException(msg);
132         }
133         serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
134         if (serviceBinding == null) {
135             String msg = "No service binding found while processing request for "
136                     + serviceName + " for tenant id=" + getTenantId()
137                     + " name=" + getTenantName();
138             logger.error(msg);
139             throw new IllegalStateException(msg);
140         }
141         if (logger.isDebugEnabled()) {
142             logger.debug("tenantId=" + tenantId
143                     + " service binding=" + serviceBinding.getName());
144         }
145         repositoryDomain = tReader.getRepositoryDomain(tenantId, serviceName);
146         if (repositoryDomain != null) {
147             if (logger.isDebugEnabled()) {
148                 logger.debug("tenantId=" + tenantId
149                         + " repository doamin=" + repositoryDomain.getName());
150             }
151         }
152     }
153
154     /* (non-Javadoc)
155      * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
156      */
157     @Override
158     public String getCommonPartLabel() {
159         return getCommonPartLabel(getServiceName());
160     }
161
162     /* (non-Javadoc)
163      * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel(java.lang.String)
164      */
165     public String getCommonPartLabel(String schemaName) {
166         return schemaName.toLowerCase() + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
167     }
168
169     /* (non-Javadoc)
170      * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
171      */
172     @Override
173     public Map<String, ObjectPartType> getPartsMetadata() {
174         if (objectPartMap.size() != 0) {
175             return objectPartMap;
176         }
177         ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
178         return objectPartMap;
179     }
180
181     /**
182      * Gets the properties for part.
183      * 
184      * @param partLabel the part label
185      * 
186      * @return the properties for part
187      */
188     public List<PropertyItemType> getPropertiesForPart(String partLabel) {
189         Map<String, ObjectPartType> partMap = getPartsMetadata();
190         ObjectPartType part = partMap.get(partLabel);
191         if (part == null) {
192             throw new RuntimeException("No such part found: " + partLabel);
193         }
194         List<PropertyType> propNodeList = part.getProperties();
195         return propNodeList.isEmpty() ? null : propNodeList.get(0).getItem();
196     }
197
198     /**
199      * @param partLabel The name of the scehma part to search in
200      * @param propName The name of the property (or properties) to find
201      * @param qualified Whether the returned values should be qualified with the
202      *          partLabel. This is when the property values are schema field references.
203      * @return List of property values for the matched property on the named schema part.
204      */
205     public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
206         List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
207         return PropertyItemUtils.getPropertyValuesByName(allProps, propName,
208                 (qualified ? (partLabel + ":") : null));
209     }
210
211     /**
212      * @param propName The name of the property (or properties) to find
213      * @param qualified Whether the returned values should be qualified with the
214      *          partLabel. This is when the property values are schema field references.
215      * @return List of property values for the matched property on any schema part.
216      */
217     public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
218         return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
219     }
220
221     /* (non-Javadoc)
222      * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
223      */
224     public String getServiceBindingPropertyValue(String propName) {
225         return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
226     }
227
228     /**
229      * Gets the common part properties.
230      * 
231      * @return the common part properties
232      */
233     public List<PropertyItemType> getCommonPartProperties() {
234         return getPropertiesForPart(getCommonPartLabel());
235     }
236
237     /**
238      * @param propName The name of the property (or properties) to find
239      * @param qualified Whether the returned values should be qualified with the
240      *          partLabel. This is when the property values are schema field references.
241      * @return List of property values for the matched property on the common schema part.
242      */
243     public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
244         return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
245     }
246
247     /* (non-Javadoc)
248      * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
249      */
250     @Override
251     public String getQualifiedServiceName() {
252         return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
253     }
254
255     /* (non-Javadoc)
256      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
257      */
258     @Override
259     public String getRepositoryClientName() {
260         if (repositoryDomain == null) {
261             return null;
262         }
263         return repositoryDomain.getRepositoryClient();
264     }
265
266     /* (non-Javadoc)
267      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
268      */
269     @Override
270     public ClientType getRepositoryClientType() {
271         //assumption: there is only one repository client configured
272         return ServiceMain.getInstance().getClientType();
273     }
274
275     /* (non-Javadoc)
276      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
277      */
278     @Override
279     public String getRepositoryDomainName() {
280         if (repositoryDomain == null) {
281             return null;
282         }
283         return repositoryDomain.getName();
284     }
285
286     /* (non-Javadoc)
287      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
288      */
289     @Override
290     public String getRepositoryDomainStorageName() {
291         if (repositoryDomain == null) {
292             return null;
293         }
294         return repositoryDomain.getStorageName();
295     }
296
297     /* (non-Javadoc)
298      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
299      */
300     @Override
301     public String getRepositoryWorkspaceId() {
302         return ServiceMain.getInstance().getWorkspaceId(getTenantId(), getServiceName());
303     }
304
305     /* (non-Javadoc)
306      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
307      */
308     @Override
309     public String getRepositoryWorkspaceName() {
310         //service name is workspace name by convention
311         return serviceBinding.getName();
312     }
313
314     /* (non-Javadoc)
315      * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
316      */
317     @Override
318     public ServiceBindingType getServiceBinding() {
319         return serviceBinding;
320     }
321
322     /* (non-Javadoc)
323      * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
324      */
325     @Override
326     public String getServiceName() {
327         return serviceBinding.getName();
328     }
329
330     /* (non-Javadoc)
331      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
332      */
333     @Override
334     public String getDocumentType() {
335         // If they have not overridden the setting, use the type of the service
336         // object.
337         return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
338     }
339     
340     @Override
341     public String getTenantQualifiedDoctype(String docType) {
342         // If they have not overridden the setting, use the type of the service
343         // object.
344         String result = ServiceBindingUtils.getTenantQualifiedDocType(this.getTenantId(), docType);
345         
346         return result;
347     }
348     
349     @Override
350     public String getTenantQualifiedDoctype() {
351         String docType = (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
352         return getTenantQualifiedDoctype(docType);
353     }
354
355     /* (non-Javadoc)
356      * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
357      */
358     @Override
359     public void setDocumentType(String docType) {
360         overrideDocumentType = docType;
361     }
362
363     /* (non-Javadoc)
364      * @see org.collectionspace.services.common.context.ServiceContext#getSecurityContext()
365      */
366     @Override
367     public SecurityContext getSecurityContext() {
368         return securityContext;
369     }
370
371     /* (non-Javadoc)
372      * @see org.collectionspace.services.common.context.ServiceContext#getUserId()
373      */
374     @Override
375     public String getUserId() {
376         return securityContext.getUserId();
377     }
378
379     /* (non-Javadoc)
380      * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
381      */
382     @Override
383     public String getTenantId() {
384         return securityContext.getCurrentTenantId();
385     }
386
387     /* (non-Javadoc)
388      * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
389      */
390     @Override
391     public String getTenantName() {
392         return securityContext.getCurrentTenantName();
393     }
394
395     /* (non-Javadoc)
396      * @see org.collectionspace.services.common.context.ServiceContext#getInput()
397      */
398     @Override
399     public abstract IT getInput();
400
401     /* (non-Javadoc)
402      * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
403      */
404     @Override
405     public abstract void setInput(IT input);
406
407     /* (non-Javadoc)
408      * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
409      */
410     @Override
411     public abstract OT getOutput();
412
413     /* (non-Javadoc)
414      * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
415      */
416     @Override
417     public abstract void setOutput(OT output);
418
419     /* (non-Javadoc)
420      * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
421      */
422     @Override
423     public Map<String, Object> getProperties() {
424         return properties;
425     }
426
427     /* (non-Javadoc)
428      * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
429      */
430     @Override
431     public void setProperties(Map<String, Object> props) {
432         properties.putAll(props);
433     }
434
435     /* (non-Javadoc)
436      * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
437      */
438     public Object getProperty(String name) {
439         return properties.get(name);
440     }
441
442     /* (non-Javadoc)
443      * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
444      */
445     public void setProperty(String name, Object o) {
446         properties.put(name, o);
447     }
448
449     /**
450      * checkTenantContext makss sure tenant context exists
451      *
452      * @return the string
453      *
454      * @throws UnauthorizedException the unauthorized exception
455      */
456     private void checkTenantContext() throws UnauthorizedException {
457
458         String tenantId = securityContext.getCurrentTenantId();
459         if (tenantId == null) {
460             String msg = "Could not find tenant context";
461             logger.error(msg);
462             throw new UnauthorizedException(msg);
463         }
464     }
465
466     private static String buildWorkflowWhereClause(MultivaluedMap<String, String> queryParams) {
467         String result = null;
468         
469         String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
470         if (includeDeleted != null && includeDeleted.equalsIgnoreCase(Boolean.FALSE.toString())) {      
471                 result = "ecm:currentLifeCycleState <> 'deleted'";
472         }
473         
474         return result;
475     }
476     
477     /**
478      * Creates the document handler instance.
479      * 
480      * @return the document handler
481      * 
482      * @throws Exception the exception
483      */
484     private DocumentHandler createDocumentHandlerInstance() throws Exception {
485         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
486         Class<?> c = tccl.loadClass(getDocumentHandlerClass());
487         if (DocumentHandler.class.isAssignableFrom(c)) {
488             docHandler = (DocumentHandler) c.newInstance();
489         } else {
490             throw new IllegalArgumentException("Not of type "
491                     + DocumentHandler.class.getCanonicalName());
492         }
493         //
494         // Create a default document filter
495         //
496         docHandler.setServiceContext(this);
497         DocumentFilter docFilter = docHandler.createDocumentFilter();
498         //
499         // If the context was created with query parameters,
500         // reflect the values of those parameters in the document filter
501         // to specify sort ordering, pagination, etc.
502         //
503         if (this.getQueryParams() != null) {
504           docFilter.setSortOrder(this.getQueryParams());
505           docFilter.setPagination(this.getQueryParams());
506           String workflowWhereClause = buildWorkflowWhereClause(queryParams);
507           if (workflowWhereClause != null) {
508                   docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);                 
509           }            
510
511         }
512         docHandler.setDocumentFilter(docFilter);
513
514         return docHandler;
515     }
516
517     /* (non-Javadoc)
518      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
519      */
520     @Override
521     public DocumentHandler getDocumentHandler() throws Exception {
522         DocumentHandler result = docHandler;
523         // create a new instance if one does not yet exist
524         if (result == null) {
525             result = createDocumentHandlerInstance();
526         }
527         return result;
528     }
529
530     /* (non-Javadoc)
531      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
532      */
533     @Override
534     public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
535         DocumentHandler result = getDocumentHandler();
536         DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
537         documentFilter.setPagination(queryParams);
538         return result;
539     }
540
541     /**
542      * Gets the document handler class.
543      * 
544      * @return the document handler class
545      */
546     private String getDocumentHandlerClass() {
547         if (serviceBinding.getDocumentHandler() == null
548                 || serviceBinding.getDocumentHandler().isEmpty()) {
549             String msg = "Missing documentHandler in service binding for "
550                     + getServiceName() + " for tenant id=" + getTenantId()
551                     + " name=" + getTenantName();
552             logger.error(msg);
553             throw new IllegalStateException(msg);
554         }
555         return serviceBinding.getDocumentHandler().trim();
556     }
557     
558     /*
559      * If this element is set in the service binding then use it otherwise
560      * assume that asserts are NOT disabled.
561      */
562     private boolean disableValidationAsserts() {
563         boolean result;
564         Boolean disableAsserts = getServiceBinding().isDisableAsserts();
565         result = (disableAsserts != null) ? disableAsserts : false;
566         return result;
567     }
568     
569     /* (non-Javadoc)
570      * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
571      */
572     @Override
573     public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
574         if (valHandlers != null) {
575             return valHandlers;
576         }
577         List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
578         List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
579         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
580         for (String clazz : handlerClazzes) {
581             clazz = clazz.trim();
582             Class<?> c = tccl.loadClass(clazz);
583             if (disableValidationAsserts() == false) {
584                 // enable validation assertions
585                 tccl.setClassAssertionStatus(clazz, true);
586             }
587             if (ValidatorHandler.class.isAssignableFrom(c)) {
588                 handlers.add((ValidatorHandler) c.newInstance());
589             }
590         }
591         valHandlers = handlers;
592         return valHandlers;
593     }
594
595     /* (non-Javadoc)
596      * @see java.lang.Object#toString()
597      */
598     @Override
599     public String toString() {
600         StringBuilder msg = new StringBuilder();
601         msg.append("AbstractServiceContext [");
602         msg.append("service name=" + serviceBinding.getName() + " ");
603         msg.append("service version=" + serviceBinding.getVersion() + " ");
604         msg.append("tenant id=" + tenantBinding.getId() + " ");
605         msg.append("tenant name=" + tenantBinding.getName() + " ");
606         msg.append(tenantBinding.getDisplayName() + " ");
607         if (repositoryDomain != null) {
608             msg.append("tenant repository domain=" + repositoryDomain.getName());
609         }
610         for (Map.Entry<String, Object> entry : properties.entrySet()) {
611             msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
612         }
613         msg.append("]");
614         return msg.toString();
615     }
616
617     /* (non-Javadoc)
618      * @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
619      */
620     @Override
621     public MultivaluedMap<String, String> getQueryParams() {
622
623          if (queryParams == null){
624               if (this.uriInfo != null){
625                 queryParams = this.uriInfo.getQueryParameters();
626             }
627          }
628          if (queryParams == null){
629              queryParams = new org.jboss.resteasy.specimpl.MultivaluedMapImpl<String,String>();
630         }
631         return this.queryParams;
632     }
633
634     @Override
635      public MultivaluedMap<String, String> getQueryParamsPtr() {
636            return this.queryParams;
637     }
638
639     /* (non-Javadoc)
640      * @see org.collectionspace.services.common.context.ServiceContext#setQueryParams(javax.ws.rs.core.MultivaluedMap)
641      */
642     @Override
643     public void setQueryParams(MultivaluedMap<String, String> theQueryParams) {
644         this.queryParams = theQueryParams;
645     }
646
647     @Override
648     public void setUriInfo(UriInfo ui){
649         this.uriInfo = ui;
650     }
651
652    @Override
653    public UriInfo getUriInfo(){
654         return this.uriInfo;
655     }
656 }