/** * Copyright (C) 2010 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xcmis.wssoap.impl; import org.xcmis.core.CmisAccessControlListType; import org.xcmis.core.CmisAllowableActionsType; import org.xcmis.core.CmisObjectType; import org.xcmis.core.CmisPropertiesType; import org.xcmis.core.CmisRenditionType; import org.xcmis.core.EnumIncludeRelationships; import org.xcmis.core.EnumUnfileObject; import org.xcmis.core.EnumVersioningState; import org.xcmis.messaging.CmisContentStreamType; import org.xcmis.messaging.CmisExtensionType; import org.xcmis.messaging.DeleteTreeResponse; import org.xcmis.soap.CmisException; import org.xcmis.soap.ObjectServicePort; import org.xcmis.spi.BaseContentStream; import org.xcmis.spi.ChangeTokenHolder; import org.xcmis.spi.CmisConstants; import org.xcmis.spi.CmisRegistry; import org.xcmis.spi.Connection; import org.xcmis.spi.ConstraintException; import org.xcmis.spi.ContentStream; import org.xcmis.spi.model.IncludeRelationships; import org.xcmis.spi.model.UnfileObject; import org.xcmis.spi.model.VersioningState; import org.xcmis.spi.utils.Logger; import org.xcmis.spi.utils.MimeType; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.util.List; import javax.activation.DataHandler; import javax.activation.DataSource; /** * @author <a href="mailto:max.shaposhnik@exoplatform.com">Max Shaposhnik</a> * @version $Id: ObjectServicePortImpl.java 2 2010-02-04 17:21:49Z andrew00x $ */ @javax.jws.WebService(// name = "ObjectServicePort", serviceName = "ObjectService", // portName = "ObjectServicePort", // targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", // wsdlLocation = "/wsdl/CMISWS-Service.wsdl" //, // endpointInterface = "org.xcmis.soap.ObjectServicePort" ) public class ObjectServicePortImpl implements ObjectServicePort { /** Logger. */ private static final Logger LOG = Logger.getLogger(ObjectServicePortImpl.class); /** * Constructs instance of <code>ObjectServicePortImpl</code> . * */ public ObjectServicePortImpl() { } /** * {@inheritDoc} */ public void createDocument(String repositoryId, // CmisPropertiesType properties, // String folderId, // CmisContentStreamType contentStream, // EnumVersioningState versioningState, // List<String> policies, // CmisAccessControlListType addACEs, // CmisAccessControlListType removeACEs, // javax.xml.ws.Holder<CmisExtensionType> extension, // javax.xml.ws.Holder<String> objectId) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation createDocument"); } ContentStream cs = null; Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); if (contentStream != null) { cs = new BaseContentStream(contentStream.getStream().getInputStream(), contentStream.getFilename(), MimeType .fromString(contentStream.getMimeType())); } objectId.value = conn.createDocument(folderId, // TypeConverter.getPropertyMap(properties), // cs, // TypeConverter.getListAccessControlEntry(addACEs), // TypeConverter.getListAccessControlEntry(removeACEs), // policies, versioningState == null ? VersioningState.MAJOR : VersioningState.fromValue(versioningState .value()) // ); } catch (Exception e) { LOG.error("Create document error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void createDocumentFromSource(String repositoryId, // String sourceId, // CmisPropertiesType properties, // String folderId, // EnumVersioningState versioningState, // List<String> policies, // CmisAccessControlListType addACEs, // CmisAccessControlListType removeACEs, // javax.xml.ws.Holder<CmisExtensionType> extension, // javax.xml.ws.Holder<String> objectId) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation createDocumentFromSource"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); objectId.value = conn.createDocumentFromSource(sourceId, // folderId, // TypeConverter.getPropertyMap(properties), // TypeConverter.getListAccessControlEntry(addACEs), // TypeConverter.getListAccessControlEntry(removeACEs), // policies, versioningState == null ? VersioningState.MAJOR : VersioningState.fromValue(versioningState .value()) // ); } catch (Exception e) { LOG.error("Create document from source error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void createFolder(String repositoryId, // CmisPropertiesType properties, // String folderId, // List<String> policies, // CmisAccessControlListType addACEs, // CmisAccessControlListType removeACEs, // javax.xml.ws.Holder<CmisExtensionType> extension, // javax.xml.ws.Holder<String> objectId) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation createFolder"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); objectId.value = conn.createFolder(folderId, TypeConverter.getPropertyMap(properties), TypeConverter .getListAccessControlEntry(addACEs), // TypeConverter.getListAccessControlEntry(removeACEs), // policies); } catch (Exception e) { LOG.error("Create folder error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void createPolicy(String repositoryId, // CmisPropertiesType properties, // String folderId, // List<String> policies, // CmisAccessControlListType addACEs, // CmisAccessControlListType removeACEs, // javax.xml.ws.Holder<CmisExtensionType> extension, // javax.xml.ws.Holder<String> objectId) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation createPolicy"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); objectId.value = conn.createPolicy(folderId, TypeConverter.getPropertyMap(properties), TypeConverter .getListAccessControlEntry(addACEs), // TypeConverter.getListAccessControlEntry(removeACEs), policies); } catch (Exception e) { LOG.error("Create policy error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void createRelationship(String repositoryId, // CmisPropertiesType properties, // List<String> policies, // CmisAccessControlListType addACEs, // CmisAccessControlListType removeACEs, // javax.xml.ws.Holder<CmisExtensionType> extension, // javax.xml.ws.Holder<String> objectId) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation createRelationship"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); objectId.value = conn.createRelationship(TypeConverter.getPropertyMap(properties), TypeConverter .getListAccessControlEntry(addACEs), // TypeConverter.getListAccessControlEntry(removeACEs), policies); } catch (Exception e) { LOG.error("Create relationship error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void deleteContentStream(String repositoryId, javax.xml.ws.Holder<String> documentId, javax.xml.ws.Holder<String> changeToken, javax.xml.ws.Holder<CmisExtensionType> extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation deleteContentStream"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); ChangeTokenHolder hold = new ChangeTokenHolder(); if (changeToken != null) { hold.setValue(changeToken.value); } documentId.value = conn.deleteContentStream(documentId.value, // changeToken != null ? hold : null); } catch (Exception e) { LOG.error("Delete document's content error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public CmisExtensionType deleteObject(String repositoryId, String objectId, Boolean allVersions, CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation deleteObject"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); conn.deleteObject(objectId, allVersions); } catch (Exception e) { LOG.error("Delete object error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } return new CmisExtensionType(); } /** * {@inheritDoc} */ public DeleteTreeResponse.FailedToDelete deleteTree(String repositoryId, // String folderId, // Boolean allVersions, // EnumUnfileObject unfileObject, // Boolean continueOnFailure, // CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation deleteTree"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); DeleteTreeResponse.FailedToDelete failed = new DeleteTreeResponse.FailedToDelete(); failed.getObjectIds().addAll(conn.deleteTree(folderId, // allVersions, // unfileObject == null ? UnfileObject.DELETE : UnfileObject.fromValue(unfileObject.value()), // continueOnFailure == null ? false : continueOnFailure)); return failed; } catch (Exception e) { LOG.error("Delete folder tree error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId, CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation getAllowableActions"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); return TypeConverter.getCmisAllowableActionsType(conn.getAllowableActions(objectId)); } catch (Exception e) { LOG.error("Get allowable actions error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public CmisContentStreamType getContentStream(String repositoryId, // String objectId, // String streamId, // java.math.BigInteger offset, // java.math.BigInteger length, // CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation getContentStream"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); ContentStream cs = conn.getContentStream(objectId, streamId); String type = cs.getMediaType() == null ? "application/octet-stream" : cs.getMediaType().toString(); CmisContentStreamType result = new CmisContentStreamType(); result.setFilename(cs.getFileName()); result.setMimeType(type); if (cs.length() > 0) { // Not clear need to set length of full content or part of it for range requests. result.setLength(BigInteger.valueOf(cs.length())); } InputStream in = cs.getStream(); if (offset == null && length == null) { result.setStream(new DataHandler(new InputStreamDataSource(in, type))); } else { result.setStream(new DataHandler(new InputStreamDataSource( new ContentRange(in, offset == null ? 0 : offset.longValue(), length == null ? -1 : length.longValue()), type))); } return result; } catch (Exception e) { LOG.error("Get content stream error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } private static class InputStreamDataSource implements DataSource { private final InputStream in; private final String type; private InputStreamDataSource(InputStream in, String type) { this.in = in; this.type = type; } @Override public InputStream getInputStream() throws IOException { return in; } @Override public OutputStream getOutputStream() throws IOException { return null; } @Override public String getContentType() { return type; } @Override public String getName() { return null; } } private static class ContentRange extends FilterInputStream { private long remaining; private final boolean needTruncate; private ContentRange(InputStream in, long offset, long length) throws IOException, ConstraintException { super(in); if (offset > 0) { if (in.skip(offset) < offset) { throw new ConstraintException("offset value is greater than the size of the content. "); } } needTruncate = length >= 0; remaining = length; } @Override public int read() throws IOException { if (needTruncate) { if (remaining > 0) { int b = super.read(); remaining -= 1; return b; } return -1; } return super.read(); } @Override public int read(byte[] b, int off, int len) throws IOException { if (needTruncate) { if (remaining > 0) { int n = super.read(b, off, (int)Math.min(len, remaining)); remaining -= n; return n; } return -1; } return super.read(b, off, len); } } /** * {@inheritDoc} */ public CmisObjectType getObject(String repositoryId, // String objectId, // String propertyFilter, // Boolean includeAllowableActions, // EnumIncludeRelationships includeRelationships, // String renditionFilter, // Boolean includePolicyIds, // Boolean includeACL, // CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation getObject"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); return TypeConverter.getCmisObjectType(conn.getObject(objectId, // includeAllowableActions == null ? false : includeAllowableActions, // includeRelationships == null ? IncludeRelationships.NONE : IncludeRelationships .fromValue(includeRelationships.value()), // includePolicyIds == null ? false : includePolicyIds, // includeACL == null ? false : includeACL, // false, propertyFilter, // renditionFilter)); } catch (Exception e) { LOG.error("Get object error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public CmisObjectType getObjectByPath(String repositoryId, // String path, // String propertyFilter, // Boolean includeAllowableActions, // EnumIncludeRelationships includeRelationships, // String renditionFilter, // Boolean includePolicyIds, // Boolean includeACL, // CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation getObjectByPath"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); return TypeConverter.getCmisObjectType(conn.getObjectByPath(path, // includeAllowableActions == null ? false : includeAllowableActions, // includeRelationships == null ? IncludeRelationships.NONE : IncludeRelationships .fromValue(includeRelationships.value()), // includePolicyIds == null ? false : includePolicyIds, // includeACL == null ? false : includeACL, // false, propertyFilter, // renditionFilter)); } catch (Exception e) { LOG.error("Get object by path error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public CmisPropertiesType getProperties(String repositoryId, String objectId, String propertyFilter, CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation getProperties"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); return TypeConverter.getCmisPropertiesType(conn.getProperties(objectId, false, propertyFilter)); } catch (Exception e) { LOG.error("Get properties error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public List<CmisRenditionType> getRenditions(String repositoryId, String objectId, String renditionFilter, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation getRenditions"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); return TypeConverter.getCmisRenditionTypeList(conn.getRenditions(objectId, // renditionFilter, // maxItems == null ? CmisConstants.MAX_ITEMS : maxItems.intValue(), // skipCount == null ? 0 : skipCount.intValue())); } catch (Exception e) { LOG.error("Get renditions error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void moveObject(String repositoryId, javax.xml.ws.Holder<String> objectId, String targetFolderId, String sourceFolderId, javax.xml.ws.Holder<CmisExtensionType> extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation moveObject"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); objectId.value = conn.moveObject(objectId.value, targetFolderId, sourceFolderId); } catch (Exception e) { LOG.error("Move object error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void setContentStream(String repositoryId, // javax.xml.ws.Holder<String> documentId, // Boolean overwriteFlag, // javax.xml.ws.Holder<String> changeToken, // CmisContentStreamType contentStream, // javax.xml.ws.Holder<CmisExtensionType> extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation setContentStream"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); ContentStream cs = null; if (contentStream != null) { cs = new BaseContentStream(contentStream.getStream().getInputStream(), contentStream.getFilename(), MimeType .fromString(contentStream.getMimeType())); } ChangeTokenHolder hold = new ChangeTokenHolder(); if (changeToken != null) { hold.setValue(changeToken.value); } documentId.value = conn.setContentStream(documentId.value, // cs, // changeToken == null ? null : hold, // overwriteFlag == null ? true : overwriteFlag); } catch (Exception e) { LOG.error("Set content stream error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } /** * {@inheritDoc} */ public void updateProperties(String repositoryId, // javax.xml.ws.Holder<String> objectId, // javax.xml.ws.Holder<String> changeToken, // CmisPropertiesType properties, // javax.xml.ws.Holder<CmisExtensionType> extension) throws CmisException { if (LOG.isDebugEnabled()) { LOG.debug("Executing operation updateProperties"); } Connection conn = null; try { conn = CmisRegistry.getInstance().getConnection(repositoryId); ChangeTokenHolder hold = new ChangeTokenHolder(); if (changeToken != null) { hold.setValue(changeToken.value); } objectId.value = conn.updateProperties(objectId.value, // changeToken.value == null ? null : hold, // TypeConverter.getPropertyMap(properties)); } catch (Exception e) { LOG.error("Update properties error: " + e.getMessage(), e); throw ExceptionFactory.generateException(e); } finally { if (conn != null) { conn.close(); } } } }