package org.ow2.bonita.services;
/**
* Copyright (C) 2011 BonitaSoft S.A.
* BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2.0 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import javax.activation.MimeType;
import javax.activation.MimeTypeParseException;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.ItemIterable;
import org.apache.chemistry.opencmis.client.api.ObjectId;
import org.apache.chemistry.opencmis.client.api.QueryResult;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.api.SessionFactory;
import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.enums.BindingType;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.ow2.bonita.DocumentAlreadyExistsException;
import org.ow2.bonita.DocumentNotFoundException;
import org.ow2.bonita.DocumentationCreationException;
import org.ow2.bonita.FolderAlreadyExistsException;
import org.ow2.bonita.facade.uuid.ProcessDefinitionUUID;
import org.ow2.bonita.facade.uuid.ProcessInstanceUUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* CMIS implementation of the document manager
*
* @author Baptiste Mesta
*
*/
public class CMISDocumentManager implements DocumentationManager {
private static ThreadLocal<SimpleDateFormat> CMIS_DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
protected synchronized SimpleDateFormat initialValue() {
SimpleDateFormat gmtTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'");
gmtTime.setTimeZone(TimeZone.getTimeZone("GMT"));
return gmtTime;
}
};
private final String binding;
private final String url;
private final String repositoryId;
private final String defaultUsername;
private final String defaultPassword;
private String rootFolderId;
private Session session;
private final Map<String,Session> sessionsMap = new HashMap<String, Session>();
private final boolean isServerUseLocalTime;
private final Map<ProcessDefinitionUUID,String> processDefinitionMap = new HashMap<ProcessDefinitionUUID, String>();
private final Map<ProcessInstanceUUID,String> processInstanceMap = new HashMap<ProcessInstanceUUID, String>();
private static final Logger LOGGER = LoggerFactory.getLogger(CMISDocumentManager.class);
public CMISDocumentManager(final String binding, final String url, final String repositoryId, final Boolean isServerUseLocalTime, String defaultUsername, String defaultPassword) {
this.binding = binding;
this.url = url;
this.repositoryId = repositoryId;
this.isServerUseLocalTime = isServerUseLocalTime;
this.defaultUsername = defaultUsername;
this.defaultPassword = defaultPassword;
java.net.CookieManager cm = new java.net.CookieManager(null, java.net.CookiePolicy.ACCEPT_ALL);
java.net.CookieHandler.setDefault(cm);
}
public synchronized Session createSessionById(final String repositoryId, String userId2) {
final SessionFactory f = SessionFactoryImpl.newInstance();
// String userId;
// if (userId2 == null) {
// userId = BonitaConstants.SYSTEM_USER;
// try {
// userId = EnvTool.getUserId();
// } catch (Exception e) {}
// } else {
// userId = userId2;
// }
// String password = "";
// if (!BonitaConstants.SYSTEM_USER.equals(userId)) {
// final IdentityService identityService = EnvTool.getIdentityService();
// final User user = identityService.findUserByUsername(userId);
// if (user == null) {
// throw new BonitaRuntimeException(userId + " not found");
// }
// password = user.getPassword();
//
// StringBuilder usernameAndDomain = new StringBuilder();
// usernameAndDomain.append(userId);
// usernameAndDomain.append("@");
// usernameAndDomain.append(DomainOwner.getDomain());
// userId = usernameAndDomain.toString();
// }
String userId = null;
String password = defaultPassword;
if (userId2 != null) {
userId = userId2;
} else {
userId = defaultUsername;
}
Session session = sessionsMap.get(userId);
// if (session == null) {
final Map<String, String> parameter = fixParameters(userId, password);
parameter.put(SessionParameter.REPOSITORY_ID, repositoryId);
session = f.createSession(parameter);
if ( rootFolderId == null ) {
final CmisObject rootFolder = session.getObjectByPath("/");
this.rootFolderId = rootFolder.getId();
}
sessionsMap.put(userId, session);
// }
return session;
}
public synchronized Session getSession() {
session = createSessionById(repositoryId, null);
return session;
}
public synchronized Session getSession(String userId) {
session = createSessionById(repositoryId, userId);
return session;
}
protected Map<String, String> fixParameters(final String username, final String password) {
final Map<String, String> parameter = new HashMap<String, String>();
if ("ATOM".equals(binding)) {
parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
} else if (binding.toLowerCase().startsWith("WebService".toLowerCase())) {
parameter.put(SessionParameter.WEBSERVICES_ACL_SERVICE, url + "/ACLService/AccessControlServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, url + "/DiscoveryService/DiscoveryServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, url + "/MultiFilingService/MultiFilingServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, url + "/NavigationService/NavigationServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, url + "/ObjectService/ObjectServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, url + "/PolicyService/PolicyServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, url + "/RelationshipService/RelationshipServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, url + "/RepositoryService/RepositoryServicePort?wsdl");
parameter.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, url + "/VersioningService/VersioningServicePort?wsdl");
parameter.put(SessionParameter.AUTH_HTTP_BASIC, "false");
parameter.put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, "false");
parameter.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value());
}
parameter.put(SessionParameter.ATOMPUB_URL, url);
parameter.put(SessionParameter.USER, username);
parameter.put(SessionParameter.PASSWORD, password);
return parameter;
}
public boolean folderExists(final String folderName) {
try {
final CmisObject object = getSession().getObjectByPath("/" + folderName);
return object instanceof Folder;
} catch (final CmisBaseException e) {
return false;
}
}
public boolean folderExists(final String folderName, final String parentFolderId) {
try {
final Session session2 = getSession();
final Folder parentFolder = (Folder) session2.getObject(session2.createObjectId(parentFolderId));
for (final CmisObject object : parentFolder.getChildren()) {
if (object instanceof Folder && folderName.equals(object.getName())) {
return true;
}
}
} catch (final CmisBaseException e) {
e.printStackTrace();
}
return false;
}
public org.ow2.bonita.services.Folder createFolder(final String folderName) throws FolderAlreadyExistsException {
getSession();
try {
final org.ow2.bonita.services.Folder createFolder = createFolder(folderName, rootFolderId);
return createFolder;
} catch (final CmisRuntimeException e) {
throw new FolderAlreadyExistsException(folderName, e);
}
}
public org.ow2.bonita.services.Folder createFolder(final String folderName, final String parentFolderId) throws FolderAlreadyExistsException {
final Session session = getSession();
final Folder folder;
try{
folder = (Folder) session.getObject(session.createObjectId(parentFolderId));
}catch(CmisRuntimeException e) {
throw new FolderAlreadyExistsException(folderName, e);
}
final HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put(PropertyIds.NAME, folderName);
properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder");
properties.put(PropertyIds.PARENT_ID, parentFolderId);
try {
final Folder child = folder.createFolder(properties, null, null, null, session.getDefaultContext());
return convertFolder(child);
} catch (final CmisRuntimeException e) {
throw new FolderAlreadyExistsException(folderName, e);
}
}
public Document createDocument(final String name, final String parentFolderId)
throws DocumentationCreationException, DocumentAlreadyExistsException {
final Session session = getSession();
return createDocument(session, name, parentFolderId);
}
/**
* @param session
* @param name
* @param parentFolderId
* @return
* @throws DocumentationCreationException
*/
private Document createDocument(final Session session, final String name, final String parentFolderId)
throws DocumentationCreationException {
final Folder folder = (Folder) session.getObject(session.createObjectId(parentFolderId));
final Map<String, String> newDocProps = new HashMap<String, String>();
newDocProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
newDocProps.put(PropertyIds.NAME, name);
try {
final org.apache.chemistry.opencmis.client.api.Document doc =
folder.createDocument(newDocProps, null, null, null, null, null, session.getDefaultContext());
return convertDocument(doc);
} catch(final CmisBaseException e){
throw new DocumentationCreationException("Document may alreadyExists: "+name, e);
}
}
public Document getDocument(final String documentId) throws DocumentNotFoundException {
final Session session2 = getSession();
try {
final org.apache.chemistry.opencmis.client.api.Document doc =
(org.apache.chemistry.opencmis.client.api.Document) session2.getObject(session2.createObjectId(documentId));
return convertDocument(doc);
} catch (final CmisObjectNotFoundException e) {
throw new DocumentNotFoundException(documentId, e);
}
}
// TODO throws a DocumentAlreadyExistsException when it exists
public Document createDocument(final String name, final String parentFolderId, final String fileName, final String contentMimeType, final byte[] fileContent) throws DocumentationCreationException {
final Session session = getSession();
return createDocument(session, name, parentFolderId, fileName, contentMimeType, fileContent);
}
/**
* @param session
* @param name
* @param parentFolderId
* @param fileName
* @param contentMimeType
* @param contentSize
* @param fileContent
* @return
* @throws DocumentationCreationException
*/
private Document createDocument(final Session session, final String name, final String parentFolderId, final String fileName,
final String contentMimeType, final byte[] fileContent) throws DocumentationCreationException {
if(contentMimeType != null) {
try {
new MimeType(contentMimeType);
} catch (final MimeTypeParseException e1) {
throw new DocumentationCreationException("Mime type not valid",e1);
}
}
final Folder folder = (Folder) session.getObject(session.createObjectId(parentFolderId));
final Map<String, String> newDocProps = new HashMap<String, String>();
newDocProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
newDocProps.put(PropertyIds.NAME, name);
newDocProps.put(PropertyIds.CONTENT_STREAM_FILE_NAME, fileName);
BigInteger length;
if (fileContent != null && fileContent.length > 0) {
length = BigInteger.valueOf(fileContent.length);
} else {
length = null;
}
final ContentStream contentStream;
if(fileContent == null || fileContent.length <=0){
contentStream = null;
}else{
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileContent);
try {
contentStream = new ContentStreamImpl(fileName, length, contentMimeType, byteArrayInputStream);
} catch(final CmisBaseException e){
throw new DocumentationCreationException("Can't create the content of the document "+name, e);
} finally {
try {
byteArrayInputStream.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
try {
final String id = folder.createDocument(newDocProps, contentStream, null, null, null, null, session.getDefaultContext()).getId();
return convertDocument((org.apache.chemistry.opencmis.client.api.Document) session.getObject(session.createObjectId(id)));
} catch(final CmisBaseException e){
throw new DocumentationCreationException("Document may alreadyExists: "+name, e);
}
}
private org.ow2.bonita.services.Folder convertFolder(final Folder cmisFolder) {
final List<Folder> parents = cmisFolder.getParents();
String parentId;
if (parents != null && parents.size() > 0) {
parentId = parents.get(0).getId();
} else {
parentId = null;
}
final FolderImpl folderImpl = new FolderImpl(cmisFolder.getName(), parentId);
folderImpl.setId(cmisFolder.getId());
return folderImpl;
}
private org.ow2.bonita.services.Document convertDocument(final org.apache.chemistry.opencmis.client.api.Document document) {
Boolean latestVersion = document.isLatestVersion();
Boolean majorVersion = document.isMajorVersion();
Folder folder = document.getParents().get(0);
String path = folder.getPath().substring(1);
String[] split = path.split("/");
ProcessInstanceUUID processInstanceUUID = null;
ProcessDefinitionUUID processDefinitionUUID = null;
if(split.length >= 2){
processDefinitionUUID = new ProcessDefinitionUUID(split[0]);
processInstanceUUID = new ProcessInstanceUUID(split[1]);
}
final DocumentImpl doc = new DocumentImpl(document.getName(),
folder.getId(),
document.getCreatedBy(),
convertDate(document.getCreationDate()),
convertDate(document.getLastModificationDate()),
latestVersion != null ? latestVersion : false,
majorVersion != null ? majorVersion : false,
document.getVersionLabel(),
document.getVersionSeriesId(),
document.getContentStreamFileName(),
document.getContentStreamMimeType(),
document.getContentStreamLength(),
processDefinitionUUID, processInstanceUUID);
doc.setId(document.getId());
return doc;
}
private Date convertDate(GregorianCalendar creationDate) {
Date convertedDate;
if (creationDate != null) {
int rawOffset = 0;
long timeInMillis = creationDate.getTimeInMillis();
if (isServerUseLocalTime) {
//!\ this is a hack, the server should be at GMT 0 and DST = 0 but it's on the local time
TimeZone defaultTimeZone = TimeZone.getDefault();
rawOffset = defaultTimeZone.getRawOffset() + defaultTimeZone.getDSTSavings();
}
convertedDate = new Date (timeInMillis - rawOffset);
} else {
convertedDate = null;
}
return convertedDate;
}
private Date localToServerDate(Date localDate) {
if (!isServerUseLocalTime) { //convert it to GMT 0
TimeZone defaultTimeZone = TimeZone.getDefault();
return new Date(localDate.getTime() - defaultTimeZone.getRawOffset() - defaultTimeZone.getDSTSavings());
} else {
return localDate;
}
}
public List<Document> getChildrenDocuments(final String folderId) {
final Session session2 = getSession();
final Folder folder = (Folder) session2.getObject(session2.createObjectId(folderId));
final List<Document> documents = new ArrayList<Document>();
for (final CmisObject children : folder.getChildren()) {
if (children instanceof org.apache.chemistry.opencmis.client.api.Document) {
documents.add(convertDocument((org.apache.chemistry.opencmis.client.api.Document) children));
}
}
return documents;
}
public List<org.ow2.bonita.services.Folder> getChildrenFolder(final String folderId) {
final Session session2 = getSession();
final Folder folder = (Folder) session2.getObject(session2.createObjectId(folderId));
final List<org.ow2.bonita.services.Folder> subFolders = new ArrayList<org.ow2.bonita.services.Folder>();
for (final CmisObject children : folder.getChildren()) {
if (children instanceof Folder) {
subFolders.add(convertFolder((Folder) children));
}
}
return subFolders;
}
public org.ow2.bonita.services.Folder getRootFolder() {
final Session session2 = getSession();
final Folder folder = (Folder) session2.getObject(session2.createObjectId(rootFolderId));
return convertFolder(folder);
}
public void deleteFolder(final org.ow2.bonita.services.Folder folder) {
final Session session2 = getSession();
String id = folder.getId();
session2.getObject(session2.createObjectId(id)).delete(true);// FIXME
// check
// child
// not
// exists
Entry<ProcessDefinitionUUID, String> entryToDelete = null;
for (Entry<ProcessDefinitionUUID, String> entry : processDefinitionMap.entrySet()) {
if(id.equals(entry.getValue())){
entryToDelete = entry;
break;
}
}
if(entryToDelete != null){
processDefinitionMap.remove(entryToDelete.getKey());
return;
}
Entry<ProcessInstanceUUID, String> entryToDelete2 = null;
for (Entry<ProcessInstanceUUID, String> entry : processInstanceMap.entrySet()) {
if(id.equals(entry.getValue())){
entryToDelete2 = entry;
break;
}
}
if(entryToDelete2 != null){
processInstanceMap.remove(entryToDelete2.getKey());
return;
}
}
public void deleteDocument(final String documentId, final boolean allVersions) throws DocumentNotFoundException {
try {
getSession().getBinding().getObjectService().deleteObject(repositoryId, documentId, allVersions, null);
} catch (final CmisObjectNotFoundException e) {
throw new DocumentNotFoundException(documentId, e);
}
}
private static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return output.toByteArray();
} finally {
if (output != null) {
output.close();
}
}
}
public byte[] getContent(final Document document) throws DocumentNotFoundException {
final Session session2 = getSession();
final org.apache.chemistry.opencmis.client.api.Document doc =
(org.apache.chemistry.opencmis.client.api.Document) session2.getObject(session2.createObjectId(document.getId()));
final ContentStream contentStream = doc.getContentStream();
if (contentStream != null) {
final InputStream stream = contentStream.getStream();
byte[] byteArray;
try {
byteArray = toByteArray(stream);
return byteArray;
} catch (final IOException e) {
e.printStackTrace();
} finally {
try {
stream.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public String getDocumentPath(final String documentId) {
final Session session2 = getSession();
final org.apache.chemistry.opencmis.client.api.Document object =
(org.apache.chemistry.opencmis.client.api.Document) session2.getObject(session2.createObjectId(documentId));
return object.getParents().get(0).getPath() + "/" + object.getName();
}
public Document createVersion(final String documentId, final boolean isMajorVersion) {
final Session session2 = getSession();
return createVersion(session2, documentId, isMajorVersion);
}
/**
* @param session
* @param documentId
* @param isMajorVersion
* @return
*/
private Document createVersion(final Session session, final String documentId, final boolean isMajorVersion) {
final org.apache.chemistry.opencmis.client.api.Document cmisDoc =
(org.apache.chemistry.opencmis.client.api.Document) session.getObject(session.createObjectId(documentId));
final ObjectId pwcid = cmisDoc.checkOut();
ObjectId newVersion = null;
try {
final org.apache.chemistry.opencmis.client.api.Document pwc =
(org.apache.chemistry.opencmis.client.api.Document) session.getObject(pwcid);
final Map<String, Object> newDocProps = new HashMap<String, Object>();
newDocProps.put(PropertyIds.NAME, cmisDoc.getName());
newDocProps.put(PropertyIds.IS_MAJOR_VERSION, isMajorVersion);
newVersion = pwc.checkIn(true, newDocProps, null, "");// TODO
} catch (Throwable t) {
session.getBinding().getVersioningService().cancelCheckOut(repositoryId, pwcid.getId(), null);
throw new RuntimeException(t);
}
// check
// in
// comment
session.clear();//must clear it because xcmis change ids of documents
return convertDocument((org.apache.chemistry.opencmis.client.api.Document) session.getObject(newVersion));
}
public Document createVersion(final String documentId, final boolean isMajorVersion, final String fileName, final String mimeType, final byte[] content) throws DocumentationCreationException {
final Session session2 = getSession();
return createVersion(session2, documentId, isMajorVersion, fileName, mimeType, content);
}
/**
* @param session
* @param documentId
* @param isMajorVersion
* @param fileName
* @param mimeType
* @param content
* @return
*/
private Document createVersion(final Session session, final String documentId, final boolean isMajorVersion, final String fileName,
final String mimeType, final byte[] content) {
final org.apache.chemistry.opencmis.client.api.Document cmisDoc =
(org.apache.chemistry.opencmis.client.api.Document) session.getObject(session.createObjectId(documentId));
final ObjectId pwcid = cmisDoc.checkOut();
ObjectId newVersion = null;
try {
final org.apache.chemistry.opencmis.client.api.Document pwc =
(org.apache.chemistry.opencmis.client.api.Document) session.getObject(pwcid);
if (content != null && content.length > 0) {
if(mimeType != null) {
try {
new MimeType(mimeType);
} catch (final MimeTypeParseException e1) {
throw new DocumentationCreationException("Mime type not valid",e1);
}
}
final ByteArrayInputStream insputStream = new ByteArrayInputStream(content);
try {
final ContentStream contentStream = session.getBinding().getObjectFactory()
.createContentStream(fileName, BigInteger.valueOf(content.length), mimeType, insputStream);
pwc.setContentStream(contentStream, true);
} finally {
try {
insputStream.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
final Map<String, Object> newDocProps = new HashMap<String, Object>();
newDocProps.put(PropertyIds.NAME, cmisDoc.getName());
newDocProps.put(PropertyIds.CONTENT_STREAM_FILE_NAME, fileName);
newDocProps.put(PropertyIds.CONTENT_STREAM_MIME_TYPE, mimeType);
newDocProps.put(PropertyIds.IS_MAJOR_VERSION, isMajorVersion);
newVersion = pwc.checkIn(isMajorVersion, newDocProps, null, "");// TODO
} catch (Throwable t) {
session.getBinding().getVersioningService().cancelCheckOut(repositoryId, pwcid.getId(), null);
throw new RuntimeException(t);
}
// check
// in
// comment
session.clear();//must clear it because xcmis change ids of documents
return convertDocument((org.apache.chemistry.opencmis.client.api.Document) session.getObject(newVersion));
}
public List<org.ow2.bonita.services.Folder> getFolders(final String folderName) {
final Session session2 = getSession();
final String statement = "SELECT * FROM cmis:folder WHERE cmis:name = '" + folderName + "'";
final ItemIterable<QueryResult> query = session2.query(statement, true);
final ArrayList<org.ow2.bonita.services.Folder> folders = new ArrayList<org.ow2.bonita.services.Folder>();
try {
for (final QueryResult queryResult : query) {
final PropertyData<Object> propertyById = queryResult.getPropertyById("cmis:objectId");
final String objectId = (String) propertyById.getValues().get(0);
final Folder cmisFolder = (Folder) session2.getObject(session2.createObjectId(objectId));
folders.add(convertFolder(cmisFolder));
}
} catch (final CmisObjectNotFoundException e) {
LOGGER.debug("can't find object with query: " + statement, e);
}
return folders;
}
public List<Document> getVersionsOfDocument(final String documentId) {
final Session session2 = getSession();
// List<ObjectData> allVersions =
// session2.getBinding().getVersioningService()
// .getAllVersions(repositoryId, document.getId(),
// document.getVersionSeriesId(), null, false, null);
final List<Document> versions = new ArrayList<Document>();
final List<org.apache.chemistry.opencmis.client.api.Document> allVersions2 =
((org.apache.chemistry.opencmis.client.api.Document) session2.getObject(session2.createObjectId(documentId))).getAllVersions();
for (final org.apache.chemistry.opencmis.client.api.Document oldDoc : allVersions2) {
versions.add(convertDocument(oldDoc));
}
return versions;
}
public Document createDocument(final String name, final ProcessDefinitionUUID definitionUUID, final ProcessInstanceUUID instanceUUID)
throws DocumentationCreationException, DocumentAlreadyExistsException {
Session session = getSession();
final String folderId = createPath(session, definitionUUID, instanceUUID);
return createDocument(session,name, folderId);
}
public Document createDocument(final String name, final ProcessDefinitionUUID definitionUUID, final ProcessInstanceUUID instanceUUID, final String fileName,
final String contentMimeType, final byte[] fileContent) throws DocumentationCreationException, DocumentAlreadyExistsException {
Session session = getSession();
final String subFolder = createPath(session, definitionUUID, instanceUUID);
return createDocument(session,name, subFolder, fileName, contentMimeType, fileContent);
}
private String createPath(Session session, final ProcessDefinitionUUID definitionUUID, final ProcessInstanceUUID instanceUUID)
throws DocumentationCreationException {
String mainFolderId = null;
if (processDefinitionMap.containsKey(definitionUUID)) {
mainFolderId = processDefinitionMap.get(definitionUUID);
} else {
final String processDefUUIDValue = definitionUUID.getValue();
if(rootFolderId == null){//FIXME better handling of sessions
getSession();
}
List<org.ow2.bonita.services.Folder> childrenFolder = getChildrenFolder(rootFolderId);
for (org.ow2.bonita.services.Folder folder : childrenFolder) {
if (processDefUUIDValue.equals(folder.getName())) {
mainFolderId = folder.getId();
break;
}
}
if (mainFolderId == null) {
try {
mainFolderId = createFolder(processDefUUIDValue, rootFolderId).getId();
} catch (final FolderAlreadyExistsException e) {
e.printStackTrace();
}
}
processDefinitionMap.put(definitionUUID, mainFolderId);
}
if (instanceUUID == null) {
return mainFolderId;
}
String subFolderId = null;
if (processInstanceMap.containsKey(instanceUUID)) {
subFolderId = processInstanceMap.get(instanceUUID);
} else {
final String processInstValue = instanceUUID.getValue();
List<org.ow2.bonita.services.Folder> childrenFolder = getChildrenFolder(mainFolderId);
for (org.ow2.bonita.services.Folder folder : childrenFolder) {
if (processInstValue.equals(folder.getName())) {
subFolderId = folder.getId();
break;
}
}
if (subFolderId == null) {
try {
subFolderId = createFolder(processInstValue, mainFolderId).getId();
} catch (final FolderAlreadyExistsException e) {
throw new DocumentationCreationException("Folder already exists", e);
}
}
processInstanceMap.put(instanceUUID, subFolderId);
}
return subFolderId;
}
public SearchResult search(final DocumentSearchBuilder builder, final int fromResult, final int maxResults) {
final Session session2 = getSession();
final StringBuilder whereClause = new StringBuilder();
whereClause.append("SELECT * FROM cmis:document");
final List<Object> query = builder.getQuery();
if (!query.isEmpty()) {
whereClause.append(" WHERE ");
}
for (final Object object : query) {
if (object instanceof DocumentCriterion) {
final DocumentCriterion criterion = (DocumentCriterion) object;
switch (criterion.getField()) {
case ID:
createEqualsOrInClause(whereClause, criterion, "cmis:objectId");
break;
case PROCESS_DEFINITION_UUID:
String idOfProcessDefinitionUUID = getIdOfProcessDefinitionUUID(criterion);
if(idOfProcessDefinitionUUID == null){
final List<Document> list = Collections.emptyList();
return new SearchResult(list, 0);
}
whereClause.append(" IN_TREE('");
whereClause.append(idOfProcessDefinitionUUID);
whereClause.append("') ");
break;
case PROCESS_DEFINITION_UUID_WITHOUT_INSTANCES:
String idOfProcessDefinitionUUID2 = getIdOfProcessDefinitionUUID(criterion);
if(idOfProcessDefinitionUUID2 == null){
final List<Document> list = Collections.emptyList();
return new SearchResult(list, 0);
}
whereClause.append(" IN_FOLDER('");
whereClause.append(idOfProcessDefinitionUUID2);
whereClause.append("') ");
break;
case PROCESS_INSTANCE_UUID:
ProcessInstanceUUID processInstanceUUID = new ProcessInstanceUUID((String) criterion.getValue());
final String id2;
if(processInstanceMap.containsKey(processInstanceUUID)){
id2 = processInstanceMap.get(processInstanceUUID);
}else{
final List<org.ow2.bonita.services.Folder> folders2 = getFolders(processInstanceUUID.getValue());
if (folders2.size() == 0) {
final List<Document> list = Collections.emptyList();
return new SearchResult(list, 0);
}
id2 = folders2.get(0).getId();
}
whereClause.append(" IN_FOLDER('");
whereClause.append(id2);
whereClause.append("') ");
break;
case NAME:
createEqualsOrInClause(whereClause, criterion, "cmis:name");
break;
case FILENAME:
createEqualsOrInClause(whereClause, criterion, "cmis:contentStreamFileName");
break;
case CREATION_DATE:
getTimeComparison(whereClause, criterion, "cmis:creationDate");
break;
case AUTHOR:
createEqualsOrInClause(whereClause, criterion, "cmis:createdBy");
break;
case LAST_MODIFICATION_DATE:
getTimeComparison(whereClause, criterion, "cmis:lastModificationDate");
break;
}
} else {
whereClause.append(" ").append(object).append(" ");
}
}
final ItemIterable<QueryResult> queryResult = session2.query(whereClause.toString(), builder.isSearchAllVersions());
queryResult.skipTo(fromResult);
final ItemIterable<QueryResult> page = queryResult.getPage(maxResults);
final List<Document> documents = new ArrayList<Document>();
for (final QueryResult queryResult2 : page) {
final PropertyData<Object> propertyById = queryResult2.getPropertyById("cmis:objectId");
final org.apache.chemistry.opencmis.client.api.Document doc = (org.apache.chemistry.opencmis.client.api.Document) session2
.getObject(session2.createObjectId((String) propertyById.getValues().get(0)));
documents.add(convertDocument(doc));
}
final SearchResult result = new SearchResult(documents, (int) page.getPageNumItems());
return result;
}
private void createEqualsOrInClause(final StringBuilder whereClause, final DocumentCriterion criterion, String field) {
if(criterion.getValues() != null){
whereClause.append(" " + field + " IN (");
Collection<?> values = criterion.getValues();
for (Iterator<?> iterator = values.iterator(); iterator.hasNext();) {
Object object2 = (Object) iterator.next();
whereClause.append("'");
whereClause.append(object2);
whereClause.append("'");
if(iterator.hasNext()){
whereClause.append(",");
}
}
whereClause.append(") ");
}else{
whereClause.append(" " + field + " = '");
whereClause.append(criterion.getValue());
whereClause.append("' ");
}
}
/**
* @param criterion
* @return
*/
private String getIdOfProcessDefinitionUUID(final DocumentCriterion criterion) {
final String id;
ProcessDefinitionUUID processDef = new ProcessDefinitionUUID((String) criterion.getValue());
if(processDefinitionMap.containsKey(processDef)){
id = processDefinitionMap.get(processDef);
}else{
final List<org.ow2.bonita.services.Folder> folders = getFolders(processDef.getValue());
if (folders.size() == 0) {
return null;
}
id = folders.get(0).getId();
}
return id;
}
private void getTimeComparison(final StringBuilder whereClause, final DocumentCriterion criterion, final String attribute) {
final SimpleDateFormat cmisDateFormat = CMISDocumentManager.CMIS_DATE_FORMAT.get();
if(criterion.getValue() != null) {
whereClause.append(attribute);
whereClause.append(" = TIMESTAMP '");
final Date value = (Date) criterion.getValue();
final String fromDate = cmisDateFormat.format(localToServerDate(value));
whereClause.append(fromDate);
whereClause.append("' ");
} else {
whereClause.append(" (");
whereClause.append(attribute);
whereClause.append(" >= TIMESTAMP '");
final Date from = (Date) criterion.getFrom();
final String fromDate = cmisDateFormat.format(localToServerDate(from));
whereClause.append(fromDate);
whereClause.append("' AND ");
whereClause.append(attribute);
whereClause.append(" <= TIMESTAMP '");
final Date to = (Date) criterion.getTo();
final String toDate = cmisDateFormat.format(localToServerDate(to));
whereClause.append(toDate);
whereClause.append("') ");
}
}
public void clear() throws DocumentNotFoundException {
clear(getRootFolder());
sessionsMap.clear();
processDefinitionMap.clear();
processInstanceMap.clear();
session = null;
}
public void clear(org.ow2.bonita.services.Folder folder) throws DocumentNotFoundException {
for (org.ow2.bonita.services.Folder subFolder : getChildrenFolder(folder.getId())) {
clear(subFolder);
deleteFolder(subFolder);
}
for (Document doc : getChildrenDocuments(folder.getId())) {
deleteDocument(doc.getId(), true);
}
}
public void updateDocumentContent(String documentId, String fileName, String mimeType, int size, byte[] content)
throws DocumentNotFoundException {
Session session2 = getSession();
org.apache.chemistry.opencmis.client.api.Document document = null;
try {
document = (org.apache.chemistry.opencmis.client.api.Document) session2
.getObject(session2.createObjectId(documentId));
} catch (Exception e) {
throw new DocumentNotFoundException(documentId, e);
}
if (content != null) {
ByteArrayInputStream inputStream = null;
try {
inputStream = new ByteArrayInputStream(content);
ContentStream contentStream = session
.getBinding()
.getObjectFactory()
.createContentStream(fileName, BigInteger.valueOf(size), mimeType,
inputStream);
document.setContentStream(contentStream, true);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public boolean documentExists(final ProcessDefinitionUUID processDefinitionUUID, final String name) {
try{
CmisObject objectByPath = getSession().getObjectByPath("/"+processDefinitionUUID.getValue()+"/"+name);
return objectByPath != null && objectByPath instanceof org.apache.chemistry.opencmis.client.api.Document;
} catch (CmisRuntimeException e) {
//not found
}
return false;
}
public boolean documentExists(final ProcessDefinitionUUID processDefinitionUUID, final ProcessInstanceUUID processInstanceUUID, final String name) {
try{
CmisObject objectByPath = getSession().getObjectByPath("/"+processDefinitionUUID.getValue()+"/"+processInstanceUUID.getValue()+"/"+name);
return objectByPath != null && objectByPath instanceof org.apache.chemistry.opencmis.client.api.Document;
} catch (CmisRuntimeException e) {
//not found
}
return false;
}
public void attachDocumentTo(ProcessDefinitionUUID processDefinitionUUID, String documentId) throws DocumentNotFoundException {
attachDocumentTo(processDefinitionUUID,null, documentId);
}
public void attachDocumentTo(ProcessDefinitionUUID processDefinitionUUID, ProcessInstanceUUID processInstanceUUID, String documentId)
throws DocumentNotFoundException {
Session session2 = getSession();
try {
String parentFolder = createPath(session, processDefinitionUUID, processInstanceUUID);
org.apache.chemistry.opencmis.client.api.Document document;
document = (org.apache.chemistry.opencmis.client.api.Document) session2
.getObject(session2.createObjectId(documentId));
Folder cmisFolder = (Folder) session2.getObject(session2.createObjectId(parentFolder));
document.addToFolder(cmisFolder, true);
} catch (CmisRuntimeException e) {
throw new DocumentNotFoundException(documentId);
} catch (DocumentationCreationException dce) {
throw new DocumentNotFoundException(documentId, dce);
}
}
public Document createDocument(final String name, final ProcessDefinitionUUID definitionUUID, final ProcessInstanceUUID instanceUUID, final String author, Date versionDate)
throws DocumentationCreationException, DocumentAlreadyExistsException {
Session session = getSession(author);
final String folderId = createPath(session, definitionUUID, instanceUUID);
return createDocument(session,name, folderId);
}
public Document createDocument(final String name, final ProcessDefinitionUUID definitionUUID, final ProcessInstanceUUID instanceUUID, final String author, Date versionDate, final String fileName, final String mimeType, final byte[] content)
throws DocumentationCreationException, DocumentAlreadyExistsException {
Session session = getSession(author);
final String subFolder = createPath(session, definitionUUID, instanceUUID);
return createDocument(session,name, subFolder, fileName, mimeType, content);
}
public Document createVersion(String documentId, boolean isMajorVersion, String author, Date versionDate) throws DocumentationCreationException {
//versionDate can't be set manually
final Session session2 = getSession(author);
return createVersion(session2, documentId, isMajorVersion);
}
public Document createVersion(String documentId, boolean isMajorVersion, String author, Date versionDate, String fileName, String mimeType, byte[] content)
throws DocumentationCreationException {
final Session session2 = getSession(author);
return createVersion(session2, documentId, isMajorVersion, fileName, mimeType, content);
}
}