Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ It's a maven project. Just run
mvn clean install
```
## Usage
This service uses a threadpool to load files at startup. To configure the thread pool size, use `THREAD_POOL_SIZE` env variable.
By default, the thread pool size is 100.

The configuration file is `/src/main/webapp/WEB_INF/classes/repository.properties`.
```bash
# ServiceFactory Implementation class
Expand Down
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<build-version>1.0.0-SNAPSHOT</build-version>
<junit.version>4.13.1</junit.version>
<slf4j.version>1.7.5</slf4j.version>
<commonsio.version>2.4</commonsio.version>
<commonsio.version>2.7</commonsio.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
Expand All @@ -36,6 +36,7 @@
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifestEntries>
<Bundle-Name>fr.mgdis.lightweightcmis</Bundle-Name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.CreatablePropertyTypes;
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
Expand Down Expand Up @@ -70,6 +72,41 @@ public BaseServiceValidatorImpl(StoreManager sm) {
fStoreManager = sm;
}

/**
* Check if repository is known and that object exists. To avoid later calls
* to again retrieve the object from the id return the retrieved object for
* later use.
*
* @param repositoryId
* repository id
* @param objectId
* object id
* @param action
* cmis action
* @return object for objectId
*/
protected StoredObject checkStandardParameters(String repositoryId, String objectId, String action) {
// consider idempotency for many deleteTree
if (!"deleteTree".equals(action)) {
return checkStandardParameters(repositoryId, objectId);
}
if (null == repositoryId) {
throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
}

if (null == objectId) {
throw new CmisInvalidArgumentException(OBJECT_ID_CANNOT_BE_NULL);
}

ObjectStore objStore = fStoreManager.getObjectStore(repositoryId);

if (objStore == null) {
throw new CmisObjectNotFoundException(UNKNOWN_REPOSITORY_ID + repositoryId);
}

return objStore.getObjectById(objectId);
}

/**
* Check if repository is known and that object exists. To avoid later calls
* to again retrieve the object from the id return the retrieved object for
Expand Down Expand Up @@ -105,6 +142,28 @@ protected StoredObject checkStandardParameters(String repositoryId, String objec
return so;
}

protected StoredObject checkStandardParametersByPath(String repositoryId, String path, String user, String action) {
// consider idempotency for many deleteTree
if (!"deleteTree".equals(action)) {
return checkStandardParametersByPath(repositoryId, path, user);
}
if (null == repositoryId) {
throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
}

if (null == path) {
throw new CmisInvalidArgumentException("Path parameter cannot be null.");
}

ObjectStore objStore = fStoreManager.getObjectStore(repositoryId);

if (objStore == null) {
throw new CmisObjectNotFoundException(UNKNOWN_REPOSITORY_ID + repositoryId);
}

return objStore.getObjectByPath(path, user);
}

protected StoredObject checkStandardParametersByPath(String repositoryId, String path, String user) {
if (null == repositoryId) {
throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
Expand Down Expand Up @@ -608,8 +667,12 @@ public StoredObject getRenditions(CallContext context, String repositoryId, Stri

public StoredObject getObjectByPath(CallContext context, String repositoryId, String path,
ExtensionsData extension) {

return checkStandardParametersByPath(repositoryId, path, context.getUsername());
Boolean isDeleteTree = false;
if(context.get("httpServletRequest") != null) {
String qs = ((HttpServletRequest) context.get("httpServletRequest")).getQueryString();
isDeleteTree = qs != null && qs.contains("cmisaction=deleteTree");
}
return checkStandardParametersByPath(repositoryId, path, context.getUsername(), isDeleteTree ? "deleteTree" : null);
}


Expand Down Expand Up @@ -647,7 +710,7 @@ public StoredObject deleteObject(CallContext context, String repositoryId, Strin

public StoredObject deleteTree(CallContext context, String repositoryId, String folderId, Boolean allVersions,
UnfileObject unfileObjects, ExtensionsData extension) {
return checkStandardParameters(repositoryId, folderId);
return checkStandardParameters(repositoryId, folderId, "deleteTree");
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,9 @@ public FailedToDeleteData deleteTree(CallContext context, String repositoryId, S
ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);

if (null == so) {
throw new CmisInvalidArgumentException("Cannot delete object with id " + folderId
+ ". Object does not exist.");
// Do not fail on an already deleted object
// consider idempotency for many deleteTree
return result;
}

if (!(so instanceof Folder)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
import org.apache.chemistry.opencmis.inmemory.FilterParser;
import org.apache.chemistry.opencmis.inmemory.storedobj.api.Document;
import org.apache.chemistry.opencmis.inmemory.storedobj.api.Fileable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -48,14 +47,12 @@ public DocumentImpl() { // visibility should be package


public ContentStream getContent() {
return fContent;
return this.fContent;
}


public void setContent(ContentStream content) {
fContent = content;
this.fContent = content;
}


public void fillProperties(Map<String, PropertyData<?>> properties, BindingsObjectFactory objFactory,
List<String> requestedIds) {
Expand All @@ -74,7 +71,8 @@ public void fillProperties(Map<String, PropertyData<?>> properties, BindingsObje
// Set the content related properties
if (FilterParser.isContainedInFilter(PropertyIds.CONTENT_STREAM_FILE_NAME, requestedIds)) {
properties.put(PropertyIds.CONTENT_STREAM_FILE_NAME, objFactory.createPropertyStringData(
PropertyIds.CONTENT_STREAM_FILE_NAME, null != fContent ? fContent.getFileName() : (String) null));
// contentStreamFileName should always reflect the relative path to the file
PropertyIds.CONTENT_STREAM_FILE_NAME, null != fContent ? this.getPath() : (String) null));
}
if (FilterParser.isContainedInFilter(PropertyIds.CONTENT_STREAM_ID, requestedIds)) {
properties.put(PropertyIds.CONTENT_STREAM_ID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ public String getPath() {
}
if (this.getParentId() != null && this.getStore() != null) {
FolderImpl parent = (FolderImpl) this.getStore().getObjectById(this.getParentId());
if (parent == null) {
return null;
}
String path = "/" + this.getName();
if (!parent.getPath().equals("/")) {
path = parent.getPath() + path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@
package org.apache.chemistry.opencmis.inmemory.storedobj.impl;

import java.util.List;
import javax.servlet.http.HttpServletRequest;

import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
import org.apache.chemistry.opencmis.commons.data.Properties;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.chemistry.opencmis.commons.spi.Holder;
import org.apache.chemistry.opencmis.inmemory.server.BaseServiceValidatorImpl;
Expand Down Expand Up @@ -496,7 +501,24 @@ public StoredObject getRenditions(CallContext context, String repositoryId, Stri
public StoredObject getObjectByPath(CallContext context, String repositoryId, String path,
ExtensionsData extension) {

Boolean isDeleteTree = false;
if(context.get("httpServletRequest") != null) {
String qs = ((HttpServletRequest) context.get("httpServletRequest")).getQueryString();
isDeleteTree = qs != null && qs.contains("cmisaction=deleteTree");
}
StoredObject so = super.getObjectByPath(context, repositoryId, path, extension);
// consider idempotency for many deleteTree on the same folder
if (isDeleteTree && so == null) {
// add a dummy already deleted folder
StoredObject odImpl = new StoredObjectImpl();
PropertiesImpl props = new PropertiesImpl();
props.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_ID, "410Gone"));
props.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value()));
props.addProperty(new PropertyIdImpl(PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_FOLDER.value()));
odImpl.setProperties(props.getProperties());
odImpl.setTypeId(BaseTypeId.CMIS_FOLDER.value());
return odImpl;
}
checkReadAccess(repositoryId, context.getUsername(), so);
return so;
}
Expand Down Expand Up @@ -594,6 +616,10 @@ public StoredObject deleteTree(CallContext context, String repositoryId, String
UnfileObject unfileObjects, ExtensionsData extension) {

StoredObject so = super.deleteTree(context, repositoryId, folderId, allVersions, unfileObjects, extension);
// consider idempotency for many deleteTree on the same folder
if (so == null) {
return null;
}
checkWriteAccess(repositoryId, context.getUsername(), so);
return so;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ public ContentStream getContent(StoredObject so, long offset, long length) {
ContentStream contentStream = content.getContent();
if (null == contentStream && so.getId().length() <= 3) {
return null;
} else if (offset <= 0 && length < 0) {
} else if (this.persistenceManager != null) {
return this.persistenceManager.readContent(
this.persistenceManager.getFile(so, fStoredObjectMap),
false);
Expand All @@ -1190,6 +1190,12 @@ public ContentStream getContent(StoredObject so, long offset, long length) {
}

public ContentStream setContent(StoredObject so, ContentStream contentStream) {
if (contentStream == null &&
so instanceof Content &&
((Content) so).getContent() != null &&
((Content) so).getContent().getFileName() != null) {
so.getStore().getPersistenceManager().deleteFromDisk(so);
}
if (contentStream == null) return null;
String fileName = contentStream.getFileName();
try {
Expand Down Expand Up @@ -1221,18 +1227,18 @@ public ContentStream setContent(StoredObject so, ContentStream contentStream) {
so.setId(id + "." + extension);
}
}
fileName = so.getStore().getPersistenceManager()
.getFile(so, fStoredObjectMap).getAbsolutePath();
newContent.setPersistencemanager(so.getStore()
.getPersistenceManager());
newContent.setFileName(fileName);
String mimeType = contentStream.getMimeType();
if (null == mimeType || mimeType.length() <= 0) {
mimeType = "application/octet-stream"; // use as
// fallback
}
newContent.setMimeType(mimeType);
newContent.setLastModified(new GregorianCalendar());
fileName = so.getStore().getPersistenceManager()
.getFile(so, fStoredObjectMap).getAbsolutePath();
newContent.setFileName(fileName);
try {
newContent.setContent(contentStream.getStream());
} catch (IOException e) {
Expand Down
Loading