]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
00ea2611eba6b17499934080928e8d610a9dceae
[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.security.acl.Group;
27 import java.util.ArrayList;
28 import java.util.Enumeration;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import javax.security.auth.Subject;
34 import javax.security.jacc.PolicyContext;
35 import javax.security.jacc.PolicyContextException;
36 import javax.ws.rs.core.MultivaluedMap;
37
38 import org.collectionspace.authentication.AuthN;
39 import org.collectionspace.authentication.CSpaceTenant;
40
41 import org.collectionspace.services.common.ClientType;
42 import org.collectionspace.services.common.ServiceMain;
43 import org.collectionspace.services.common.config.PropertyItemUtils;
44 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
45 import org.collectionspace.services.common.document.DocumentHandler;
46 import org.collectionspace.services.common.document.DocumentFilter;
47 import org.collectionspace.services.common.document.ValidatorHandler;
48 import org.collectionspace.services.common.security.UnauthorizedException;
49 import org.collectionspace.services.common.service.ObjectPartType;
50 import org.collectionspace.services.common.service.ServiceBindingType;
51 import org.collectionspace.services.common.service.ServiceObjectType;
52 import org.collectionspace.services.common.tenant.TenantBindingType;
53 import org.collectionspace.services.common.types.PropertyItemType;
54 import org.collectionspace.services.common.types.PropertyType;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 /**
59  * AbstractServiceContext
60  *
61  * $LastChangedRevision: $
62  * $LastChangedDate: $
63  */
64 /**
65  * @author pschmitz
66  *
67  * @param <IT>
68  * @param <OT>
69  */
70 /**
71  * @author pschmitz
72  *
73  * @param <IT>
74  * @param <OT>
75  */
76 public abstract class AbstractServiceContextImpl<IT, OT>
77         implements ServiceContext<IT, OT> {
78
79     /** The logger. */
80     final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
81     
82     /** The properties. */
83     Map<String, Object> properties = new HashMap<String, Object>();
84     
85     /** The object part map. */
86     Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
87     
88     /** The service binding. */
89     private ServiceBindingType serviceBinding;
90     
91     /** The tenant binding. */
92     private TenantBindingType tenantBinding;
93     
94     /** The override document type. */
95     private String overrideDocumentType = null;
96     
97     /** The val handlers. */
98     private List<ValidatorHandler> valHandlers = null;
99     
100     /** The doc handler. */
101     private DocumentHandler docHandler = null;
102
103     private AbstractServiceContextImpl() {} // private constructor for singleton pattern
104     
105     // request 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         TenantBindingConfigReaderImpl tReader =
117                 ServiceMain.getInstance().getTenantBindingConfigReader();
118         //FIXME retrieveTenantId is not working consistently in non-auth mode
119         //TODO: get tenant binding from security context
120         String tenantId = retrieveTenantId();
121         if (tenantId == null) {
122             //for testing purposes
123             tenantId = "1"; //hardcoded for movingimages.us
124         }
125         tenantBinding = tReader.getTenantBinding(tenantId);
126         if (tenantBinding == null) {
127             String msg = "No tenant binding found for tenantId=" + tenantId
128                     + " while processing request for service= " + serviceName;
129             logger.error(msg);
130             throw new IllegalStateException(msg);
131         }
132         serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
133         if (serviceBinding == null) {
134             String msg = "No service binding found while processing request for "
135                     + serviceName + " for tenant id=" + getTenantId()
136                     + " name=" + getTenantName();
137             logger.error(msg);
138             throw new IllegalStateException(msg);
139         }
140         if (logger.isDebugEnabled()) {
141             logger.debug("tenantId=" + tenantId
142                     + " service binding=" + serviceBinding.getName());
143         }
144     }
145
146     /**
147      * getCommonPartLabel get common part label
148      * @return
149      */
150     @Override
151     public String getCommonPartLabel() {
152         return getCommonPartLabel(getServiceName());
153     }
154
155     /**
156      * getCommonPartLabel get common part label
157      * @return
158      */
159     public String getCommonPartLabel(String schemaName) {
160         return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
161     }
162
163     /* (non-Javadoc)
164      * @see org.collectionspace.services.common.context.ServiceContext#getPartsMetadata()
165      */
166     @Override
167     public Map<String, ObjectPartType> getPartsMetadata() {
168         if (objectPartMap.size() != 0) {
169             return objectPartMap;
170         }
171         ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
172         return objectPartMap;
173     }
174
175     /**
176      * Gets the properties for part.
177      * 
178      * @param partLabel the part label
179      * 
180      * @return the properties for part
181      */
182     public List<PropertyItemType> getPropertiesForPart(String partLabel) {
183         Map<String, ObjectPartType> partMap = getPartsMetadata();
184         ObjectPartType part = partMap.get(partLabel);
185         if(part==null) {
186                 throw new RuntimeException("No such part found: "+partLabel);
187         }
188         List<PropertyType> propNodeList = part.getProperties();
189         return propNodeList.isEmpty()?null:propNodeList.get(0).getItem();
190     }
191
192     /**
193      * @param partLabel The name of the scehma part to search in
194      * @param propName The name of the property (or properties) to find
195      * @param qualified Whether the returned values should be qualified with the
196      *          partLabel. This is when the property values are schema field references.
197      * @return List of property values for the matched property on the named schema part.
198      */
199     public List<String> getPropertyValuesForPart(String partLabel, String propName, boolean qualified) {
200         List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
201         return PropertyItemUtils.getPropertyValuesByName(allProps, propName, 
202                                                                                                         (qualified?(partLabel+":"):null));
203     }
204
205     /**
206      * @param propName The name of the property (or properties) to find
207      * @param qualified Whether the returned values should be qualified with the
208      *          partLabel. This is when the property values are schema field references.
209      * @return List of property values for the matched property on any schema part.
210      */
211     public List<String> getAllPartsPropertyValues(String propName, boolean qualified) {
212         return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified);
213     }
214     
215     /* (non-Javadoc)
216      * @see org.collectionspace.services.common.context.ServiceContext#getServiceBindingPropertyValue(java.lang.String)
217      */
218     public String getServiceBindingPropertyValue(String propName) {
219         return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
220     }
221     
222     /**
223      * Gets the common part properties.
224      * 
225      * @return the common part properties
226      */
227     public List<PropertyItemType> getCommonPartProperties() {
228         return getPropertiesForPart(getCommonPartLabel());
229     }
230
231     /**
232      * @param propName The name of the property (or properties) to find
233      * @param qualified Whether the returned values should be qualified with the
234      *          partLabel. This is when the property values are schema field references.
235      * @return List of property values for the matched property on the common schema part.
236      */
237     public List<String> getCommonPartPropertyValues(String propName, boolean qualified) {
238         return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified);
239     }
240
241     /* (non-Javadoc)
242      * @see org.collectionspace.services.common.context.ServiceContext#getQualifiedServiceName()
243      */
244     @Override
245     public String getQualifiedServiceName() {
246         return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
247     }
248
249     /* (non-Javadoc)
250      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientName()
251      */
252     @Override
253     public String getRepositoryClientName() {
254         if (serviceBinding.getRepositoryClient() == null) {
255             return null;
256         }
257         return serviceBinding.getRepositoryClient().trim();
258     }
259
260     /* (non-Javadoc)
261      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryClientType()
262      */
263     @Override
264     public ClientType getRepositoryClientType() {
265         //assumption: there is only one repository client configured
266         return ServiceMain.getInstance().getClientType();
267     }
268
269     /* (non-Javadoc)
270      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryDomainName()
271      */
272     @Override
273     public String getRepositoryDomainName() {
274         return tenantBinding.getRepositoryDomain();
275     }
276
277     /* (non-Javadoc)
278      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceId()
279      */
280     @Override
281     public String getRepositoryWorkspaceId() {
282         TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
283         return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
284     }
285
286     /* (non-Javadoc)
287      * @see org.collectionspace.services.common.context.ServiceContext#getRepositoryWorkspaceName()
288      */
289     @Override
290     public String getRepositoryWorkspaceName() {
291         //service name is workspace name by convention
292         return serviceBinding.getName();
293     }
294
295     /* (non-Javadoc)
296      * @see org.collectionspace.services.common.context.ServiceContext#getServiceBinding()
297      */
298     @Override
299     public ServiceBindingType getServiceBinding() {
300         return serviceBinding;
301     }
302
303     /* (non-Javadoc)
304      * @see org.collectionspace.services.common.context.ServiceContext#getServiceName()
305      */
306     @Override
307     public String getServiceName() {
308         return serviceBinding.getName();
309     }
310
311     /* (non-Javadoc)
312      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentType()
313      */
314     @Override
315     public String getDocumentType() {
316         // If they have not overridden the setting, use the type of the service
317         // object.
318         return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
319     }
320
321     /* (non-Javadoc)
322      * @see org.collectionspace.services.common.context.ServiceContext#setDocumentType(java.lang.String)
323      */
324     @Override
325     public void setDocumentType(String docType) {
326         overrideDocumentType = docType;
327     }
328
329     /* (non-Javadoc)
330      * @see org.collectionspace.services.common.context.ServiceContext#getTenantId()
331      */
332     @Override
333     public String getTenantId() {
334         return tenantBinding.getId();
335     }
336
337     /* (non-Javadoc)
338      * @see org.collectionspace.services.common.context.ServiceContext#getTenantName()
339      */
340     @Override
341     public String getTenantName() {
342         return tenantBinding.getName();
343     }
344
345     /* (non-Javadoc)
346      * @see org.collectionspace.services.common.context.ServiceContext#getInput()
347      */
348     @Override
349     public abstract IT getInput();
350
351     /* (non-Javadoc)
352      * @see org.collectionspace.services.common.context.ServiceContext#setInput(java.lang.Object)
353      */
354     @Override
355     public abstract void setInput(IT input);
356
357     /* (non-Javadoc)
358      * @see org.collectionspace.services.common.context.ServiceContext#getOutput()
359      */
360     @Override
361     public abstract OT getOutput();
362
363     /* (non-Javadoc)
364      * @see org.collectionspace.services.common.context.ServiceContext#setOutput(java.lang.Object)
365      */
366     @Override
367     public abstract void setOutput(OT output);
368
369     /* (non-Javadoc)
370      * @see org.collectionspace.services.common.context.ServiceContext#getProperties()
371      */
372     @Override
373     public Map<String, Object> getProperties() {
374         return properties;
375     }
376
377     /* (non-Javadoc)
378      * @see org.collectionspace.services.common.context.ServiceContext#setProperties(java.util.Map)
379      */
380     @Override
381     public void setProperties(Map<String, Object> props) {
382         properties.putAll(props);
383     }
384
385     /* (non-Javadoc)
386      * @see org.collectionspace.services.common.context.ServiceContext#getProperty(java.lang.String)
387      */
388     public Object getProperty(String name) {
389         return properties.get(name);
390     }
391
392     /* (non-Javadoc)
393      * @see org.collectionspace.services.common.context.ServiceContext#setProperty(java.lang.String, java.lang.Object)
394      */
395     public void setProperty(String name, Object o) {
396         properties.put(name, o);
397     }
398
399
400     /**
401      * Retrieve tenant id.
402      * 
403      * @return the string
404      * 
405      * @throws UnauthorizedException the unauthorized exception
406      */
407     private String retrieveTenantId() throws UnauthorizedException {
408
409         String[] tenantIds = AuthN.get().getTenantIds();
410         if (tenantIds.length == 0) {
411             String msg = "Could not find tenant context";
412             logger.error(msg);
413             throw new UnauthorizedException(msg);
414         }
415         //TODO: if a user is associated with more than one tenants, the tenant
416         //id should be matched with the one sent over the wire
417         return tenantIds[0];
418     }
419     
420     /**
421      * Creates the document handler instance.
422      * 
423      * @return the document handler
424      * 
425      * @throws Exception the exception
426      */
427     private DocumentHandler createDocumentHandlerInstance() throws Exception {
428         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
429         Class c = tccl.loadClass(getDocumentHandlerClass());
430         if (DocumentHandler.class.isAssignableFrom(c)) {
431             docHandler = (DocumentHandler) c.newInstance();
432         } else {
433             throw new IllegalArgumentException("Not of type "
434                     + DocumentHandler.class.getCanonicalName());
435         }
436         //
437         // create a default document filter with pagination if the context
438         // was created with query params
439         //
440         docHandler.setServiceContext(this);
441         DocumentFilter docFilter = docHandler.createDocumentFilter();
442         docFilter.setPagination(this.getQueryParams());
443         docHandler.setDocumentFilter(docFilter);
444         
445         return docHandler;      
446     }
447
448     /* (non-Javadoc)
449      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHandler()
450      */
451     @Override
452     public DocumentHandler getDocumentHandler() throws Exception {
453         DocumentHandler result = docHandler;            
454         // create a new instance if one does not yet exist
455         if (result == null) {
456                 result = createDocumentHandlerInstance();
457         }       
458         return result;
459     }
460         
461     /* (non-Javadoc)
462      * @see org.collectionspace.services.common.context.ServiceContext#getDocumentHanlder(javax.ws.rs.core.MultivaluedMap)
463      */
464     @Override
465     public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception {
466         DocumentHandler result = getDocumentHandler();
467         DocumentFilter documentFilter = result.getDocumentFilter(); //to see results in debugger variables view
468         documentFilter.setPagination(queryParams);
469         return result;
470     }
471
472     /**
473      * Gets the document handler class.
474      * 
475      * @return the document handler class
476      */
477     private String getDocumentHandlerClass() {
478         if (serviceBinding.getDocumentHandler() == null
479                 || serviceBinding.getDocumentHandler().isEmpty()) {
480             String msg = "Missing documentHandler in service binding for "
481                     + getServiceName() + " for tenant id=" + getTenantId()
482                     + " name=" + getTenantName();
483             logger.error(msg);
484             throw new IllegalStateException(msg);
485         }
486         return serviceBinding.getDocumentHandler().trim();
487     }
488
489     /* (non-Javadoc)
490      * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
491      */
492     @Override
493     public List<ValidatorHandler> getValidatorHandlers() throws Exception {
494         if (valHandlers != null) {
495             return valHandlers;
496         }
497         List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
498         List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
499         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
500         for (String clazz : handlerClazzes) {
501             clazz = clazz.trim();
502             Class c = tccl.loadClass(clazz);
503             if (ValidatorHandler.class.isAssignableFrom(c)) {
504                 handlers.add((ValidatorHandler) c.newInstance());
505             }
506         }
507         valHandlers = handlers;
508         return valHandlers;
509     }
510
511     /* (non-Javadoc)
512      * @see java.lang.Object#toString()
513      */
514     @Override
515     public String toString() {
516         StringBuilder msg = new StringBuilder();
517         msg.append("AbstractServiceContext [");
518         msg.append("service name=" + serviceBinding.getName() + " ");
519         msg.append("service version=" + serviceBinding.getVersion() + " ");
520         msg.append("tenant id=" + tenantBinding.getId() + " ");
521         msg.append("tenant name=" + tenantBinding.getName() + " ");
522         msg.append(tenantBinding.getDisplayName() + " ");
523         msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
524         for (Map.Entry<String, Object> entry : properties.entrySet()) {
525             msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
526         }
527         msg.append("]");
528         return msg.toString();
529     }
530     
531     @Override
532     public MultivaluedMap<String, String> getQueryParams() {
533         return this.queryParams;
534     }
535     
536     @Override
537     public void setQueryParams(MultivaluedMap<String, String> queryParams) {
538         this.queryParams = queryParams;
539     }    
540 }