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