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.Enumeration;
28 import java.util.HashMap;
29 import java.util.List;
32 import javax.security.auth.Subject;
33 import javax.security.jacc.PolicyContext;
34 import javax.security.jacc.PolicyContextException;
35 import org.collectionspace.authentication.CSpaceTenant;
37 import org.collectionspace.services.common.ClientType;
38 import org.collectionspace.services.common.ServiceMain;
39 import org.collectionspace.services.common.config.TenantBindingConfigReader;
40 import org.collectionspace.services.common.security.UnauthorizedException;
41 import org.collectionspace.services.common.service.ObjectPartType;
42 import org.collectionspace.services.common.service.ServiceBindingType;
43 import org.collectionspace.services.common.service.ServiceObjectType;
44 import org.collectionspace.services.common.tenant.TenantBindingType;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * AbstractServiceContext
51 * $LastChangedRevision: $
54 public abstract class AbstractServiceContext<IT, OT>
55 implements ServiceContext<IT, OT> {
57 final Logger logger = LoggerFactory.getLogger(AbstractServiceContext.class);
58 Map<String, Object> properties = new HashMap<String, Object>();
59 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
60 private ServiceBindingType serviceBinding;
61 private TenantBindingType tenantBinding;
62 private String overrideDocumentType = null;
64 public AbstractServiceContext(String serviceName) throws UnauthorizedException {
65 TenantBindingConfigReader tReader =
66 ServiceMain.getInstance().getTenantBindingConfigReader();
67 //FIXME retrieveTenantId is not working consistently in non-auth mode
68 //TODO: get tenant binding from security context
69 String tenantId = retrieveTenantId();
70 if (tenantId == null) {
71 //for testing purposes
72 tenantId = "1"; //hardcoded for movingimages.us
74 tenantBinding = tReader.getTenantBinding(tenantId);
75 if (tenantBinding == null) {
76 String msg = "No tenant binding found for tenantId=" + tenantId
77 + " while processing request for service= " + serviceName;
79 throw new IllegalStateException(msg);
81 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
82 if (serviceBinding == null) {
83 String msg = "No service binding found while processing request for "
84 + serviceName + " for tenant id=" + getTenantId()
85 + " name=" + getTenantName();
87 throw new IllegalStateException(msg);
89 if (logger.isDebugEnabled()) {
90 logger.debug("tenantId=" + tenantId
91 + " service binding=" + serviceBinding.getName());
96 * getCommonPartLabel get common part label
100 public String getCommonPartLabel() {
101 return getCommonPartLabel(getServiceName());
105 * getCommonPartLabel get common part label
108 public String getCommonPartLabel(String schemaName) {
109 return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
113 public Map<String, ObjectPartType> getPartsMetadata() {
114 if (objectPartMap.size() != 0) {
115 return objectPartMap;
117 ServiceBindingType serviceBinding = getServiceBinding();
118 ServiceObjectType objectType = serviceBinding.getObject();
119 List<ObjectPartType> objectPartTypes = objectType.getPart();
120 for (ObjectPartType objectPartType : objectPartTypes) {
121 objectPartMap.put(objectPartType.getLabel(), objectPartType);
123 return objectPartMap;
127 public String getQualifiedServiceName() {
128 return TenantBindingConfigReader.getTenantQualifiedServiceName(getTenantId(), getServiceName());
132 public String getRepositoryClientName() {
133 if(serviceBinding.getRepositoryClient() == null) {
136 return serviceBinding.getRepositoryClient().trim();
140 public ClientType getRepositoryClientType() {
141 //assumption: there is only one repository client configured
142 return ServiceMain.getInstance().getClientType();
146 public String getRepositoryDomainName() {
147 return tenantBinding.getRepositoryDomain();
151 public String getRepositoryWorkspaceId() {
152 TenantBindingConfigReader tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
153 return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
157 public String getRepositoryWorkspaceName() {
158 //service name is workspace name by convention
159 return serviceBinding.getName();
163 public ServiceBindingType getServiceBinding() {
164 return serviceBinding;
168 public String getDocumentHandlerClass() {
169 if (serviceBinding.getDocumentHandler() == null
170 || serviceBinding.getDocumentHandler().isEmpty()) {
171 String msg = "Missing documentHandler in service binding for "
172 + getServiceName() + " for tenant id=" + getTenantId()
173 + " name=" + getTenantName();
175 throw new IllegalStateException(msg);
177 return serviceBinding.getDocumentHandler().trim();
181 public String getServiceName() {
182 return serviceBinding.getName();
186 public String getDocumentType() {
187 // If they have not overridden the setting, use the type of the service
189 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
193 public void setDocumentType(String docType) {
194 overrideDocumentType = docType;
198 public String getTenantId() {
199 return tenantBinding.getId();
203 public String getTenantName() {
204 return tenantBinding.getName();
208 public abstract IT getInput();
211 public abstract void setInput(IT input);
214 public abstract OT getOutput();
217 public abstract void setOutput(OT output);
220 public Map<String, Object> getProperties() {
225 public void setProperties(Map<String, Object> props) {
226 properties.putAll(props);
229 public Object getProperty(String name) {
230 return properties.get(name);
233 public void setProperty(String name, Object o) {
234 properties.put(name, o);
236 private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
238 private String retrieveTenantId() throws UnauthorizedException {
240 String tenantId = null;
241 Subject caller = null;
242 Set<Group> groups = null;
244 caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
245 if (caller == null) {
246 //logger.warn("security not enabled...");
249 groups = caller.getPrincipals(Group.class);
250 if (groups != null && groups.size() == 0) {
251 //TODO: find out why subject is not null
252 if (logger.isDebugEnabled()) {
253 logger.debug("no tenant(s) found!");
257 } catch (PolicyContextException pce) {
258 String msg = "Could not retrieve principal information";
259 logger.error(msg, pce);
260 throw new UnauthorizedException(msg);
262 for (Group g : groups) {
263 if ("Tenants".equals(g.getName())) {
264 Enumeration members = g.members();
265 while (members.hasMoreElements()) {
266 CSpaceTenant tenant = (CSpaceTenant) members.nextElement();
267 tenantId = tenant.getId();
268 if (logger.isDebugEnabled()) {
269 logger.debug("found tenant id=" + tenant.getId()
270 + " name=" + tenant.getName());
275 //TODO: if a user is associated with more than one tenants, the tenant
276 //id should be matched with sent over the wire
277 if (tenantId == null) {
278 String msg = "Could not find tenant context";
280 throw new UnauthorizedException(msg);
286 public String toString() {
287 StringBuilder msg = new StringBuilder();
288 msg.append("AbstractServiceContext [");
289 msg.append("service name=" + serviceBinding.getName() + " ");
290 msg.append("service version=" + serviceBinding.getVersion() + " ");
291 msg.append("tenant id=" + tenantBinding.getId() + " ");
292 msg.append("tenant name=" + tenantBinding.getName() + " ");
293 msg.append(tenantBinding.getDisplayName() + " ");
294 msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
295 for (Map.Entry<String, Object> entry : properties.entrySet()) {
296 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
299 return msg.toString();