]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
448a0cf19fddb69db32b03ba09ce2d50995d93f6
[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         ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
125         return objectPartMap;
126     }
127     
128     public List<PropertyType> getPropertiesForPart(String partLabel) {
129         Map<String, ObjectPartType> partMap = getPartsMetadata();
130         ObjectPartType part = partMap.get(partLabel);
131         if(part==null) {
132                 throw new RuntimeException("No such part found: "+partLabel);
133         }
134         return part.getProperties();
135     }
136
137     public List<String> getPropertyValuesForPart(String partLabel, String propName) {
138         List<PropertyType> allProps = getPropertiesForPart(partLabel);
139         return ServiceBindingUtils.getPropertyValuesByName(allProps, propName);
140     }
141
142     public List<String> getPropertyValues(String propName) {
143         return ServiceBindingUtils.getPropertyValues(getServiceBinding(), propName);
144     }
145     
146     public List<PropertyType> getCommonPartProperties() {
147         return getPropertiesForPart(getCommonPartLabel());
148     }
149
150     public List<String> getCommonPartPropertyValues(String propName) {
151         return getPropertyValuesForPart(getCommonPartLabel(), propName);
152     }
153
154     @Override
155     public String getQualifiedServiceName() {
156         return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
157     }
158
159     @Override
160     public String getRepositoryClientName() {
161         if (serviceBinding.getRepositoryClient() == null) {
162             return null;
163         }
164         return serviceBinding.getRepositoryClient().trim();
165     }
166
167     @Override
168     public ClientType getRepositoryClientType() {
169         //assumption: there is only one repository client configured
170         return ServiceMain.getInstance().getClientType();
171     }
172
173     @Override
174     public String getRepositoryDomainName() {
175         return tenantBinding.getRepositoryDomain();
176     }
177
178     @Override
179     public String getRepositoryWorkspaceId() {
180         TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
181         return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
182     }
183
184     @Override
185     public String getRepositoryWorkspaceName() {
186         //service name is workspace name by convention
187         return serviceBinding.getName();
188     }
189
190     @Override
191     public ServiceBindingType getServiceBinding() {
192         return serviceBinding;
193     }
194
195     @Override
196     public String getServiceName() {
197         return serviceBinding.getName();
198     }
199
200     @Override
201     public String getDocumentType() {
202         // If they have not overridden the setting, use the type of the service
203         // object.
204         return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
205     }
206
207     @Override
208     public void setDocumentType(String docType) {
209         overrideDocumentType = docType;
210     }
211
212     @Override
213     public String getTenantId() {
214         return tenantBinding.getId();
215     }
216
217     @Override
218     public String getTenantName() {
219         return tenantBinding.getName();
220     }
221
222     @Override
223     public abstract IT getInput();
224
225     @Override
226     public abstract void setInput(IT input);
227
228     @Override
229     public abstract OT getOutput();
230
231     @Override
232     public abstract void setOutput(OT output);
233
234     @Override
235     public Map<String, Object> getProperties() {
236         return properties;
237     }
238
239     @Override
240     public void setProperties(Map<String, Object> props) {
241         properties.putAll(props);
242     }
243
244     public Object getProperty(String name) {
245         return properties.get(name);
246     }
247
248     public void setProperty(String name, Object o) {
249         properties.put(name, o);
250     }
251     private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
252
253     private String retrieveTenantId() throws UnauthorizedException {
254
255         String tenantId = null;
256         Subject caller = null;
257         Set<Group> groups = null;
258         try {
259             caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
260             if (caller == null) {
261                 //logger.warn("security not enabled...");
262                 return tenantId;
263             }
264             groups = caller.getPrincipals(Group.class);
265             if (groups != null && groups.size() == 0) {
266                 //TODO: find out why subject is not null
267                 if (logger.isDebugEnabled()) {
268                     logger.debug("no tenant(s) found!");
269                 }
270                 return tenantId;
271             }
272         } catch (PolicyContextException pce) {
273             String msg = "Could not retrieve principal information";
274             logger.error(msg, pce);
275             throw new UnauthorizedException(msg);
276         }
277         for (Group g : groups) {
278             if ("Tenants".equals(g.getName())) {
279                 Enumeration members = g.members();
280                 while (members.hasMoreElements()) {
281                     CSpaceTenant tenant = (CSpaceTenant) members.nextElement();
282                     tenantId = tenant.getId();
283                     if (logger.isDebugEnabled()) {
284                         logger.debug("found tenant id=" + tenant.getId()
285                                 + " name=" + tenant.getName());
286                     }
287                 }
288             }
289         }
290         //TODO: if a user is associated with more than one tenants, the tenant
291         //id should be matched with sent over the wire
292         if (tenantId == null) {
293             String msg = "Could not find tenant context";
294             logger.error(msg);
295             throw new UnauthorizedException(msg);
296         }
297         return tenantId;
298     }
299
300     @Override
301     public DocumentHandler getDocumentHandler() throws Exception {
302         if (docHandler != null) {
303             return docHandler;
304         }
305         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
306         Class c = tccl.loadClass(getDocumentHandlerClass());
307         if (DocumentHandler.class.isAssignableFrom(c)) {
308             docHandler = (DocumentHandler) c.newInstance();
309         } else {
310             throw new IllegalArgumentException("Not of type " +
311                     DocumentHandler.class.getCanonicalName());
312         }
313         docHandler.setServiceContext(this);
314         return docHandler;
315     }
316
317     private String getDocumentHandlerClass() {
318         if (serviceBinding.getDocumentHandler() == null
319                 || serviceBinding.getDocumentHandler().isEmpty()) {
320             String msg = "Missing documentHandler in service binding for "
321                     + getServiceName() + " for tenant id=" + getTenantId()
322                     + " name=" + getTenantName();
323             logger.error(msg);
324             throw new IllegalStateException(msg);
325         }
326         return serviceBinding.getDocumentHandler().trim();
327     }
328
329     @Override
330     public List<ValidatorHandler> getValidatorHandlers() throws Exception {
331         if (valHandlers != null) {
332             return valHandlers;
333         }
334         List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
335         List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
336         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
337         for (String clazz : handlerClazzes) {
338             clazz = clazz.trim();
339             Class c = tccl.loadClass(clazz);
340             if (ValidatorHandler.class.isAssignableFrom(c)) {
341                 handlers.add((ValidatorHandler) c.newInstance());
342             }
343         }
344         valHandlers = handlers;
345         return valHandlers;
346     }
347
348     @Override
349     public String toString() {
350         StringBuilder msg = new StringBuilder();
351         msg.append("AbstractServiceContext [");
352         msg.append("service name=" + serviceBinding.getName() + " ");
353         msg.append("service version=" + serviceBinding.getVersion() + " ");
354         msg.append("tenant id=" + tenantBinding.getId() + " ");
355         msg.append("tenant name=" + tenantBinding.getName() + " ");
356         msg.append(tenantBinding.getDisplayName() + " ");
357         msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
358         for (Map.Entry<String, Object> entry : properties.entrySet()) {
359             msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
360         }
361         msg.append("]");
362         return msg.toString();
363     }
364 }