/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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 library 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.
*/
package com.liferay.portal.store.cmis;
import com.liferay.document.library.kernel.exception.DuplicateFileException;
import com.liferay.document.library.kernel.exception.NoSuchFileException;
import com.liferay.document.library.kernel.store.BaseStore;
import com.liferay.document.library.kernel.store.Store;
import com.liferay.document.library.kernel.util.DLUtil;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.ContentTypes;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.store.cmis.configuration.CMISStoreConfiguration;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
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.OperationContext;
import org.apache.chemistry.opencmis.client.api.Repository;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.api.SessionFactory;
import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl;
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.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.BindingType;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
/**
* @author Alexander Chow
* @author Edward Han
* @author Manuel de la Peña
* @deprecated As of 2.0.0, with no direct replacement
*/
@Component(
configurationPid = "com.liferay.portal.store.cmis.configuration.CMISStoreConfiguration",
configurationPolicy = ConfigurationPolicy.REQUIRE, immediate = true,
property = "store.type=com.liferay.portal.store.cmis.CMISStore",
service = Store.class
)
@Deprecated
public class CMISStore extends BaseStore {
@Override
public void addDirectory(
long companyId, long repositoryId, String dirName) {
Folder folder = getRepositoryFolder(companyId, repositoryId);
String[] dirNames = StringUtil.split(dirName, CharPool.SLASH);
for (String curDirName : dirNames) {
Folder subfolder = getFolder(folder, curDirName);
if (subfolder == null) {
subfolder = createFolder(folder, curDirName);
}
folder = subfolder;
}
}
@Override
public void addFile(
long companyId, long repositoryId, String fileName, InputStream is)
throws DuplicateFileException {
updateFile(companyId, repositoryId, fileName, VERSION_DEFAULT, is);
}
@Override
public void checkRoot(long companyId) {
}
@Override
public void copyFileVersion(
long companyId, long repositoryId, String fileName,
String fromVersionLabel, String toVersionLabel)
throws DuplicateFileException, NoSuchFileException {
if (fromVersionLabel.equals(toVersionLabel)) {
throw new DuplicateFileException(
companyId, repositoryId, fileName, toVersionLabel);
}
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, fileName, false);
if (versioningFolder == null) {
throw new NoSuchFileException(
companyId, repositoryId, fileName, fromVersionLabel);
}
if (hasFile(companyId, repositoryId, fileName, toVersionLabel)) {
throw new DuplicateFileException(
companyId, repositoryId, fileName, toVersionLabel);
}
ObjectId versioningFolderObjectId = new ObjectIdImpl(
versioningFolder.getId());
Map<String, Object> documentProperties = new HashMap<>();
documentProperties.put(PropertyIds.NAME, toVersionLabel);
documentProperties.put(
PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
Document document = getVersionedDocument(
companyId, repositoryId, fileName, fromVersionLabel);
document.copy(
versioningFolderObjectId, documentProperties, null,
document.getPolicies(), null, null, null);
}
@Override
public void deleteDirectory(
long companyId, long repositoryId, String dirName) {
Folder repositoryFolder = getRepositoryFolder(companyId, repositoryId);
Folder directory = getFolder(repositoryFolder, dirName);
if (directory != null) {
directory.deleteTree(true, UnfileObject.DELETE, false);
}
}
@Override
public void deleteFile(long companyId, long repositoryId, String fileName) {
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, fileName, false);
if (versioningFolder == null) {
logFailedDeletion(companyId, repositoryId, fileName);
}
else {
versioningFolder.deleteTree(true, UnfileObject.DELETE, false);
}
}
@Override
public void deleteFile(
long companyId, long repositoryId, String fileName,
String versionLabel) {
Document document = null;
try {
document = getVersionedDocument(
companyId, repositoryId, fileName, versionLabel);
document.delete(true);
}
catch (NoSuchFileException nsfe) {
logFailedDeletion(
companyId, repositoryId, fileName, versionLabel, nsfe);
}
}
@Override
public InputStream getFileAsStream(
long companyId, long repositoryId, String fileName,
String versionLabel)
throws NoSuchFileException {
if (Validator.isNull(versionLabel)) {
versionLabel = getHeadVersionLabel(
companyId, repositoryId, fileName);
}
Document document = getVersionedDocument(
companyId, repositoryId, fileName, versionLabel);
ContentStream contentStream = document.getContentStream();
return contentStream.getStream();
}
@Override
public String[] getFileNames(long companyId, long repositoryId) {
Folder folder = getRepositoryFolder(companyId, repositoryId);
List<String> fileNames = new ArrayList<>();
doGetFileNames(fileNames, StringPool.BLANK, folder);
return fileNames.toArray(new String[fileNames.size()]);
}
@Override
public String[] getFileNames(
long companyId, long repositoryId, String dirName) {
Folder directory = getRepositoryFolder(companyId, repositoryId);
String[] subfolderNames = StringUtil.split(dirName, StringPool.SLASH);
for (String subfolderName : subfolderNames) {
directory = getFolder(directory, subfolderName);
if (directory == null) {
return new String[0];
}
}
List<String> fileNames = new ArrayList<>();
doGetFileNames(fileNames, dirName, directory);
return fileNames.toArray(new String[fileNames.size()]);
}
@Override
public long getFileSize(long companyId, long repositoryId, String fileName)
throws NoSuchFileException {
String versionLabel = getHeadVersionLabel(
companyId, repositoryId, fileName);
Document document = getVersionedDocument(
companyId, repositoryId, fileName, versionLabel);
return document.getContentStreamLength();
}
public String getHeadVersionLabel(
long companyId, long repositoryId, String dirName)
throws NoSuchFileException {
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, dirName, false);
if (versioningFolder == null) {
throw new NoSuchFileException(companyId, repositoryId, dirName);
}
String headVersionLabel = VERSION_DEFAULT;
List<String> versionLabels = getVersionLabels(versioningFolder);
for (String versionLabel : versionLabels) {
if (DLUtil.compareVersions(versionLabel, headVersionLabel) > 0) {
headVersionLabel = versionLabel;
}
}
return headVersionLabel;
}
@Override
public boolean hasDirectory(
long companyId, long repositoryId, String dirName) {
Folder folder = getRepositoryFolder(companyId, repositoryId);
String[] dirNames = StringUtil.split(dirName, CharPool.SLASH);
for (String subdirName : dirNames) {
Folder subfolder = getFolder(folder, subdirName);
if (subfolder == null) {
return false;
}
}
return true;
}
@Override
public boolean hasFile(
long companyId, long repositoryId, String fileName,
String versionLabel) {
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, fileName, true);
Document document = getDocument(versioningFolder, versionLabel);
if (document == null) {
return false;
}
else {
return true;
}
}
@Override
public void updateFile(
long companyId, long repositoryId, long newRepositoryId,
String fileName)
throws DuplicateFileException, NoSuchFileException {
if (repositoryId == newRepositoryId) {
throw new DuplicateFileException(
companyId, newRepositoryId, fileName);
}
Folder oldVersioningFolderEntry = getVersioningFolder(
companyId, repositoryId, fileName, false);
if (oldVersioningFolderEntry == null) {
throw new NoSuchFileException(companyId, repositoryId, fileName);
}
if (hasFile(companyId, newRepositoryId, fileName)) {
throw new DuplicateFileException(
companyId, newRepositoryId, fileName);
}
Folder newVersioningFolderEntry = getVersioningFolder(
companyId, newRepositoryId, fileName, true);
List<String> versionLabels = getVersionLabels(oldVersioningFolderEntry);
for (String versionLabel : versionLabels) {
Document document = getDocument(
oldVersioningFolderEntry, versionLabel);
ContentStream contentStream = document.getContentStream();
InputStream is = contentStream.getStream();
createDocument(newVersioningFolderEntry, versionLabel, is);
}
oldVersioningFolderEntry.deleteTree(true, UnfileObject.DELETE, false);
}
@Override
public void updateFile(
long companyId, long repositoryId, String fileName,
String newFileName)
throws DuplicateFileException, NoSuchFileException {
if (fileName.equals(newFileName)) {
throw new DuplicateFileException(
companyId, repositoryId, newFileName);
}
Folder oldVersioningFolderEntry = getVersioningFolder(
companyId, repositoryId, fileName, false);
if (oldVersioningFolderEntry == null) {
throw new NoSuchFileException(companyId, repositoryId, fileName);
}
if (hasFile(companyId, repositoryId, newFileName)) {
throw new DuplicateFileException(
companyId, repositoryId, newFileName);
}
Folder newVersioningFolderEntry = getVersioningFolder(
companyId, repositoryId, newFileName, true);
List<String> versionLabels = getVersionLabels(oldVersioningFolderEntry);
for (String versionLabel : versionLabels) {
Document document = getDocument(
oldVersioningFolderEntry, versionLabel);
ContentStream contentStream = document.getContentStream();
InputStream is = contentStream.getStream();
createDocument(newVersioningFolderEntry, versionLabel, is);
}
oldVersioningFolderEntry.deleteTree(true, UnfileObject.DELETE, false);
}
@Override
public void updateFile(
long companyId, long repositoryId, String fileName,
String versionLabel, InputStream is)
throws DuplicateFileException {
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, fileName, true);
String title = String.valueOf(versionLabel);
Document document = getDocument(versioningFolder, title);
if (document != null) {
throw new DuplicateFileException(
companyId, repositoryId, fileName, versionLabel);
}
createDocument(versioningFolder, title, is);
}
@Override
public void updateFileVersion(
long companyId, long repositoryId, String fileName,
String fromVersionLabel, String toVersionLabel)
throws DuplicateFileException, NoSuchFileException {
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, fileName, false);
if (versioningFolder == null) {
throw new NoSuchFileException(
companyId, repositoryId, fileName, fromVersionLabel);
}
Document document = getDocument(versioningFolder, toVersionLabel);
if (document != null) {
throw new DuplicateFileException(
companyId, repositoryId, fileName, toVersionLabel);
}
document = getVersionedDocument(
companyId, repositoryId, fileName, fromVersionLabel);
Map<String, Object> documentProperties = new HashMap<>();
documentProperties.put(PropertyIds.NAME, toVersionLabel);
document.updateProperties(documentProperties);
}
@Activate
protected void activate(
BundleContext bundleContext, Map<String, Object> properties) {
if (_log.isWarnEnabled()) {
StringBundler sb = new StringBundler(3);
sb.append("Liferay is configured via the portal property ");
sb.append("\"dl.store.impl\" to use CMIS to persist documents. ");
sb.append("CMIS is deprecated and is not supported.");
_log.warn(sb);
}
_cmisStoreConfiguration = ConfigurableUtil.createConfigurable(
CMISStoreConfiguration.class, properties);
_operationContext = createOperationContext();
_sessionFactory = SessionFactoryImpl.newInstance();
_session = createSession(
bundleContext.getBundle(), _cmisStoreConfiguration,
_operationContext, _sessionFactory);
_systemRootDir = getFolder(
_session.getRootFolder(), _cmisStoreConfiguration.systemRootDir());
if (_systemRootDir == null) {
_systemRootDir = createFolder(
_session.getRootFolder(),
_cmisStoreConfiguration.systemRootDir());
}
}
protected Document createDocument(
Folder versioningFolder, String title, InputStream is) {
Map<String, Object> documentProperties = new HashMap<>();
documentProperties.put(PropertyIds.NAME, title);
documentProperties.put(
PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
ContentStream contentStream = new ContentStreamImpl(
null, null, ContentTypes.APPLICATION_OCTET_STREAM, is);
return versioningFolder.createDocument(
documentProperties, contentStream, null);
}
protected Folder createFolder(ObjectId parentFolderId, String name) {
Map<String, Object> properties = new HashMap<>();
properties.put(PropertyIds.NAME, name);
properties.put(
PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value());
ObjectId objectId = _session.createFolder(properties, parentFolderId);
return (Folder)_session.getObject(objectId);
}
protected OperationContextImpl createOperationContext() {
Set<String> defaultFilterSet = new HashSet<>();
// Base
defaultFilterSet.add(PropertyIds.BASE_TYPE_ID);
defaultFilterSet.add(PropertyIds.CREATED_BY);
defaultFilterSet.add(PropertyIds.CREATION_DATE);
defaultFilterSet.add(PropertyIds.LAST_MODIFIED_BY);
defaultFilterSet.add(PropertyIds.LAST_MODIFICATION_DATE);
defaultFilterSet.add(PropertyIds.NAME);
defaultFilterSet.add(PropertyIds.OBJECT_ID);
defaultFilterSet.add(PropertyIds.OBJECT_TYPE_ID);
// Document
defaultFilterSet.add(PropertyIds.CONTENT_STREAM_LENGTH);
defaultFilterSet.add(PropertyIds.CONTENT_STREAM_MIME_TYPE);
defaultFilterSet.add(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
defaultFilterSet.add(PropertyIds.VERSION_LABEL);
defaultFilterSet.add(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY);
defaultFilterSet.add(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID);
defaultFilterSet.add(PropertyIds.VERSION_SERIES_ID);
// Folder
defaultFilterSet.add(PropertyIds.PARENT_ID);
defaultFilterSet.add(PropertyIds.PATH);
// Operation context
return new OperationContextImpl(
defaultFilterSet, false, true, false, IncludeRelationships.NONE,
null, false, "cmis:name ASC", true, 1000);
}
protected Session createSession(
Bundle bundle, CMISStoreConfiguration cmisStoreConfiguration,
OperationContext operationContext, SessionFactory sessionFactory) {
Map<String, String> parameters = new HashMap<>();
parameters.put(
SessionParameter.ATOMPUB_URL,
cmisStoreConfiguration.repositoryUrl());
parameters.put(
SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
parameters.put(SessionParameter.COMPRESSION, Boolean.TRUE.toString());
Locale locale = LocaleUtil.getDefault();
parameters.put(
SessionParameter.LOCALE_ISO3166_COUNTRY, locale.getCountry());
parameters.put(
SessionParameter.LOCALE_ISO639_LANGUAGE, locale.getLanguage());
parameters.put(
SessionParameter.PASSWORD,
cmisStoreConfiguration.credentialsPassword());
parameters.put(
SessionParameter.USER,
cmisStoreConfiguration.credentialsUsername());
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
ClassLoader bundleClassLoader = bundleWiring.getClassLoader();
thread.setContextClassLoader(bundleClassLoader);
try {
List<Repository> repositories = sessionFactory.getRepositories(
parameters);
Repository repository = repositories.get(0);
Session session = repository.createSession();
session.setDefaultContext(operationContext);
return session;
}
finally {
thread.setContextClassLoader(contextClassLoader);
}
}
@Deactivate
protected void deactivate() {
_systemRootDir = null;
}
protected void doGetFileNames(
List<String> fileNames, String dirName, Folder folder) {
List<Folder> folders = getFolders(folder);
if (ListUtil.isNotEmpty(folders)) {
for (Folder curFolder : folders) {
String subdirName = null;
if (Validator.isBlank(dirName)) {
subdirName = curFolder.getName();
}
else {
subdirName =
dirName + StringPool.SLASH + curFolder.getName();
}
doGetFileNames(fileNames, subdirName, curFolder);
}
}
else if (Validator.isNotNull(dirName)) {
fileNames.add(dirName);
}
}
protected Folder getCompanyFolder(long companyId) {
String name = String.valueOf(companyId);
Folder companyFolder = getFolder(_systemRootDir, name);
if (companyFolder == null) {
companyFolder = createFolder(_systemRootDir, name);
}
return companyFolder;
}
protected Document getDocument(Folder parentFolder, String name) {
ItemIterable<CmisObject> cmisObjects = parentFolder.getChildren();
for (CmisObject cmisObject : cmisObjects) {
if (cmisObject instanceof Document &&
name.equals(cmisObject.getName())) {
return (Document)cmisObject;
}
}
return null;
}
protected Folder getFolder(Folder parentFolder, String name) {
ItemIterable<CmisObject> cmisObjects = parentFolder.getChildren();
for (CmisObject cmisObject : cmisObjects) {
if (cmisObject instanceof Folder &&
name.equals(cmisObject.getName())) {
return (Folder)cmisObject;
}
}
return null;
}
protected List<Folder> getFolders(Folder folder) {
List<Folder> folders = new ArrayList<>();
ItemIterable<CmisObject> cmisObjects = folder.getChildren();
for (CmisObject cmisObject : cmisObjects) {
if (cmisObject instanceof Folder) {
folders.add((Folder)cmisObject);
}
}
return folders;
}
protected Folder getRepositoryFolder(long companyId, long repositoryId) {
Folder companyFolder = getCompanyFolder(companyId);
String name = String.valueOf(repositoryId);
Folder repositoryFolder = getFolder(companyFolder, name);
if (repositoryFolder == null) {
repositoryFolder = createFolder(companyFolder, name);
}
return repositoryFolder;
}
protected Document getVersionedDocument(
long companyId, long repositoryId, String fileName,
String versionLabel)
throws NoSuchFileException {
Folder versioningFolder = getVersioningFolder(
companyId, repositoryId, fileName, false);
if (versioningFolder == null) {
throw new NoSuchFileException(companyId, repositoryId, fileName);
}
Document document = getDocument(versioningFolder, versionLabel);
if (document == null) {
throw new NoSuchFileException(
companyId, repositoryId, fileName, versionLabel);
}
return document;
}
protected Folder getVersioningFolder(
long companyId, long repositoryId, String fileName, boolean create) {
Folder repositoryFolder = getRepositoryFolder(companyId, repositoryId);
Folder versioningFolder = repositoryFolder;
String[] dirNames = StringUtil.split(fileName, CharPool.SLASH);
for (String dirName : dirNames) {
Folder subfolder = getFolder(versioningFolder, dirName);
if (create && (subfolder == null)) {
subfolder = createFolder(versioningFolder, dirName);
}
versioningFolder = subfolder;
}
return versioningFolder;
}
protected List<String> getVersionLabels(Folder versioningFolder) {
List<String> versions = new ArrayList<>();
ItemIterable<CmisObject> cmisObjects = versioningFolder.getChildren();
for (CmisObject cmisObject : cmisObjects) {
if (cmisObject instanceof Document) {
versions.add(cmisObject.getName());
}
}
return versions;
}
@Modified
protected void modified(
BundleContext bundleContext, Map<String, Object> properties) {
deactivate();
activate(bundleContext, properties);
}
private static final Log _log = LogFactoryUtil.getLog(CMISStore.class);
private CMISStoreConfiguration _cmisStoreConfiguration;
private OperationContext _operationContext;
private Session _session;
private SessionFactory _sessionFactory;
private Folder _systemRootDir;
}