Java tutorial
/** * OpenKM, Open Document Management System (http://www.openkm.com) * Copyright (c) 2006-2015 Paco Avila & Josep Llort * * No bytes were intentionally harmed during the development of this application. * * 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 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, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.openkm.module.db; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; import com.openkm.automation.AutomationException; import com.openkm.automation.AutomationManager; import com.openkm.automation.AutomationUtils; import com.openkm.bean.Document; import com.openkm.bean.ExtendedAttributes; import com.openkm.bean.FileUploadResponse; import com.openkm.bean.LockInfo; import com.openkm.bean.Repository; import com.openkm.bean.Version; import com.openkm.core.AccessDeniedException; import com.openkm.core.Config; import com.openkm.core.DatabaseException; import com.openkm.core.FileSizeExceededException; import com.openkm.core.ItemExistsException; import com.openkm.core.LockException; import com.openkm.core.MimeTypeConfig; import com.openkm.core.NoSuchGroupException; import com.openkm.core.ParseException; import com.openkm.core.PathNotFoundException; import com.openkm.core.Ref; import com.openkm.core.RepositoryException; import com.openkm.core.UnsupportedMimeTypeException; import com.openkm.core.UserQuotaExceededException; import com.openkm.core.VersionException; import com.openkm.core.VirusDetectedException; import com.openkm.core.VirusDetection; import com.openkm.core.WorkflowException; import com.openkm.dao.MimeTypeDAO; import com.openkm.dao.NodeBaseDAO; import com.openkm.dao.NodeDocumentDAO; import com.openkm.dao.NodeDocumentVersionDAO; import com.openkm.dao.NodeFolderDAO; import com.openkm.dao.bean.AutomationRule; import com.openkm.dao.bean.NodeBase; import com.openkm.dao.bean.NodeDocument; import com.openkm.dao.bean.NodeDocumentVersion; import com.openkm.dao.bean.NodeFolder; import com.openkm.dao.bean.NodeLock; import com.openkm.dao.bean.NodeNote; import com.openkm.dao.bean.NodeProperty; import com.openkm.extension.core.ExtensionException; import com.openkm.module.DocumentModule; import com.openkm.module.common.CommonGeneralModule; import com.openkm.module.db.base.BaseDocumentModule; import com.openkm.module.db.base.BaseModule; import com.openkm.module.db.base.BaseNoteModule; import com.openkm.module.db.base.BaseNotificationModule; import com.openkm.principal.PrincipalAdapterException; import com.openkm.spring.PrincipalUtils; import com.openkm.util.ConfigUtils; import com.openkm.util.FileUtils; import com.openkm.util.FormatUtil; import com.openkm.util.PathUtils; import com.openkm.util.UserActivity; import com.openkm.util.impexp.RepositoryExporter; public class DbDocumentModule implements DocumentModule { private static Logger log = LoggerFactory.getLogger(DbDocumentModule.class); @Override public Document create(String token, Document doc, InputStream is) throws UnsupportedMimeTypeException, FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, ItemExistsException, PathNotFoundException, AccessDeniedException, RepositoryException, IOException, DatabaseException, ExtensionException, AutomationException { log.debug("create({}, {}, {})", new Object[] { token, doc, is }); return create(token, doc, is, is.available(), null); } /** * Used when big files and WebDAV and GoogleDocs */ public Document create(String token, Document doc, InputStream is, long size, String userId) throws UnsupportedMimeTypeException, FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, ItemExistsException, PathNotFoundException, AccessDeniedException, RepositoryException, IOException, DatabaseException, ExtensionException, AutomationException { log.debug("create({}, {}, {}, {}, {})", new Object[] { token, doc, is, size, userId }); return create(token, doc, is, size, userId, new Ref<FileUploadResponse>(null)); } /** * Used when big files and FileUpload */ public Document create(String token, Document doc, InputStream is, long size, String userId, Ref<FileUploadResponse> fuResponse) throws UnsupportedMimeTypeException, FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, ItemExistsException, PathNotFoundException, AccessDeniedException, RepositoryException, IOException, DatabaseException, ExtensionException, AutomationException { log.debug("create({}, {}, {}, {}, {}, {})", new Object[] { token, doc, is, size, userId, fuResponse }); long begin = System.currentTimeMillis(); Document newDocument = null; Authentication auth = null, oldAuth = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } if (!PathUtils.checkPath(doc.getPath())) { throw new RepositoryException("Invalid path: " + doc.getPath()); } String parentPath = PathUtils.getParent(doc.getPath()); String name = PathUtils.getName(doc.getPath()); // Add to KEA - must have the same extension int idx = name.lastIndexOf('.'); String fileExtension = idx > 0 ? name.substring(idx) : ".tmp"; File tmp = File.createTempFile("okm", fileExtension); try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (Config.MAX_FILE_SIZE > 0 && size > Config.MAX_FILE_SIZE) { log.error("Uploaded file size: {} ({}), Max file size: {} ({})", new Object[] { FormatUtil.formatSize(size), size, FormatUtil.formatSize(Config.MAX_FILE_SIZE), Config.MAX_FILE_SIZE }); String usr = userId == null ? auth.getName() : userId; UserActivity.log(usr, "ERROR_FILE_SIZE_EXCEEDED", null, doc.getPath(), FormatUtil.formatSize(size)); throw new FileSizeExceededException(FormatUtil.formatSize(size)); } // Escape dangerous chars in name name = PathUtils.escape(name); if (!name.isEmpty()) { doc.setPath(parentPath + "/" + name); // Check file restrictions String mimeType = MimeTypeConfig.mimeTypes.getContentType(name.toLowerCase()); doc.setMimeType(mimeType); if (Config.RESTRICT_FILE_MIME && MimeTypeDAO.findByName(mimeType) == null) { String usr = userId == null ? auth.getName() : userId; UserActivity.log(usr, "ERROR_UNSUPPORTED_MIME_TYPE", null, doc.getPath(), mimeType); throw new UnsupportedMimeTypeException(mimeType); } // Restrict for extension if (!Config.RESTRICT_FILE_NAME.isEmpty()) { StringTokenizer st = new StringTokenizer(Config.RESTRICT_FILE_NAME, Config.LIST_SEPARATOR); while (st.hasMoreTokens()) { String wc = st.nextToken().trim(); String re = ConfigUtils.wildcard2regexp(wc); if (Pattern.matches(re, name)) { String usr = userId == null ? auth.getName() : userId; UserActivity.log(usr, "ERROR_UNSUPPORTED_MIME_TYPE", null, doc.getPath(), mimeType); throw new UnsupportedMimeTypeException(mimeType); } } } // Manage temporary files byte[] buff = new byte[4 * 1024]; FileOutputStream fos = new FileOutputStream(tmp); int read; while ((read = is.read(buff)) != -1) { fos.write(buff, 0, read); } fos.flush(); fos.close(); is.close(); is = new FileInputStream(tmp); if (!Config.SYSTEM_ANTIVIR.equals("")) { String info = VirusDetection.detect(tmp); if (info != null) { String usr = userId == null ? auth.getName() : userId; UserActivity.log(usr, "ERROR_VIRUS_DETECTED", null, doc.getPath(), info); throw new VirusDetectedException(info); } } String parentUuid = NodeBaseDAO.getInstance().getUuidFromPath(parentPath); NodeBase parentNode = NodeBaseDAO.getInstance().findByPk(parentUuid); // AUTOMATION - PRE // INSIDE BaseDocumentModule.create // Create node Set<String> keywords = doc.getKeywords() != null ? doc.getKeywords() : new HashSet<String>(); NodeDocument docNode = BaseDocumentModule.create(auth.getName(), parentPath, parentNode, name, doc.getTitle(), doc.getCreated(), mimeType, is, size, keywords, new HashSet<String>(), new HashSet<NodeProperty>(), new ArrayList<NodeNote>(), fuResponse); // AUTOMATION - POST // INSIDE BaseDocumentModule.create // Set returned folder properties newDocument = BaseDocumentModule.getProperties(auth.getName(), docNode); // Setting wizard properties // INSIDE BaseDocumentModule.create if (fuResponse.get() == null) { fuResponse.set(new FileUploadResponse()); } fuResponse.get().setHasAutomation(AutomationManager.getInstance().hasAutomation()); if (userId == null) { // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), "CREATE_DOCUMENT", null); // Activity log UserActivity.log(auth.getName(), "CREATE_DOCUMENT", docNode.getUuid(), doc.getPath(), mimeType + ", " + size); } else { // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, userId, "CREATE_MAIL_ATTACHMENT", null); // Activity log UserActivity.log(userId, "CREATE_MAIL_ATTACHMENT", docNode.getUuid(), doc.getPath(), mimeType + ", " + size); } } else { throw new RepositoryException("Invalid document name"); } } finally { IOUtils.closeQuietly(is); org.apache.commons.io.FileUtils.deleteQuietly(tmp); if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("create.Time: {}", System.currentTimeMillis() - begin); log.debug("create: {}", newDocument); return newDocument; } /* * Added this 20/02/2017 * By Herve AHOUANTCHEDE */ public static Document createByMigration(String token, Document doc, InputStream is, long size) throws UnsupportedMimeTypeException, FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, ItemExistsException, PathNotFoundException, AccessDeniedException, RepositoryException, IOException, DatabaseException, ExtensionException, AutomationException { System.out.println("Begin of createdByMigration"); long begin = System.currentTimeMillis(); Document newDocument = null; Authentication auth = null, oldAuth = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } if (!PathUtils.checkPath(doc.getPath())) { throw new RepositoryException("Invalid path: " + doc.getPath()); } String parentPath = PathUtils.getParent(doc.getPath()); String name = PathUtils.getName(doc.getPath()); // Add to KEA - must have the same extension int idx = name.lastIndexOf('.'); String fileExtension = idx > 0 ? name.substring(idx) : ".tmp"; File tmp = File.createTempFile("okm", fileExtension); try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } // Escape dangerous chars in name name = PathUtils.escape(name); if (!name.isEmpty()) { doc.setPath(parentPath + "/" + name); // Check file restrictions String mimeType = MimeTypeConfig.mimeTypes.getContentType(name.toLowerCase()); doc.setMimeType(mimeType); if (Config.RESTRICT_FILE_MIME && MimeTypeDAO.findByName(mimeType) == null) { String usr = doc.getAuthor(); UserActivity.log(usr, "ERROR_UNSUPPORTED_MIME_TYPE", null, doc.getPath(), mimeType); throw new UnsupportedMimeTypeException(mimeType); } // Restrict for extension if (!Config.RESTRICT_FILE_NAME.isEmpty()) { StringTokenizer st = new StringTokenizer(Config.RESTRICT_FILE_NAME, Config.LIST_SEPARATOR); while (st.hasMoreTokens()) { String wc = st.nextToken().trim(); String re = ConfigUtils.wildcard2regexp(wc); if (Pattern.matches(re, name)) { String usr = doc.getAuthor(); UserActivity.log(usr, "ERROR_UNSUPPORTED_MIME_TYPE", null, doc.getPath(), mimeType); throw new UnsupportedMimeTypeException(mimeType); } } } // Manage temporary files byte[] buff = new byte[4 * 1024]; FileOutputStream fos = new FileOutputStream(tmp); int read; while ((read = is.read(buff)) != -1) { fos.write(buff, 0, read); } fos.flush(); fos.close(); is.close(); is = new FileInputStream(tmp); if (!Config.SYSTEM_ANTIVIR.equals("")) { String info = VirusDetection.detect(tmp); if (info != null) { String usr = doc.getAuthor(); UserActivity.log(usr, "ERROR_VIRUS_DETECTED", null, doc.getPath(), info); throw new VirusDetectedException(info); } } String parentUuid = NodeBaseDAO.getInstance().getUuidFromPath(parentPath); NodeBase parentNode = NodeBaseDAO.getInstance().findByPk(parentUuid); // AUTOMATION - PRE // INSIDE BaseDocumentModule.create // Create node Set<String> keywords = doc.getKeywords() != null ? doc.getKeywords() : new HashSet<String>(); NodeDocument docNode = BaseDocumentModule.createByMigration(doc.getAuthor(), parentPath, parentNode, name, doc.getTitle(), doc.getCreated(), mimeType, is, size, keywords, new HashSet<String>(), new HashSet<NodeProperty>(), new ArrayList<NodeNote>()); // AUTOMATION - POST // INSIDE BaseDocumentModule.create // Set returned folder properties newDocument = BaseDocumentModule.getProperties(auth.getName(), docNode); if (doc.getAuthor() == null) { // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), "CREATE_DOCUMENT", null); // Activity log UserActivity.log(auth.getName(), "CREATE_DOCUMENT", docNode.getUuid(), doc.getPath(), mimeType + ", " + size); } else { // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, doc.getAuthor(), "CREATE_MAIL_ATTACHMENT", null); // Activity log UserActivity.log(doc.getAuthor(), "CREATE_MAIL_ATTACHMENT", docNode.getUuid(), doc.getPath(), mimeType + ", " + size); } } else { throw new RepositoryException("Invalid document name"); } } finally { IOUtils.closeQuietly(is); org.apache.commons.io.FileUtils.deleteQuietly(tmp); if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("create.Time: {}", System.currentTimeMillis() - begin); log.debug("create: {}", newDocument); return newDocument; } @Override public void delete(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("delete({}, {})", new Object[] { token, docId }); long begin = System.currentTimeMillis(); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } if (BaseDocumentModule.hasWorkflowNodes(docUuid)) { throw new LockException("Can't delete a document used in a workflow"); } String userTrashPath = "/" + Repository.TRASH + "/" + auth.getName(); String userTrashUuid = NodeBaseDAO.getInstance().getUuidFromPath(userTrashPath); String name = PathUtils.getName(docPath); // Check subscriptions NodeDocument documentNode = NodeDocumentDAO.getInstance().findByPk(docUuid); BaseNotificationModule.checkSubscriptions(documentNode, PrincipalUtils.getUser(), "DELETE_DOCUMENT", null); // After notification move to trash folder NodeDocumentDAO.getInstance().delete(name, docUuid, userTrashUuid); // Activity log UserActivity.log(auth.getName(), "DELETE_DOCUMENT", docUuid, docPath, null); } catch (WorkflowException e) { throw new RepositoryException(e.getMessage()); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("delete.Time: {}", System.currentTimeMillis() - begin); log.debug("delete: void"); } @Override public Document rename(String token, String docId, String newName) throws PathNotFoundException, ItemExistsException, AccessDeniedException, LockException, RepositoryException, DatabaseException { log.debug("rename({}, {}, {})", new Object[] { token, docId, newName }); Document renamedDocument = null; Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } String name = PathUtils.getName(docPath); // Escape dangerous chars in name newName = PathUtils.escape(newName); if (newName != null && !newName.isEmpty() && !newName.equals(name)) { NodeDocument documentNode = NodeDocumentDAO.getInstance().rename(docUuid, newName); renamedDocument = BaseDocumentModule.getProperties(auth.getName(), documentNode); // Check subscriptions BaseNotificationModule.checkSubscriptions(documentNode, PrincipalUtils.getUser(), "RENAME_DOCUMENT", null); } else { // Don't change anything NodeDocument documentNode = NodeDocumentDAO.getInstance().findByPk(docUuid); renamedDocument = BaseDocumentModule.getProperties(auth.getName(), documentNode); } // Activity log UserActivity.log(auth.getName(), "RENAME_DOCUMENT", docUuid, docPath, newName); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("rename: {}", renamedDocument); return renamedDocument; } @Override public Document getProperties(String token, String docId) throws PathNotFoundException, RepositoryException, DatabaseException { log.debug("getProperties({}, {})", token, docId); Document doc = null; Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); doc = BaseDocumentModule.getProperties(auth.getName(), docNode); // Activity log UserActivity.log(auth.getName(), "GET_DOCUMENT_PROPERTIES", docUuid, docPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("getProperties: {}", doc); return doc; } @Override public void setProperties(String token, Document doc) throws VersionException, LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("setProperties({}, {})", token, doc); Authentication auth = null, oldAuth = null; @SuppressWarnings("unused") String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (doc.getPath() != null && !doc.getPath().isEmpty()) { docPath = doc.getPath(); docUuid = NodeBaseDAO.getInstance().getUuidFromPath(doc.getPath()); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(doc.getUuid()); docUuid = doc.getUuid(); } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), "SET_DOCUMENT_PROPERTIES", null); // Activity log UserActivity.log(auth.getName(), "SET_DOCUMENT_PROPERTIES", docUuid, doc.getPath(), null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("setProperties: void"); } @Override public InputStream getContent(String token, String docId, boolean checkout) throws PathNotFoundException, AccessDeniedException, RepositoryException, IOException, DatabaseException { log.debug("getContent({}, {}, {})", new Object[] { token, docId, checkout }); return getContent(token, docId, checkout, true); } /** * Retrieve the content input stream from a document * * @param token Authorization token. * @param docId Path of the document to get the content or its UUID. * @param checkout If the content is retrieved due to a checkout or not. * @param extendedSecurity If the extended security DOWNLOAD permission should be evaluated. * This is used to enable the document preview. */ public InputStream getContent(String token, String docId, boolean checkout, boolean extendedSecurity) throws PathNotFoundException, AccessDeniedException, RepositoryException, IOException, DatabaseException { log.debug("getContent({}, {}, {}, {})", new Object[] { token, docId, checkout, extendedSecurity }); long begin = System.currentTimeMillis(); InputStream is = null; Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } is = BaseDocumentModule.getContent(auth.getName(), docUuid, docPath, checkout, extendedSecurity); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("getContent.Time: {}", System.currentTimeMillis() - begin); log.debug("getContent: {}", is); return is; } @Override public InputStream getContentByVersion(String token, String docId, String verName) throws RepositoryException, PathNotFoundException, IOException, DatabaseException { log.debug("getContentByVersion({}, {}, {})", new Object[] { token, docId, verName }); InputStream is = null; Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } is = NodeDocumentVersionDAO.getInstance().getVersionContentByParent(docUuid, verName); // Activity log UserActivity.log(auth.getName(), "GET_DOCUMENT_CONTENT_BY_VERSION", docUuid, docPath, verName + ", " + is.available()); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("getContentByVersion: {}", is); return is; } @Override @Deprecated public List<Document> getChilds(String token, String fldId) throws PathNotFoundException, RepositoryException, DatabaseException { return getChildren(token, fldId); } @Override public List<Document> getChildren(String token, String fldId) throws PathNotFoundException, RepositoryException, DatabaseException { log.debug("getChildren({}, {})", token, fldId); long begin = System.currentTimeMillis(); List<Document> children = new ArrayList<Document>(); Authentication auth = null, oldAuth = null; String fldPath = null; String fldUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(fldId)) { fldPath = fldId; fldUuid = NodeBaseDAO.getInstance().getUuidFromPath(fldId); } else { fldPath = NodeBaseDAO.getInstance().getPathFromUuid(fldId); fldUuid = fldId; } for (NodeDocument nDocument : NodeDocumentDAO.getInstance().findByParent(fldUuid)) { children.add(BaseDocumentModule.getProperties(auth.getName(), nDocument)); } // Activity log UserActivity.log(auth.getName(), "GET_CHILDREN_DOCUMENTS", fldUuid, fldPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("getChildren.Time: {}", System.currentTimeMillis() - begin); log.debug("getChildren: {}", children); return children; } @Override public void checkout(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { checkout(token, docId, null); } /** * Used in Zoho extension */ public void checkout(String token, String docId, String userId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("checkout({}, {}, {})", new Object[] { token, docId, userId }); long begin = System.currentTimeMillis(); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (userId == null) { userId = auth.getName(); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocumentDAO.getInstance().checkout(userId, docUuid); // Activity log UserActivity.log(auth.getName(), "CHECKOUT_DOCUMENT", docUuid, docPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("checkout.Time: {}", System.currentTimeMillis() - begin); log.debug("checkout: void"); } @Override public void cancelCheckout(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("cancelCheckout({}, {})", token, docId); cancelCheckoutHelper(token, docId, false); log.debug("cancelCheckout: void"); } @Override public void forceCancelCheckout(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException, PrincipalAdapterException { log.debug("forceCancelCheckout({}, {})", token, docId); if (PrincipalUtils.getRoles().contains(Config.DEFAULT_ADMIN_ROLE)) { cancelCheckoutHelper(token, docId, true); } else { throw new AccessDeniedException("Only administrator use allowed"); } log.debug("forceCancelCheckout: void"); } /** * Implement cancelCheckout and forceCancelCheckout features */ private void cancelCheckoutHelper(String token, String docId, boolean force) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("cancelCheckoutHelper({}, {}, {})", new Object[] { token, docId, force }); long begin = System.currentTimeMillis(); Authentication auth = null, oldAuth = null; String action = force ? "FORCE_CANCEL_DOCUMENT_CHECKOUT" : "CANCEL_DOCUMENT_CHECKOUT"; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); NodeDocumentDAO.getInstance().cancelCheckout(auth.getName(), docUuid, force); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), action, null); // Activity log UserActivity.log(auth.getName(), action, docUuid, docPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("cancelCheckoutHelper.Time: {}", System.currentTimeMillis() - begin); log.debug("cancelCheckoutHelper: void"); } @Override public boolean isCheckedOut(String token, String docId) throws PathNotFoundException, RepositoryException, DatabaseException { log.debug("isCheckedOut({}, {})", token, docId); boolean checkedOut = false; @SuppressWarnings("unused") Authentication auth = null, oldAuth = null; @SuppressWarnings("unused") String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } checkedOut = NodeDocumentDAO.getInstance().isCheckedOut(docUuid); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("isCheckedOut: {}", checkedOut); return checkedOut; } @Override public Version checkin(String token, String docId, InputStream is, String comment) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException, AutomationException { return checkin(token, docId, is, is.available(), comment, null, 0); } @Override public Version checkin(String token, String docId, InputStream is, String comment, int increment) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException, AutomationException { return checkin(token, docId, is, is.available(), comment, null, increment); } /** * Used in Zoho extension */ public Version checkin(String token, String docId, InputStream is, String comment, String userId) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException, AutomationException { return checkin(token, docId, is, is.available(), comment, userId, 0); } /** * Used when big files and WebDAV */ public Version checkin(String token, String docId, InputStream is, long size, String comment, String userId) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException, AutomationException { return checkin(token, docId, is, size, comment, userId, 0); } /** * Used when increase document major version */ public Version checkin(String token, String docId, InputStream is, long size, String comment, String userId, int increment) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException, AutomationException { log.debug("checkin({}, {}, {}, {}, {}, {})", new Object[] { token, docId, is, size, comment, userId }); long begin = System.currentTimeMillis(); Version version = new Version(); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } String name = PathUtils.getName(docPath); int idx = name.lastIndexOf('.'); String fileExtension = idx > 0 ? name.substring(idx) : ".tmp"; File tmp = File.createTempFile("okm", fileExtension); try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (userId == null) { userId = auth.getName(); } if (Config.MAX_FILE_SIZE > 0 && size > Config.MAX_FILE_SIZE) { log.error("Uploaded file size: {} ({}), Max file size: {} ({})", new Object[] { FormatUtil.formatSize(size), size, FormatUtil.formatSize(Config.MAX_FILE_SIZE), Config.MAX_FILE_SIZE }); UserActivity.log(userId, "ERROR_FILE_SIZE_EXCEEDED", null, docPath, FormatUtil.formatSize(size)); throw new FileSizeExceededException(FormatUtil.formatSize(size)); } // Manage temporary files byte[] buff = new byte[4 * 1024]; FileOutputStream fos = new FileOutputStream(tmp); int read; while ((read = is.read(buff)) != -1) { fos.write(buff, 0, read); } fos.flush(); fos.close(); is.close(); is = new FileInputStream(tmp); if (!Config.SYSTEM_ANTIVIR.equals("")) { String info = VirusDetection.detect(tmp); if (info != null) { UserActivity.log(userId, "ERROR_VIRUS_DETECTED", null, docPath, info); throw new VirusDetectedException(info); } } // AUTOMATION - PRE NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); Map<String, Object> env = new HashMap<String, Object>(); env.put(AutomationUtils.DOCUMENT_NODE, docNode); AutomationManager.getInstance().fireEvent(AutomationRule.EVENT_DOCUMENT_UPDATE, AutomationRule.AT_PRE, env); docNode = (NodeDocument) env.get(AutomationUtils.DOCUMENT_NODE); NodeDocumentVersion newDocVersion = NodeDocumentVersionDAO.getInstance().checkin(userId, comment, docUuid, is, size, increment); version = BaseModule.getProperties(newDocVersion); // AUTOMATION - POST AutomationManager.getInstance().fireEvent(AutomationRule.EVENT_DOCUMENT_UPDATE, AutomationRule.AT_POST, env); // Add comment (as system user) String text = "New version " + version.getName() + " by " + userId + ": " + comment; BaseNoteModule.create(docUuid, Config.SYSTEM_USER, text); // Remove pdf & preview from cache CommonGeneralModule.cleanPreviewCache(docUuid); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, userId, "CHECKIN_DOCUMENT", comment); // Activity log UserActivity.log(auth.getName(), "CHECKIN_DOCUMENT", docUuid, docPath, size + ", " + comment); } catch (DatabaseException e) { throw e; } finally { IOUtils.closeQuietly(is); org.apache.commons.io.FileUtils.deleteQuietly(tmp); if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("checkin.Time: {}", System.currentTimeMillis() - begin); log.debug("checkin: {}", version); return version; } @Override public LockInfo lock(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("lock({}, {})", token, docId); LockInfo lck = null; Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); NodeLock nLock = NodeDocumentDAO.getInstance().lock(auth.getName(), docUuid); lck = BaseModule.getProperties(nLock, docPath); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), "LOCK_DOCUMENT", null); // Activity log UserActivity.log(auth.getName(), "LOCK_DOCUMENT", docUuid, docPath, lck.getToken()); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("lock: {}", lck); return lck; } @Override public void unlock(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("unlock({}, {})", token, docId); unlockHelper(token, docId, false); log.debug("unlock: void"); } @Override public void forceUnlock(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException, PrincipalAdapterException { log.debug("forceUnlock({}, {})", token, docId); if (PrincipalUtils.getRoles().contains(Config.DEFAULT_ADMIN_ROLE)) { unlockHelper(token, docId, true); } else { throw new AccessDeniedException("Only administrator use allowed"); } log.debug("forceUnlock: void"); } /** * Implement unlock and forceUnlock features */ private void unlockHelper(String token, String docId, boolean force) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("unlock({}, {}, {})", new Object[] { token, docId, force }); Authentication auth = null, oldAuth = null; String action = force ? "FORCE_UNLOCK_DOCUMENT" : "UNLOCK_DOCUMENT"; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); NodeDocumentDAO.getInstance().unlock(auth.getName(), docUuid, force); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), action, null); // Activity log UserActivity.log(auth.getName(), action, docUuid, docPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("unlock: void"); } @Override public boolean isLocked(String token, String docId) throws RepositoryException, PathNotFoundException, DatabaseException { log.debug("isLocked({}, {})", token, docId); boolean locked = false; @SuppressWarnings("unused") Authentication auth = null, oldAuth = null; @SuppressWarnings("unused") String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } locked = NodeDocumentDAO.getInstance().isLocked(docUuid); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("isLocked: {}", locked); return locked; } @Override public LockInfo getLockInfo(String token, String docId) throws RepositoryException, PathNotFoundException, LockException, DatabaseException { log.debug("getLock({}, {})", token, docId); LockInfo lock = null; @SuppressWarnings("unused") Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeLock nLock = NodeDocumentDAO.getInstance().getLock(docUuid); lock = BaseModule.getProperties(nLock, docPath); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("getLock: {}", lock); return lock; } @Override public void purge(String token, String docId) throws LockException, AccessDeniedException, RepositoryException, PathNotFoundException, DatabaseException { log.debug("purge({}, {})", token, docId); @SuppressWarnings("unused") Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } if (Config.REPOSITORY_PURGATORY_HOME != null && !Config.REPOSITORY_PURGATORY_HOME.isEmpty()) { File dateDir = FileUtils.createDateDir(Config.REPOSITORY_PURGATORY_HOME); File dstPath = new File(dateDir, PathUtils.getName(docPath)); RepositoryExporter.exportDocument(null, docPath, dstPath.getPath(), true, false, null, null); } NodeDocumentDAO.getInstance().purge(docUuid); // Activity log - Already inside DAO // UserActivity.log(auth.getName(), "PURGE_DOCUMENT", docUuid, docPath, null); } catch (IOException e) { throw new RepositoryException(e.getMessage(), e); } catch (ParseException e) { throw new RepositoryException(e.getMessage(), e); } catch (NoSuchGroupException e) { throw new RepositoryException(e.getMessage(), e); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("purge: void"); } @Override public void move(String token, String docId, String dstId) throws PathNotFoundException, ItemExistsException, AccessDeniedException, LockException, RepositoryException, DatabaseException, ExtensionException, AutomationException { log.debug("move({}, {}, {})", new Object[] { token, docId, dstId }); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; String dstPath = null; String dstUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } if (PathUtils.isPath(dstId)) { if (!PathUtils.checkPath(dstId)) { throw new RepositoryException("Invalid destination path: " + dstId); } dstPath = dstId; dstUuid = NodeBaseDAO.getInstance().getUuidFromPath(dstId); } else { dstPath = NodeBaseDAO.getInstance().getPathFromUuid(dstId); dstUuid = dstId; if (!PathUtils.checkPath(dstPath)) { throw new RepositoryException("Invalid destination path: " + dstPath); } } // AUTOMATION - PRE Map<String, Object> env = new HashMap<String, Object>(); env.put(AutomationUtils.DOCUMENT_UUID, docUuid); env.put(AutomationUtils.FOLDER_UUID, dstUuid); AutomationManager.getInstance().fireEvent(AutomationRule.EVENT_DOCUMENT_MOVE, AutomationRule.AT_PRE, env); NodeDocumentDAO.getInstance().move(docUuid, dstUuid); // AUTOMATION - POST AutomationManager.getInstance().fireEvent(AutomationRule.EVENT_DOCUMENT_MOVE, AutomationRule.AT_POST, env); // Activity log UserActivity.log(auth.getName(), "MOVE_DOCUMENT", docUuid, docPath, dstPath); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("move: void"); } @Override public void copy(String token, String docPath, String dstPath) throws ItemExistsException, PathNotFoundException, AccessDeniedException, RepositoryException, IOException, AutomationException, DatabaseException, UserQuotaExceededException { log.debug("copy({}, {}, {})", new Object[] { token, docPath, dstPath }); extendedCopy(token, docPath, dstPath, PathUtils.getName(docPath), new ExtendedAttributes()); } @Override public void extendedCopy(String token, String docId, String dstId, String docName, ExtendedAttributes extAttr) throws ItemExistsException, PathNotFoundException, AccessDeniedException, RepositoryException, IOException, AutomationException, DatabaseException, UserQuotaExceededException { log.debug("extendedCopy({}, {}, {}, {}, {})", new Object[] { token, docId, dstId, docName, extAttr }); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; String dstPath = null; String dstUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } if (PathUtils.isPath(dstId)) { dstPath = dstId; dstUuid = NodeBaseDAO.getInstance().getUuidFromPath(dstId); } else { dstPath = NodeBaseDAO.getInstance().getPathFromUuid(dstId); dstUuid = dstId; } if (docName == null) { docName = PathUtils.getName(docPath); } else { // Escape dangerous chars in name docName = PathUtils.escape(docName); } NodeDocument srcDocNode = NodeDocumentDAO.getInstance().findByPk(docUuid, extAttr.isPropertyGroups()); NodeFolder dstFldNode = NodeFolderDAO.getInstance().findByPk(dstUuid); NodeDocument newDocNode = BaseDocumentModule.copy(auth.getName(), srcDocNode, dstPath, dstFldNode, docName, extAttr); // Check subscriptions BaseNotificationModule.checkSubscriptions(dstFldNode, auth.getName(), "COPY_DOCUMENT", null); // Activity log UserActivity.log(auth.getName(), "COPY_DOCUMENT", newDocNode.getUuid(), docPath, dstPath); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } } @Override public void restoreVersion(String token, String docId, String versionId) throws PathNotFoundException, AccessDeniedException, LockException, RepositoryException, DatabaseException { log.debug("restoreVersion({}, {}, {})", new Object[] { token, docId, versionId }); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocumentVersionDAO.getInstance().restoreVersion(docUuid, versionId); // Remove pdf & preview from cache CommonGeneralModule.cleanPreviewCache(docUuid); // Activity log UserActivity.log(auth.getName(), "RESTORE_DOCUMENT_VERSION", docUuid, docPath, versionId); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("restoreVersion: void"); } @Override public void purgeVersionHistory(String token, String docId) throws AccessDeniedException, PathNotFoundException, LockException, RepositoryException, DatabaseException { log.debug("purgeVersionHistory({}, {})", token, docId); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocumentVersionDAO.getInstance().purgeVersionHistory(docUuid); // Activity log UserActivity.log(auth.getName(), "PURGE_DOCUMENT_VERSION_HISTORY", docUuid, docPath, null); } catch (IOException e) { throw new RepositoryException(e.getMessage(), e); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("purgeVersionHistory: void"); } @Override public List<Version> getVersionHistory(String token, String docId) throws PathNotFoundException, RepositoryException, DatabaseException { log.debug("getVersionHistory({}, {})", token, docId); List<Version> history = new ArrayList<Version>(); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } List<NodeDocumentVersion> docVersions = NodeDocumentVersionDAO.getInstance().findByParent(docUuid); for (NodeDocumentVersion nDocVersion : docVersions) { history.add(BaseModule.getProperties(nDocVersion)); } // Activity log UserActivity.log(auth.getName(), "GET_DOCUMENT_VERSION_HISTORY", docUuid, docPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("getVersionHistory: {}", history); return history; } @Override @SuppressWarnings("unused") public long getVersionHistorySize(String token, String docId) throws RepositoryException, PathNotFoundException, DatabaseException { log.debug("getVersionHistorySize({}, {})", token, docId); long versionHistorySize = 0; Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } List<NodeDocumentVersion> docVersions = NodeDocumentVersionDAO.getInstance().findByParent(docUuid); for (NodeDocumentVersion nDocVersion : docVersions) { versionHistorySize += nDocVersion.getSize(); } } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("getVersionHistorySize: {}", versionHistorySize); return versionHistorySize; } @Override public boolean isValid(String token, String docId) throws PathNotFoundException, RepositoryException, DatabaseException { log.debug("isValid({}, {})", token, docId); boolean valid = true; @SuppressWarnings("unused") Authentication auth = null, oldAuth = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docUuid = docId; } try { NodeDocumentDAO.getInstance().findByPk(docUuid); } catch (PathNotFoundException e) { valid = false; } } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("isValid: {}", valid); return valid; } @Override public String getPath(String token, String uuid) throws AccessDeniedException, RepositoryException, DatabaseException { try { return NodeBaseDAO.getInstance().getPathFromUuid(uuid); } catch (PathNotFoundException e) { throw new RepositoryException(e.getMessage(), e); } } /* * ======================== * LiveEdit methods * ========================= */ /** * Create temporal file and set content. */ public void liveEditSetContent(String token, String docId, InputStream is) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException { log.debug("liveEditSetContent({}, {})", new Object[] { docId, is }); Authentication auth = null, oldAuth = null; int size = is.available(); String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } String name = PathUtils.getName(docPath); int idx = name.lastIndexOf('.'); String fileExtension = idx > 0 ? name.substring(idx) : ".tmp"; File tmp = File.createTempFile("okm", fileExtension); try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (Config.MAX_FILE_SIZE > 0 && size > Config.MAX_FILE_SIZE) { log.error("Uploaded file size: {} ({}), Max file size: {} ({})", new Object[] { FormatUtil.formatSize(size), size, FormatUtil.formatSize(Config.MAX_FILE_SIZE), Config.MAX_FILE_SIZE }); UserActivity.log(auth.getName(), "ERROR_FILE_SIZE_EXCEEDED", null, docPath, FormatUtil.formatSize(size)); throw new FileSizeExceededException(FormatUtil.formatSize(size)); } // Manage temporary files byte[] buff = new byte[4 * 1024]; FileOutputStream fos = new FileOutputStream(tmp); int read; while ((read = is.read(buff)) != -1) { fos.write(buff, 0, read); } fos.flush(); fos.close(); is.close(); is = new FileInputStream(tmp); if (!Config.SYSTEM_ANTIVIR.equals("")) { String info = VirusDetection.detect(tmp); if (info != null) { UserActivity.log(auth.getName(), "ERROR_VIRUS_DETECTED", null, docPath, info); throw new VirusDetectedException(info); } } NodeDocumentVersionDAO.getInstance().liveEditSetContent(docUuid, is, size); } catch (DatabaseException e) { throw e; } finally { IOUtils.closeQuietly(is); org.apache.commons.io.FileUtils.deleteQuietly(tmp); if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("liveEditSetContent: void"); } /** * New version and delete temporal file. */ public Version liveEditCheckin(String token, String docId, String comment, int increment) throws FileSizeExceededException, UserQuotaExceededException, VirusDetectedException, AccessDeniedException, RepositoryException, PathNotFoundException, LockException, VersionException, IOException, DatabaseException { log.debug("liveEditCheckin({}, {}, {})", new Object[] { token, docId, comment }); Version version = new Version(); Authentication auth = null, oldAuth = null; String docPath = null; String docUuid = null; if (Config.SYSTEM_READONLY) { throw new AccessDeniedException("System is in read-only mode"); } try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); NodeDocumentVersion newDocVersion = NodeDocumentVersionDAO.getInstance().liveEditCheckin(auth.getName(), comment, increment, docUuid); version = BaseModule.getProperties(newDocVersion); // Add comment (as system user) String text = "New version " + version.getName() + " by " + auth.getName() + ": " + comment; BaseNoteModule.create(docUuid, Config.SYSTEM_USER, text); // Remove pdf & preview from cache CommonGeneralModule.cleanPreviewCache(docUuid); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), "CHECKIN_DOCUMENT", comment); // Activity log UserActivity.log(auth.getName(), "CHECKIN_DOCUMENT", docUuid, docPath, newDocVersion.getSize() + ", " + comment); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.debug("tempCheckin: {}", version); return version; } /** * Cancel checkout and delete temporal file. */ public void liveEditCancelCheckout(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("liveEditCancelCheckout({}, {})", token, docId); liveEditCancelCheckoutHelper(token, docId, false); log.debug("liveEditCancelCheckout: void"); } /** * Cancel checkout and delete temporal file. */ public void liveEditForceCancelCheckout(String token, String docId) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("liveEditForceCancelCheckout({}, {})", token, docId); if (PrincipalUtils.getRoles().contains(Config.DEFAULT_ADMIN_ROLE)) { liveEditCancelCheckoutHelper(token, docId, true); } else { throw new AccessDeniedException("Only administrator use allowed"); } log.debug("liveEditForceCancelCheckout: void"); } private void liveEditCancelCheckoutHelper(String token, String docId, boolean force) throws LockException, PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException { log.debug("liveEditCancelCheckoutHelper({}, {}, {})", new Object[] { token, docId, force }); long begin = System.currentTimeMillis(); Authentication auth = null, oldAuth = null; String action = force ? "FORCE_CANCEL_DOCUMENT_CHECKOUT" : "CANCEL_DOCUMENT_CHECKOUT"; String docPath = null; String docUuid = null; try { if (token == null) { auth = PrincipalUtils.getAuthentication(); } else { oldAuth = PrincipalUtils.getAuthentication(); auth = PrincipalUtils.getAuthenticationByToken(token); } if (PathUtils.isPath(docId)) { docPath = docId; docUuid = NodeBaseDAO.getInstance().getUuidFromPath(docId); } else { docPath = NodeBaseDAO.getInstance().getPathFromUuid(docId); docUuid = docId; } NodeDocument docNode = NodeDocumentDAO.getInstance().findByPk(docUuid); NodeDocumentDAO.getInstance().liveEditCancelCheckout(auth.getName(), docUuid, force); // Check subscriptions BaseNotificationModule.checkSubscriptions(docNode, auth.getName(), action, null); // Activity log UserActivity.log(auth.getName(), action, docUuid, docPath, null); } catch (DatabaseException e) { throw e; } finally { if (token != null) { PrincipalUtils.setAuthentication(oldAuth); } } log.trace("liveEditCancelCheckoutHelper.Time: {}", System.currentTimeMillis() - begin); log.debug("liveEditCancelCheckoutHelper: void"); } }