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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.common.context;
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;
33 import javax.security.auth.Subject;
34 import javax.security.jacc.PolicyContext;
35 import javax.security.jacc.PolicyContextException;
36 import org.collectionspace.authentication.CSpaceTenant;
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;
54 * AbstractServiceContext
56 * $LastChangedRevision: $
59 public abstract class AbstractServiceContextImpl<IT, OT>
60 implements ServiceContext<IT, OT> {
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;
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
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;
86 throw new IllegalStateException(msg);
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();
94 throw new IllegalStateException(msg);
96 if (logger.isDebugEnabled()) {
97 logger.debug("tenantId=" + tenantId
98 + " service binding=" + serviceBinding.getName());
103 * getCommonPartLabel get common part label
107 public String getCommonPartLabel() {
108 return getCommonPartLabel(getServiceName());
112 * getCommonPartLabel get common part label
115 public String getCommonPartLabel(String schemaName) {
116 return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
120 public Map<String, ObjectPartType> getPartsMetadata() {
121 if (objectPartMap.size() != 0) {
122 return objectPartMap;
124 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
125 return objectPartMap;
128 public List<PropertyType> getPropertiesForPart(String partLabel) {
129 Map<String, ObjectPartType> partMap = getPartsMetadata();
130 ObjectPartType part = partMap.get(partLabel);
132 throw new RuntimeException("No such part found: "+partLabel);
134 return part.getProperties();
137 public List<String> getPropertyValuesForPart(String partLabel, String propName) {
138 List<PropertyType> allProps = getPropertiesForPart(partLabel);
139 return ServiceBindingUtils.getPropertyValuesByName(allProps, propName);
142 public List<String> getPropertyValues(String propName) {
143 return ServiceBindingUtils.getPropertyValues(getServiceBinding(), propName);
146 public List<PropertyType> getCommonPartProperties() {
147 return getPropertiesForPart(getCommonPartLabel());
150 public List<String> getCommonPartPropertyValues(String propName) {
151 return getPropertyValuesForPart(getCommonPartLabel(), propName);
155 public String getQualifiedServiceName() {
156 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
160 public String getRepositoryClientName() {
161 if (serviceBinding.getRepositoryClient() == null) {
164 return serviceBinding.getRepositoryClient().trim();
168 public ClientType getRepositoryClientType() {
169 //assumption: there is only one repository client configured
170 return ServiceMain.getInstance().getClientType();
174 public String getRepositoryDomainName() {
175 return tenantBinding.getRepositoryDomain();
179 public String getRepositoryWorkspaceId() {
180 TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
181 return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
185 public String getRepositoryWorkspaceName() {
186 //service name is workspace name by convention
187 return serviceBinding.getName();
191 public ServiceBindingType getServiceBinding() {
192 return serviceBinding;
196 public String getServiceName() {
197 return serviceBinding.getName();
201 public String getDocumentType() {
202 // If they have not overridden the setting, use the type of the service
204 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
208 public void setDocumentType(String docType) {
209 overrideDocumentType = docType;
213 public String getTenantId() {
214 return tenantBinding.getId();
218 public String getTenantName() {
219 return tenantBinding.getName();
223 public abstract IT getInput();
226 public abstract void setInput(IT input);
229 public abstract OT getOutput();
232 public abstract void setOutput(OT output);
235 public Map<String, Object> getProperties() {
240 public void setProperties(Map<String, Object> props) {
241 properties.putAll(props);
244 public Object getProperty(String name) {
245 return properties.get(name);
248 public void setProperty(String name, Object o) {
249 properties.put(name, o);
251 private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
253 private String retrieveTenantId() throws UnauthorizedException {
255 String tenantId = null;
256 Subject caller = null;
257 Set<Group> groups = null;
259 caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
260 if (caller == null) {
261 //logger.warn("security not enabled...");
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!");
272 } catch (PolicyContextException pce) {
273 String msg = "Could not retrieve principal information";
274 logger.error(msg, pce);
275 throw new UnauthorizedException(msg);
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());
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";
295 throw new UnauthorizedException(msg);
301 public DocumentHandler getDocumentHandler() throws Exception {
302 if (docHandler != null) {
305 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
306 Class c = tccl.loadClass(getDocumentHandlerClass());
307 if (DocumentHandler.class.isAssignableFrom(c)) {
308 docHandler = (DocumentHandler) c.newInstance();
310 throw new IllegalArgumentException("Not of type " +
311 DocumentHandler.class.getCanonicalName());
313 docHandler.setServiceContext(this);
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();
324 throw new IllegalStateException(msg);
326 return serviceBinding.getDocumentHandler().trim();
330 public List<ValidatorHandler> getValidatorHandlers() throws Exception {
331 if (valHandlers != null) {
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());
344 valHandlers = handlers;
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());
362 return msg.toString();