blob: d057a9dec0c15c0a9a5d7d67a9e485018d6ab617 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.chemistry.opencmis.server.impl.webservices;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisFilterNotValidException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisVersioningException;
import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisException;
import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisFaultType;
import org.apache.chemistry.opencmis.commons.impl.jaxb.EnumServiceException;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.chemistry.opencmis.commons.server.CmisService;
import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory;
import org.apache.chemistry.opencmis.commons.server.ProgressControlCmisService;
import org.apache.chemistry.opencmis.commons.server.ProgressControlCmisService.Progress;
import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
import org.apache.chemistry.opencmis.server.impl.ServerVersion;
import org.apache.chemistry.opencmis.server.shared.ExceptionHelper;
import org.apache.chemistry.opencmis.server.shared.TempStoreOutputStreamFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
/**
* This class contains operations used by all services.
*/
public abstract class AbstractService {
private static final Logger LOG = LoggerFactory.getLogger(AbstractService.class);
public static final String CALL_CONTEXT_MAP = "org.apache.chemistry.opencmis.callcontext";
/**
* Returns the services factory.
*/
protected CmisServiceFactory getServiceFactory(WebServiceContext wsContext) {
ServletContext servletContext = (ServletContext) wsContext.getMessageContext().get(
MessageContext.SERVLET_CONTEXT);
// get services factory
CmisServiceFactory factory = (CmisServiceFactory) servletContext
.getAttribute(CmisRepositoryContextListener.SERVICES_FACTORY);
if (factory == null) {
throw new CmisRuntimeException("Service factory not available! Configuration problem?");
}
HttpServletResponse httpResp = (HttpServletResponse) wsContext.getMessageContext().get(
MessageContext.SERVLET_RESPONSE);
httpResp.setHeader("Server", ServerVersion.OPENCMIS_SERVER);
return factory;
}
/**
* Creates a CallContext object for the Web Service context.
*/
@SuppressWarnings("unchecked")
protected CallContext createContext(WebServiceContext wsContext, CmisServiceFactory factory, String repositoryId) {
ServletContext servletContext = (ServletContext) wsContext.getMessageContext().get(
MessageContext.SERVLET_CONTEXT);
HttpServletRequest request = (HttpServletRequest) wsContext.getMessageContext().get(
MessageContext.SERVLET_REQUEST);
HttpServletResponse response = (HttpServletResponse) wsContext.getMessageContext().get(
MessageContext.SERVLET_RESPONSE);
CmisVersion cmisVersion = (CmisVersion) request.getAttribute(CmisWebServicesServlet.CMIS_VERSION);
if (cmisVersion == null) {
throw new CmisRuntimeException("Server configuration issue. CMIS version not set!");
}
TempStoreOutputStreamFactory streamFactoy = TempStoreOutputStreamFactory.newInstance(factory, repositoryId);
CallContextImpl context = new CallContextImpl(CallContext.BINDING_WEBSERVICES, cmisVersion, repositoryId,
servletContext, request, response, factory, streamFactoy);
Map<String, List<String>> headers = (Map<String, List<String>>) wsContext.getMessageContext().get(
MessageContext.HTTP_REQUEST_HEADERS);
if (headers != null) {
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
if (header.getKey().equalsIgnoreCase("Accept-Language") && header.getValue() != null
&& !header.getValue().isEmpty()) {
context.setAcceptLanguage(header.getValue().get(0));
break;
}
}
}
MessageContext mc = wsContext.getMessageContext();
Map<String, String> callContextMap = (Map<String, String>) mc.get(CALL_CONTEXT_MAP);
if (callContextMap != null) {
for (Map.Entry<String, String> e : callContextMap.entrySet()) {
context.put(e.getKey(), e.getValue());
}
}
return context;
}
/**
* Returns the CMIS version.
*/
protected CmisVersion getCmisVersion(WebServiceContext wsContext) {
HttpServletRequest request = (HttpServletRequest) wsContext.getMessageContext().get(
MessageContext.SERVLET_REQUEST);
return (CmisVersion) request.getAttribute(CmisWebServicesServlet.CMIS_VERSION);
}
/**
* Returns the {@link CmisService} object.
*/
protected CmisService getService(WebServiceContext wsContext, String repositoryId) {
CmisServiceFactory factory = getServiceFactory(wsContext);
CallContext context = createContext(wsContext, factory, repositoryId);
return factory.getService(context);
}
/**
* Determines if the processing should be stopped before the service method
* is called.
*
* @return {@code true} if the processing should be stopped, {@code false}
* otherwise
*/
protected boolean stopBeforeService(CmisService service) {
if (!(service instanceof ProgressControlCmisService)) {
return false;
}
return ((ProgressControlCmisService) service).beforeServiceCall() == Progress.STOP;
}
/**
* Determines if the processing should be stopped after the service method
* is called.
*
* @return {@code true} if the processing should be stopped, {@code false}
* otherwise
*/
protected boolean stopAfterService(CmisService service) {
if (!(service instanceof ProgressControlCmisService)) {
return false;
}
return ((ProgressControlCmisService) service).afterServiceCall() == Progress.STOP;
}
/**
* Closes the service instance.
*/
protected void closeService(CmisService service) {
if (service != null) {
service.close();
}
}
/**
* Converts a CMIS exception to the appropriate Web Service exception.
*/
protected CmisException convertException(Exception ex) {
CmisFaultType fault = new CmisFaultType();
fault.setMessage("Unknown exception");
fault.setCode(BigInteger.ZERO);
fault.setType(EnumServiceException.RUNTIME);
if (ex != null) {
if (ex instanceof CmisBaseException) {
fault.setCode(((CmisBaseException) ex).getCode());
fault.setMessage(ex.getMessage());
if (ex instanceof CmisConstraintException) {
fault.setType(EnumServiceException.CONSTRAINT);
} else if (ex instanceof CmisContentAlreadyExistsException) {
fault.setType(EnumServiceException.CONTENT_ALREADY_EXISTS);
} else if (ex instanceof CmisFilterNotValidException) {
fault.setType(EnumServiceException.FILTER_NOT_VALID);
} else if (ex instanceof CmisInvalidArgumentException) {
fault.setType(EnumServiceException.INVALID_ARGUMENT);
} else if (ex instanceof CmisNameConstraintViolationException) {
fault.setType(EnumServiceException.NAME_CONSTRAINT_VIOLATION);
} else if (ex instanceof CmisNotSupportedException) {
fault.setType(EnumServiceException.NOT_SUPPORTED);
} else if (ex instanceof CmisObjectNotFoundException) {
fault.setType(EnumServiceException.OBJECT_NOT_FOUND);
} else if (ex instanceof CmisPermissionDeniedException) {
fault.setType(EnumServiceException.PERMISSION_DENIED);
} else if (ex instanceof CmisStorageException) {
LOG.error(ex.getMessage(), ex);
fault.setType(EnumServiceException.STORAGE);
} else if (ex instanceof CmisStreamNotSupportedException) {
fault.setType(EnumServiceException.STREAM_NOT_SUPPORTED);
} else if (ex instanceof CmisUpdateConflictException) {
fault.setType(EnumServiceException.UPDATE_CONFLICT);
} else if (ex instanceof CmisVersioningException) {
fault.setType(EnumServiceException.VERSIONING);
} else {
LOG.error(ex.getMessage(), ex);
}
} else {
fault.setMessage("An error occurred!");
if (ex instanceof IOException) {
LOG.warn(ex.getMessage(), ex);
} else {
LOG.error(ex.getMessage(), ex);
}
}
Node node = ExceptionHelper.getStacktraceAsNode(ex);
if (node != null) {
fault.getAny().add(node);
}
}
return new CmisException(fault.getMessage(), fault, ex);
}
}