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.AuthN;
37 import org.collectionspace.authentication.CSpaceTenant;
39 import org.collectionspace.services.common.ClientType;
40 import org.collectionspace.services.common.ServiceMain;
41 import org.collectionspace.services.common.config.PropertyItemUtils;
42 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
43 import org.collectionspace.services.common.document.DocumentHandler;
44 import org.collectionspace.services.common.document.ValidatorHandler;
45 import org.collectionspace.services.common.security.UnauthorizedException;
46 import org.collectionspace.services.common.service.ObjectPartType;
47 import org.collectionspace.services.common.service.ServiceBindingType;
48 import org.collectionspace.services.common.service.ServiceObjectType;
49 import org.collectionspace.services.common.tenant.TenantBindingType;
50 import org.collectionspace.services.common.types.PropertyItemType;
51 import org.collectionspace.services.common.types.PropertyType;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 * AbstractServiceContext
58 * $LastChangedRevision: $
61 public abstract class AbstractServiceContextImpl<IT, OT>
62 implements ServiceContext<IT, OT> {
64 final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
65 Map<String, Object> properties = new HashMap<String, Object>();
66 Map<String, ObjectPartType> objectPartMap = new HashMap<String, ObjectPartType>();
67 private ServiceBindingType serviceBinding;
68 private TenantBindingType tenantBinding;
69 private String overrideDocumentType = null;
70 private List<ValidatorHandler> valHandlers = null;
71 private DocumentHandler docHandler = null;
73 public AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
74 TenantBindingConfigReaderImpl tReader =
75 ServiceMain.getInstance().getTenantBindingConfigReader();
76 //FIXME retrieveTenantId is not working consistently in non-auth mode
77 //TODO: get tenant binding from security context
78 String tenantId = retrieveTenantId();
79 if (tenantId == null) {
80 //for testing purposes
81 tenantId = "1"; //hardcoded for movingimages.us
83 tenantBinding = tReader.getTenantBinding(tenantId);
84 if (tenantBinding == null) {
85 String msg = "No tenant binding found for tenantId=" + tenantId
86 + " while processing request for service= " + serviceName;
88 throw new IllegalStateException(msg);
90 serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
91 if (serviceBinding == null) {
92 String msg = "No service binding found while processing request for "
93 + serviceName + " for tenant id=" + getTenantId()
94 + " name=" + getTenantName();
96 throw new IllegalStateException(msg);
98 if (logger.isDebugEnabled()) {
99 logger.debug("tenantId=" + tenantId
100 + " service binding=" + serviceBinding.getName());
105 * getCommonPartLabel get common part label
109 public String getCommonPartLabel() {
110 return getCommonPartLabel(getServiceName());
114 * getCommonPartLabel get common part label
117 public String getCommonPartLabel(String schemaName) {
118 return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
122 public Map<String, ObjectPartType> getPartsMetadata() {
123 if (objectPartMap.size() != 0) {
124 return objectPartMap;
126 ServiceBindingUtils.getPartsMetadata(getServiceBinding(), objectPartMap);
127 return objectPartMap;
130 public List<PropertyItemType> getPropertiesForPart(String partLabel) {
131 Map<String, ObjectPartType> partMap = getPartsMetadata();
132 ObjectPartType part = partMap.get(partLabel);
134 throw new RuntimeException("No such part found: "+partLabel);
136 List<PropertyType> propNodeList = part.getProperties();
137 return propNodeList.isEmpty()?null:propNodeList.get(0).getItem();
140 public List<String> getPropertyValuesForPart(String partLabel, String propName) {
141 List<PropertyItemType> allProps = getPropertiesForPart(partLabel);
142 return PropertyItemUtils.getPropertyValuesByName(allProps, propName);
145 public List<String> getAllPartsPropertyValues(String propName) {
146 return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName);
149 public String getServiceBindingPropertyValue(String propName) {
150 return ServiceBindingUtils.getPropertyValue(getServiceBinding(), propName);
153 public List<PropertyItemType> getCommonPartProperties() {
154 return getPropertiesForPart(getCommonPartLabel());
157 public List<String> getCommonPartPropertyValues(String propName) {
158 return getPropertyValuesForPart(getCommonPartLabel(), propName);
162 public String getQualifiedServiceName() {
163 return TenantBindingConfigReaderImpl.getTenantQualifiedServiceName(getTenantId(), getServiceName());
167 public String getRepositoryClientName() {
168 if (serviceBinding.getRepositoryClient() == null) {
171 return serviceBinding.getRepositoryClient().trim();
175 public ClientType getRepositoryClientType() {
176 //assumption: there is only one repository client configured
177 return ServiceMain.getInstance().getClientType();
181 public String getRepositoryDomainName() {
182 return tenantBinding.getRepositoryDomain();
186 public String getRepositoryWorkspaceId() {
187 TenantBindingConfigReaderImpl tbConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
188 return tbConfigReader.getWorkspaceId(getTenantId(), getServiceName());
192 public String getRepositoryWorkspaceName() {
193 //service name is workspace name by convention
194 return serviceBinding.getName();
198 public ServiceBindingType getServiceBinding() {
199 return serviceBinding;
203 public String getServiceName() {
204 return serviceBinding.getName();
208 public String getDocumentType() {
209 // If they have not overridden the setting, use the type of the service
211 return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
215 public void setDocumentType(String docType) {
216 overrideDocumentType = docType;
220 public String getTenantId() {
221 return tenantBinding.getId();
225 public String getTenantName() {
226 return tenantBinding.getName();
230 public abstract IT getInput();
233 public abstract void setInput(IT input);
236 public abstract OT getOutput();
239 public abstract void setOutput(OT output);
242 public Map<String, Object> getProperties() {
247 public void setProperties(Map<String, Object> props) {
248 properties.putAll(props);
251 public Object getProperty(String name) {
252 return properties.get(name);
255 public void setProperty(String name, Object o) {
256 properties.put(name, o);
260 private String retrieveTenantId() throws UnauthorizedException {
262 String[] tenantIds = AuthN.get().getTenantIds();
263 if (tenantIds.length == 0) {
264 String msg = "Could not find tenant context";
266 throw new UnauthorizedException(msg);
268 //TODO: if a user is associated with more than one tenants, the tenant
269 //id should be matched with the one sent over the wire
274 public DocumentHandler getDocumentHandler() throws Exception {
275 if (docHandler != null) {
278 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
279 Class c = tccl.loadClass(getDocumentHandlerClass());
280 if (DocumentHandler.class.isAssignableFrom(c)) {
281 docHandler = (DocumentHandler) c.newInstance();
283 throw new IllegalArgumentException("Not of type "
284 + DocumentHandler.class.getCanonicalName());
286 docHandler.setServiceContext(this);
290 private String getDocumentHandlerClass() {
291 if (serviceBinding.getDocumentHandler() == null
292 || serviceBinding.getDocumentHandler().isEmpty()) {
293 String msg = "Missing documentHandler in service binding for "
294 + getServiceName() + " for tenant id=" + getTenantId()
295 + " name=" + getTenantName();
297 throw new IllegalStateException(msg);
299 return serviceBinding.getDocumentHandler().trim();
303 public List<ValidatorHandler> getValidatorHandlers() throws Exception {
304 if (valHandlers != null) {
307 List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
308 List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
309 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
310 for (String clazz : handlerClazzes) {
311 clazz = clazz.trim();
312 Class c = tccl.loadClass(clazz);
313 if (ValidatorHandler.class.isAssignableFrom(c)) {
314 handlers.add((ValidatorHandler) c.newInstance());
317 valHandlers = handlers;
322 public String toString() {
323 StringBuilder msg = new StringBuilder();
324 msg.append("AbstractServiceContext [");
325 msg.append("service name=" + serviceBinding.getName() + " ");
326 msg.append("service version=" + serviceBinding.getVersion() + " ");
327 msg.append("tenant id=" + tenantBinding.getId() + " ");
328 msg.append("tenant name=" + tenantBinding.getName() + " ");
329 msg.append(tenantBinding.getDisplayName() + " ");
330 msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
331 for (Map.Entry<String, Object> entry : properties.entrySet()) {
332 msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
335 return msg.toString();