]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
b0746f57efd3dc4062c02b4f75b5798a5a0145ac
[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 org.collectionspace.authentication.CSpaceTenant;
37
38 import org.collectionspace.services.common.ClientType;
39 import org.collectionspace.services.common.ServiceMain;
40 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
41 import org.collectionspace.services.common.document.DocumentHandler;
42 import org.collectionspace.services.common.document.ValidatorHandler;
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.service.ServiceObjectType;
47 import org.collectionspace.services.common.tenant.TenantBindingType;
48 import org.collectionspace.services.common.types.PropertyItemType;
49 import org.collectionspace.services.common.types.PropertyType;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /**
54  * AbstractServiceContext
55  *
56  * $LastChangedRevision: $
57  * $LastChangedDate: $
58  */
59 public abstract class AbstractServiceContextImpl<IT, OT>
60         implements ServiceContext<IT, OT> {
61
62     final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
63     Map<String, Object> properties = new HashMap<String, Object>();
64     Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
65     private ServiceBindingType serviceBinding;
66     private TenantBindingType tenantBinding;
67     private String overrideDocumentType = null;
68     private List<ValidatorHandler> valHandlers = null;
69     private DocumentHandler docHandler = null;
70
71     public AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
72         TenantBindingConfigReaderImpl tReader =
73                 ServiceMain.getInstance().getTenantBindingConfigReader();
74         //FIXME retrieveTenantId is not working consistently in non-auth mode
75         //TODO: get tenant binding from security context
76         String tenantId = retrieveTenantId();
77         if (tenantId == null) {
78             //for testing purposes
79             tenantId = "1"; //hardcoded for movingimages.us
80         }
81         tenantBinding = tReader.getTenantBinding(tenantId);
82         if (tenantBinding == null) {
83             String msg = "No tenant binding found for tenantId=" + tenantId
84                     + " while processing request for service= " + serviceName;
85             logger.error(msg);
86             throw new IllegalStateException(msg);
87         }
88         serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
89         if (serviceBinding == null) {
90             String msg = "No service binding found while processing request for "
91                     + serviceName + " for tenant id=" + getTenantId()
92                     + " name=" + getTenantName();
93             logger.error(msg);
94             throw new IllegalStateException(msg);
95         }
96         if (logger.isDebugEnabled()) {
97             logger.debug("tenantId=" + tenantId
98                     + " service binding=" + serviceBinding.getName());
99         }
100     }
101
102     /**
103      * getCommonPartLabel get common part label
104      * @return
105      */
106     @Override
107     public String getCommonPartLabel() {
108         return getCommonPartLabel(getServiceName());
109     }
110
111     /**
112      * getCommonPartLabel get common part label
113      * @return
114      */
115     public String getCommonPartLabel(String schemaName) {
116         return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
117     }
118
119     @Override
120     public Map<String, ObjectPartType> getPartsMetadata() {
121         if (objectPartMap.size() != 0) {
122             return objectPartMap;
123         }
124         ServiceBindingType serviceBinding = getServiceBinding();
125         ServiceObjectType objectType = serviceBinding.getObject();
126         List<ObjectPartType> objectPartTypes = objectType.getPart();
127         for (ObjectPartType objectPartType : objectPartTypes) {
128             objectPartMap.put(objectPartType.getLabel(), objectPartType);
129         }
130         return objectPartMap;
131     }
132     
133     public List<PropertyType> getPropertiesForPart(String partLabel) {
134         Map<String, ObjectPartType> partMap = getPartsMetadata();
135         ObjectPartType part = partMap.get(partLabel);
136         if(part==null) {
137                 throw new RuntimeException("No such part found: "+partLabel);
138         }
139         return part.getProperties();
140     }
141
142     public List<String> getPropertyValuesForPart(String partLabel, String propName) {
143         List<PropertyType> allProps = getPropertiesForPart(partLabel);
144         List<String> values = new ArrayList<String>();
145         if(allProps.size()>0) {
146                 List<PropertyItemType> propItems = allProps.get(0).getItem();
147                 for(PropertyItemType propItem:propItems) {
148                         if(propName.equals(propItem.getKey())) {
149                                 String value = propItem.getValue();
150                                 if(value!=null) {
151                                         values.add(value);
152                                 }
153                         }
154                 }
155         }
156         return values;
157     }
158
159     public List<PropertyType> getCommonPartProperties() {
160         return getPropertiesForPart(getCommonPartLabel());
161     }
162
163     public List<String> getCommonPartPropertyValues(String propName) {
164         return getPropertyValuesForPart(getCommonPartLabel(), propName);
165     }
166
167     @Override
168     public String getQualifiedServiceName() {
169         return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
170     }
171
172     @Override
173     public String getRepositoryClientName() {
174         if (serviceBinding.getRepositoryClient() == null) {
175             return null;
176         }
177         return serviceBinding.getRepositoryClient().trim();
178     }
179
180     @Override
181     public ClientType getRepositoryClientType() {
182         //assumption: there is only one repository client configured
183         return ServiceMain.getInstance().getClientType();
184     }
185
186     @Override
187     public String getRepositoryDomainName() {
188         return tenantBinding.getRepositoryDomain();
189     }
190
191     @Override
192     public String getRepositoryWorkspaceId() {
193         TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
194         return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
195     }
196
197     @Override
198     public String getRepositoryWorkspaceName() {
199         //service name is workspace name by convention
200         return serviceBinding.getName();
201     }
202
203     @Override
204     public ServiceBindingType getServiceBinding() {
205         return serviceBinding;
206     }
207
208     @Override
209     public String getServiceName() {
210         return serviceBinding.getName();
211     }
212
213     @Override
214     public String getDocumentType() {
215         // If they have not overridden the setting, use the type of the service
216         // object.
217         return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
218     }
219
220     @Override
221     public void setDocumentType(String docType) {
222         overrideDocumentType = docType;
223     }
224
225     @Override
226     public String getTenantId() {
227         return tenantBinding.getId();
228     }
229
230     @Override
231     public String getTenantName() {
232         return tenantBinding.getName();
233     }
234
235     @Override
236     public abstract IT getInput();
237
238     @Override
239     public abstract void setInput(IT input);
240
241     @Override
242     public abstract OT getOutput();
243
244     @Override
245     public abstract void setOutput(OT output);
246
247     @Override
248     public Map<String, Object> getProperties() {
249         return properties;
250     }
251
252     @Override
253     public void setProperties(Map<String, Object> props) {
254         properties.putAll(props);
255     }
256
257     public Object getProperty(String name) {
258         return properties.get(name);
259     }
260
261     public void setProperty(String name, Object o) {
262         properties.put(name, o);
263     }
264     private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
265
266     private String retrieveTenantId() throws UnauthorizedException {
267
268         String tenantId = null;
269         Subject caller = null;
270         Set<Group> groups = null;
271         try {
272             caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
273             if (caller == null) {
274                 //logger.warn("security not enabled...");
275                 return tenantId;
276             }
277             groups = caller.getPrincipals(Group.class);
278             if (groups != null && groups.size() == 0) {
279                 //TODO: find out why subject is not null
280                 if (logger.isDebugEnabled()) {
281                     logger.debug("no tenant(s) found!");
282                 }
283                 return tenantId;
284             }
285         } catch (PolicyContextException pce) {
286             String msg = "Could not retrieve principal information";
287             logger.error(msg, pce);
288             throw new UnauthorizedException(msg);
289         }
290         for (Group g : groups) {
291             if ("Tenants".equals(g.getName())) {
292                 Enumeration members = g.members();
293                 while (members.hasMoreElements()) {
294                     CSpaceTenant tenant = (CSpaceTenant) members.nextElement();
295                     tenantId = tenant.getId();
296                     if (logger.isDebugEnabled()) {
297                         logger.debug("found tenant id=" + tenant.getId()
298                                 + " name=" + tenant.getName());
299                     }
300                 }
301             }
302         }
303         //TODO: if a user is associated with more than one tenants, the tenant
304         //id should be matched with sent over the wire
305         if (tenantId == null) {
306             String msg = "Could not find tenant context";
307             logger.error(msg);
308             throw new UnauthorizedException(msg);
309         }
310         return tenantId;
311     }
312
313     @Override
314     public DocumentHandler getDocumentHandler() throws Exception {
315         if (docHandler != null) {
316             return docHandler;
317         }
318         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
319         Class c = tccl.loadClass(getDocumentHandlerClass());
320         if (DocumentHandler.class.isAssignableFrom(c)) {
321             docHandler = (DocumentHandler) c.newInstance();
322         } else {
323             throw new IllegalArgumentException("Not of type " +
324                     DocumentHandler.class.getCanonicalName());
325         }
326         docHandler.setServiceContext(this);
327         return docHandler;
328     }
329
330     private String getDocumentHandlerClass() {
331         if (serviceBinding.getDocumentHandler() == null
332                 || serviceBinding.getDocumentHandler().isEmpty()) {
333             String msg = "Missing documentHandler in service binding for "
334                     + getServiceName() + " for tenant id=" + getTenantId()
335                     + " name=" + getTenantName();
336             logger.error(msg);
337             throw new IllegalStateException(msg);
338         }
339         return serviceBinding.getDocumentHandler().trim();
340     }
341
342     @Override
343     public List<ValidatorHandler> getValidatorHandlers() throws Exception {
344         if (valHandlers != null) {
345             return valHandlers;
346         }
347         List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
348         List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
349         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
350         for (String clazz : handlerClazzes) {
351             clazz = clazz.trim();
352             Class c = tccl.loadClass(clazz);
353             if (ValidatorHandler.class.isAssignableFrom(c)) {
354                 handlers.add((ValidatorHandler) c.newInstance());
355             }
356         }
357         valHandlers = handlers;
358         return valHandlers;
359     }
360
361     @Override
362     public String toString() {
363         StringBuilder msg = new StringBuilder();
364         msg.append("AbstractServiceContext [");
365         msg.append("service name=" + serviceBinding.getName() + " ");
366         msg.append("service version=" + serviceBinding.getVersion() + " ");
367         msg.append("tenant id=" + tenantBinding.getId() + " ");
368         msg.append("tenant name=" + tenantBinding.getName() + " ");
369         msg.append(tenantBinding.getDisplayName() + " ");
370         msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
371         for (Map.Entry<String, Object> entry : properties.entrySet()) {
372             msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
373         }
374         msg.append("]");
375         return msg.toString();
376     }
377 }