Java tutorial
/** * openkm, Open Document Management System (http://www.openkm.com) * Copyright (c) 2006-2013 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.ikon.dao; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.commons.io.IOUtils; import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.cybozu.labs.langdetect.Detector; import com.cybozu.labs.langdetect.DetectorFactory; import com.cybozu.labs.langdetect.LangDetectException; import com.ikon.automation.AutomationManager; import com.ikon.automation.AutomationUtils; import com.ikon.bean.Permission; import com.ikon.cache.UserItemsManager; import com.ikon.core.AccessDeniedException; import com.ikon.core.Config; import com.ikon.core.DatabaseException; import com.ikon.core.ItemExistsException; import com.ikon.core.LockException; import com.ikon.core.PathNotFoundException; import com.ikon.dao.bean.AutomationRule; import com.ikon.dao.bean.NodeBase; import com.ikon.dao.bean.NodeDocument; import com.ikon.dao.bean.NodeDocumentVersion; import com.ikon.dao.bean.NodeFolder; import com.ikon.dao.bean.NodeLock; import com.ikon.extractor.RegisteredExtractors; import com.ikon.extractor.TextExtractorWork; import com.ikon.module.common.CommonGeneralModule; import com.ikon.module.db.stuff.FsDataStore; import com.ikon.module.db.stuff.LockHelper; import com.ikon.module.db.stuff.SecurityHelper; import com.ikon.module.jcr.stuff.JCRUtils; import com.ikon.spring.PrincipalUtils; import com.ikon.util.FormatUtil; import com.ikon.util.PathUtils; import com.ikon.util.UserActivity; import com.ikon.vernum.VersionNumerationAdapter; import com.ikon.vernum.VersionNumerationFactory; public class NodeDocumentDAO { private static Logger log = LoggerFactory.getLogger(NodeDocumentDAO.class); private static NodeDocumentDAO single = new NodeDocumentDAO(); private NodeDocumentDAO() { } public static NodeDocumentDAO getInstance() { return single; } /** * Create document and first version */ public NodeDocumentVersion create(NodeDocument nDoc, InputStream is, long size) throws PathNotFoundException, AccessDeniedException, ItemExistsException, DatabaseException, IOException { log.debug("create({}, {}, {})", new Object[] { nDoc, is, size }); Session session = null; Transaction tx = null; NodeDocumentVersion newDocVer = new NodeDocumentVersion(); try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeBase parentNode = (NodeBase) session.load(NodeBase.class, nDoc.getParent()); SecurityHelper.checkRead(parentNode); SecurityHelper.checkWrite(parentNode); // Check for same document name in same folder NodeBaseDAO.getInstance().checkItemExistence(session, nDoc.getParent(), nDoc.getName()); // Create first document version VersionNumerationAdapter verNumAdapter = VersionNumerationFactory.getVersionNumerationAdapter(); newDocVer.setUuid(UUID.randomUUID().toString()); newDocVer.setParent(nDoc.getUuid()); newDocVer.setName(verNumAdapter.getInitialVersionNumber()); newDocVer.setAuthor(nDoc.getAuthor()); newDocVer.setCurrent(true); newDocVer.setCreated(nDoc.getCreated()); newDocVer.setSize(size); newDocVer.setMimeType(nDoc.getMimeType()); // Persist file in datastore FsDataStore.persist(newDocVer, is); session.save(nDoc); session.save(newDocVer); HibernateUtil.commit(tx); log.debug("create: {}", newDocVer); return newDocVer; } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (ItemExistsException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); // What happen when create fails? This datastore file should be deleted! FsDataStore.delete(newDocVer.getUuid()); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Find all documents */ @SuppressWarnings("unchecked") public List<NodeDocument> findAll() throws DatabaseException { log.debug("findAll()"); Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); Query q = session.createQuery("from NodeDocument nd"); List<NodeDocument> ret = q.list(); // Security Check SecurityHelper.pruneNodeList(ret); initialize(ret); log.debug("findAll: {}", ret); return ret; } catch (HibernateException e) { throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Find by parent */ @SuppressWarnings("unchecked") public List<NodeDocument> findByParent(String parentUuid) throws PathNotFoundException, DatabaseException { log.debug("findByParent({})", parentUuid); String qs = "from NodeDocument nd where nd.parent=:parent order by nd.name"; Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check if (!Config.ROOT_NODE_UUID.equals(parentUuid)) { NodeBase parentNode = (NodeBase) session.load(NodeBase.class, parentUuid); SecurityHelper.checkRead(parentNode); } Query q = session.createQuery(qs); q.setString("parent", parentUuid); List<NodeDocument> ret = q.list(); // Security Check SecurityHelper.pruneNodeList(ret); initialize(ret); HibernateUtil.commit(tx); log.debug("findByParent: {}", ret); return ret; } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Find by pk */ public NodeDocument findByPk(String uuid) throws PathNotFoundException, DatabaseException { return findByPk(uuid, false); } /** * Find by pk and optionally initialize node property groups */ public NodeDocument findByPk(String uuid, boolean initPropGroups) throws PathNotFoundException, DatabaseException { log.debug("findByPk({}, {})", uuid, initPropGroups); String qs = "from NodeDocument nd where nd.uuid=:uuid"; Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); Query q = session.createQuery(qs); q.setString("uuid", uuid); NodeDocument nDoc = (NodeDocument) q.setMaxResults(1).uniqueResult(); if (nDoc == null) { throw new PathNotFoundException(uuid); } // Security Check SecurityHelper.checkRead(nDoc); initialize(nDoc, initPropGroups); log.debug("findByPk: {}", nDoc); return nDoc; } catch (HibernateException e) { throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Search nodes by category */ @SuppressWarnings("unchecked") public List<NodeDocument> findByCategory(String catUuid) throws PathNotFoundException, DatabaseException { log.debug("findByCategory({})", catUuid); final String qs = "from NodeDocument nd where :category in elements(nd.categories) order by nd.name"; List<NodeDocument> ret = new ArrayList<NodeDocument>(); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeBase catNode = (NodeBase) session.load(NodeBase.class, catUuid); SecurityHelper.checkRead(catNode); Query q = session.createQuery(qs); q.setString("category", catUuid); ret = q.list(); // Security Check SecurityHelper.pruneNodeList(ret); initialize(ret); HibernateUtil.commit(tx); log.debug("findByCategory: {}", ret); return ret; } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Search nodes by keyword */ @SuppressWarnings("unchecked") public List<NodeDocument> findByKeyword(String keyword) throws DatabaseException { log.debug("findByKeyword({})", keyword); final String qs = "from NodeDocument nd where :keyword in elements(nd.keywords) order by nd.name"; List<NodeDocument> ret = new ArrayList<NodeDocument>(); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setString("keyword", keyword); ret = q.list(); // Security Check SecurityHelper.pruneNodeList(ret); initialize(ret); HibernateUtil.commit(tx); log.debug("findByKeyword: {}", ret); return ret; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Search nodes by property value */ @SuppressWarnings("unchecked") public List<NodeDocument> findByPropertyValue(String group, String property, String value) throws DatabaseException { log.debug("findByPropertyValue({}, {}, {})", property, value); String qs = "select nb from NodeDocument nb join nb.properties nbp where nbp.group=:group and nbp.name=:property and nbp.value like :value"; Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setString("group", group); q.setString("property", property); q.setString("value", "%" + value + "%"); List<NodeDocument> ret = q.list(); // Security Check SecurityHelper.pruneNodeList(ret); initialize(ret); HibernateUtil.commit(tx); log.debug("findByPropertyValue: {}", ret); return ret; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Search nodes from a given parent recursively */ public List<NodeDocument> findFromParent(String parentUuid) throws DatabaseException { log.debug("findFromParent({}})", parentUuid); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); List<NodeDocument> ret = findFromParentHelper(session, parentUuid); HibernateUtil.commit(tx); log.debug("findFromParent: {}", ret); return ret; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } @SuppressWarnings("unchecked") private List<NodeDocument> findFromParentHelper(Session session, String parentUuid) throws DatabaseException, HibernateException { List<NodeDocument> nodeList = new ArrayList<NodeDocument>(); String qs = "from NodeBase n where n.parent=:parent"; Query q = session.createQuery(qs); q.setString("parent", parentUuid); List<NodeBase> nodes = q.list(); for (NodeBase nBase : nodes) { if (SecurityHelper.getAccessManager().isGranted(nBase, Permission.READ)) { if (nBase instanceof NodeFolder) { nodeList.addAll(findFromParentHelper(session, nBase.getUuid())); } else if (nBase instanceof NodeDocument) { NodeDocument nDoc = (NodeDocument) nBase; initialize(nDoc, false); nodeList.add(nDoc); } } } return nodeList; } /** * Check if folder has children */ @SuppressWarnings("unchecked") public boolean hasChildren(String parentUuid) throws PathNotFoundException, DatabaseException { log.debug("hasChildren({})", parentUuid); String qs = "from NodeDocument nd where nd.parent=:parent"; Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check if (!Config.ROOT_NODE_UUID.equals(parentUuid)) { NodeBase parentNode = (NodeBase) session.load(NodeBase.class, parentUuid); SecurityHelper.checkRead(parentNode); } Query q = session.createQuery(qs); q.setString("parent", parentUuid); List<NodeFolder> nodeList = q.list(); // Security Check SecurityHelper.pruneNodeList(nodeList); boolean ret = !nodeList.isEmpty(); HibernateUtil.commit(tx); log.debug("hasChildren: {}", ret); return ret; } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Rename document */ public NodeDocument rename(String uuid, String newName) throws PathNotFoundException, AccessDeniedException, ItemExistsException, LockException, DatabaseException { log.debug("rename({}, {})", uuid, newName); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeBase parentNode = NodeBaseDAO.getInstance().getParentNode(session, uuid); SecurityHelper.checkRead(parentNode); SecurityHelper.checkWrite(parentNode); NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); // Lock Check LockHelper.checkWriteLock(nDoc); // Check for same folder name in same parent NodeBaseDAO.getInstance().checkItemExistence(session, nDoc.getParent(), newName); nDoc.setName(newName); session.update(nDoc); initialize(nDoc, false); HibernateUtil.commit(tx); log.debug("rename: {}", nDoc); return nDoc; } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (ItemExistsException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Move document */ public void move(String uuid, String dstUuid) throws PathNotFoundException, AccessDeniedException, ItemExistsException, LockException, DatabaseException { log.debug("move({}, {})", uuid, dstUuid); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeFolder nDstFld = (NodeFolder) session.load(NodeFolder.class, dstUuid); SecurityHelper.checkRead(nDstFld); SecurityHelper.checkWrite(nDstFld); NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); // Lock Check LockHelper.checkWriteLock(nDoc); // Check for same folder name in same parent NodeBaseDAO.getInstance().checkItemExistence(session, dstUuid, nDoc.getName()); // Check if context changes if (!nDstFld.getContext().equals(nDoc.getContext())) { nDoc.setContext(nDstFld.getContext()); } nDoc.setParent(dstUuid); session.update(nDoc); HibernateUtil.commit(tx); log.debug("move: void"); } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (ItemExistsException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Delete document */ public void delete(String name, String uuid, String trashUuid, String docPath) throws PathNotFoundException, AccessDeniedException, LockException, DatabaseException { log.debug("delete({}, {}, {})", new Object[] { name, uuid, trashUuid }); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeFolder nTrashFld = (NodeFolder) session.load(NodeFolder.class, trashUuid); SecurityHelper.checkRead(nTrashFld); SecurityHelper.checkWrite(nTrashFld); NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); // Lock Check LockHelper.checkWriteLock(nDoc); // Test if already exists a document with the same name in the trash String fileName = com.ikon.util.FileUtils.getFileName(name); String fileExtension = com.ikon.util.FileUtils.getFileExtension(name); String testName = name; for (int i = 1; NodeBaseDAO.getInstance().testItemExistence(session, trashUuid, testName); i++) { // log.info("Trying with: {}", testName); testName = fileName + " (" + i + ")." + fileExtension; } nDoc.setContext(nTrashFld.getContext()); nDoc.setParent(trashUuid); nDoc.setName(testName); nDoc.setNbsOriginalPath(docPath); session.update(nDoc); HibernateUtil.commit(tx); log.debug("delete: void"); } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Checkout */ public void checkout(String user, String uuid) throws PathNotFoundException, AccessDeniedException, LockException, DatabaseException { log.debug("checkout({})", uuid); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); nDoc.setCheckedOut(true); lock(session, user, nDoc); session.update(nDoc); HibernateUtil.commit(tx); log.debug("checkout: void"); } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Cancel checkout */ public void cancelCheckout(String user, String uuid, boolean force) throws PathNotFoundException, AccessDeniedException, LockException, DatabaseException { log.debug("cancelCheckout({}, {}, {})", new Object[] { user, uuid, force }); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); nDoc.setCheckedOut(false); unlock(session, user, nDoc, force); session.update(nDoc); HibernateUtil.commit(tx); log.debug("cancelCheckout: void"); } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Test for checked out status */ public boolean isCheckedOut(String uuid) throws PathNotFoundException, DatabaseException { log.debug("isCheckedOut({})", uuid); Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); boolean checkedOut = nDoc.isCheckedOut(); log.debug("isCheckedOut: {}", checkedOut); return checkedOut; } catch (PathNotFoundException e) { throw e; } catch (HibernateException e) { throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Purge in depth */ public void purge(String uuid) throws PathNotFoundException, AccessDeniedException, LockException, DatabaseException, IOException { log.debug("purge({})", uuid); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); purgeHelper(session, nDoc); HibernateUtil.commit(tx); log.debug("purge: void"); } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw e; } catch (AccessDeniedException e) { HibernateUtil.rollback(tx); throw e; } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (IOException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Purge in depth helper * * @see com.ikon.dao.NodeFolderDAO.purgeHelper(Session, NodeFolder, boolean) * @see com.ikon.dao.NodeMailDAO.purgeHelper(Session, NodeMail) */ @SuppressWarnings("unchecked") public void purgeHelper(Session session, String parentUuid) throws PathNotFoundException, AccessDeniedException, LockException, IOException, DatabaseException, HibernateException { String qs = "from NodeDocument nd where nd.parent=:parent"; Query q = session.createQuery(qs); q.setString("parent", parentUuid); List<NodeDocument> listAttachments = q.list(); for (NodeDocument nDocument : listAttachments) { purgeHelper(session, nDocument); } } /** * Purge in depth helper */ private void purgeHelper(Session session, NodeDocument nDocument) throws PathNotFoundException, AccessDeniedException, LockException, IOException, DatabaseException, HibernateException { String path = NodeBaseDAO.getInstance().getPathFromUuid(session, nDocument.getUuid()); String user = PrincipalUtils.getUser(); String author = nDocument.getAuthor(); // Security Check SecurityHelper.checkRead(nDocument); SecurityHelper.checkDelete(nDocument); // Lock Check LockHelper.checkWriteLock(nDocument); // Remove pdf & preview from cache CommonGeneralModule.cleanPreviewCache(nDocument.getUuid()); // Delete children document versions NodeDocumentVersionDAO.getInstance().purgeHelper(session, nDocument.getUuid()); // Delete children notes NodeNoteDAO.getInstance().purgeHelper(session, nDocument.getUuid()); // Delete bookmarks BookmarkDAO.purgeBookmarksByNode(nDocument.getUuid()); // Delete the node itself session.delete(nDocument); // Update user items size if (Config.USER_ITEM_CACHE) { UserItemsManager.decDocuments(author, 1); } // Activity log UserActivity.log(user, "PURGE_DOCUMENT", nDocument.getUuid(), path, null); } /** * Lock node */ public NodeLock lock(String user, String uuid) throws PathNotFoundException, AccessDeniedException, LockException, DatabaseException { log.debug("lock({}, {})", user, uuid); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); lock(session, user, nDoc); session.update(nDoc); HibernateUtil.commit(tx); log.debug("lock: {}", nDoc.getLock()); return nDoc.getLock(); } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Lock node */ public void lock(Session session, String user, NodeDocument nDoc) throws HibernateException, LockException { if (!nDoc.isLocked()) { String token = JCRUtils.getLockToken(nDoc.getUuid()); NodeLock nLock = new NodeLock(); nLock.setToken(token); nLock.setOwner(user); nLock.setCreated(Calendar.getInstance()); nDoc.setLock(nLock); nDoc.setLocked(true); } else { throw new LockException("Node already locked"); } } /** * Unlock node */ public void unlock(String user, String uuid, boolean force) throws PathNotFoundException, AccessDeniedException, DatabaseException, LockException { log.debug("unlock({}, {}, {})", new Object[] { user, uuid, force }); Session session = null; Transaction tx = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); SecurityHelper.checkWrite(nDoc); unlock(session, user, nDoc, force); session.update(nDoc); HibernateUtil.commit(tx); log.debug("unlock: void"); } catch (LockException e) { HibernateUtil.rollback(tx); throw e; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Unlock node */ public void unlock(Session session, String user, NodeDocument nDoc, boolean force) throws HibernateException, LockException { if (nDoc.isLocked()) { if (force || user.equals(nDoc.getLock().getOwner())) { nDoc.setLock(null); nDoc.setLocked(false); } else { throw new LockException("Node not locked by user"); } } else { throw new LockException("Node not locked"); } } /** * Test for locked status */ public boolean isLocked(String uuid) throws PathNotFoundException, DatabaseException { log.debug("isLocked({})", uuid); Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); boolean locked = nDoc.isLocked(); log.debug("isLocked: {}", locked); return locked; } catch (HibernateException e) { throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Test for locked status */ public NodeLock getLock(String uuid) throws PathNotFoundException, LockException, DatabaseException { log.debug("getLock({})", uuid); Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); NodeLock nLock = nDoc.getLock(); if (nLock == null) { throw new LockException("Node not locked: " + uuid); } log.debug("getLock: {}", nLock); return nLock; } catch (HibernateException e) { throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Get document node size. * * @see com.ikon.module.nr.NrStatsModule */ public long getSize(String context) throws PathNotFoundException, DatabaseException { log.debug("getSize({})", context); String qs = "select coalesce(sum(ndv.size), 0) from NodeDocumentVersion ndv " + "where ndv.current = :current and ndv.parent in " + "(select nd.uuid from NodeDocument nd where nd.context = :context)"; Session session = null; Transaction tx = null; long total = 0; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setBoolean("current", true); q.setString("context", PathUtils.fixContext(context)); total = (Long) q.setMaxResults(1).uniqueResult(); HibernateUtil.commit(tx); log.debug("getSize: {}", total); return total; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw e; } finally { HibernateUtil.close(session); } } /** * Get document node size. * * @see com.ikon.module.nr.NrStatsModule */ public long getSubtreeSize(String path) throws PathNotFoundException, DatabaseException { log.debug("getSubtreeSize({})", path); Session session = null; Transaction tx = null; long total = 0; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); String uuid = NodeBaseDAO.getInstance().getUuidFromPath(path); total = getSubtreeSizeHelper(session, uuid); HibernateUtil.commit(tx); log.debug("getSubtreeSize: {}", total); return total; } catch (DatabaseException e) { HibernateUtil.rollback(tx); throw e; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw e; } finally { HibernateUtil.close(session); } } /** * Helper method. */ @SuppressWarnings("unchecked") private long getSubtreeSizeHelper(Session session, String parentUuid) throws HibernateException, DatabaseException { log.debug("getSubtreeSizeHelper({})", new Object[] { parentUuid }); String qs = "from NodeBase n where n.parent=:parent"; Query q = session.createQuery(qs); q.setString("parent", parentUuid); List<NodeBase> nodes = q.list(); long total = 0; for (NodeBase nBase : nodes) { if (nBase instanceof NodeFolder) { total += getSubtreeSizeHelper(session, nBase.getUuid()); } else if (nBase instanceof NodeDocument) { NodeDocumentVersion nDocVer = NodeDocumentVersionDAO.getInstance().findCurrentVersion(session, nBase.getUuid()); total += nDocVer.getSize(); } } return total; } /** * Clear pending extraction queue */ public int resetAllPendingExtractionFlags() throws DatabaseException { log.debug("resetAllPendingExtractionFlags()"); String qs = "update NodeDocument nd set nd.textExtracted=:extracted"; Session session = null; Transaction tx = null; int rowCount = 0; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setBoolean("extracted", false); rowCount = q.executeUpdate(); HibernateUtil.commit(tx); log.debug("resetAllPendingExtractionFlags: {}", rowCount); return rowCount; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Clear pending extraction queue */ public int resetPendingExtractionFlag(String docUuid) throws DatabaseException { log.debug("resetPendingExtractionFlag({})", docUuid); String qs = "update NodeDocument nd set nd.textExtracted=:extracted where nd.uuid=:uuid"; Session session = null; Transaction tx = null; int rowCount = 0; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setBoolean("extracted", false); q.setString("uuid", docUuid); rowCount = q.executeUpdate(); HibernateUtil.commit(tx); log.debug("resetPendingExtractionFlag: {}", rowCount); return rowCount; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Check for extraction queue */ public boolean hasPendingExtractions() throws DatabaseException { log.debug("hasPendingExtractions()"); String qs = "from NodeDocument nd where nd.textExtracted=:extracted"; Session session = null; Transaction tx = null; boolean ret = false; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setBoolean("extracted", false); ret = q.iterate().hasNext(); HibernateUtil.commit(tx); log.debug("hasPendingExtractions: {}", ret); return ret; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Get pending extraction queue */ @SuppressWarnings("unchecked") public List<TextExtractorWork> getPendingExtractions(int maxResults) throws DatabaseException { log.debug("getPendingExtractions({})", maxResults); String qsDoc = "select nd.uuid from NodeDocument nd where nd.textExtracted=:extracted"; String qsDocVer = "from NodeDocumentVersion ndv where ndv.parent=:parent and ndv.current=:current"; Session session = null; Transaction tx = null; List<TextExtractorWork> ret = new ArrayList<TextExtractorWork>(); try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query qDoc = session.createQuery(qsDoc); qDoc.setBoolean("extracted", false); qDoc.setMaxResults(maxResults); for (String docUuid : (List<String>) qDoc.list()) { Query qDocVer = session.createQuery(qsDocVer); qDocVer.setString("parent", docUuid); qDocVer.setBoolean("current", true); NodeDocumentVersion nDocVer = (NodeDocumentVersion) qDocVer.uniqueResult(); String docPath = NodeBaseDAO.getInstance().getPathFromUuid(session, docUuid); TextExtractorWork work = new TextExtractorWork(); work.setDocUuid(docUuid); work.setDocPath(docPath); work.setDocVerUuid(nDocVer.getUuid()); work.setDate(nDocVer.getCreated()); ret.add(work); } HibernateUtil.commit(tx); log.debug("getPendingExtractions: {}", ret); return ret; } catch (PathNotFoundException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Get pending extraction size */ public long getPendingExtractionSize() throws DatabaseException { log.debug("getPendingExtractionSize()"); String qs = "select coalesce(count(*), 0) from NodeDocument nd where nd.textExtracted=:extracted"; Session session = null; Transaction tx = null; long total = 0; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); Query q = session.createQuery(qs); q.setBoolean("extracted", false); total = (Long) q.setMaxResults(1).uniqueResult(); HibernateUtil.commit(tx); log.debug("getPendingExtractionSize: {}", total); return total; } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { HibernateUtil.close(session); } } /** * Helps on extracting text from documents */ public void textExtractorHelper(TextExtractorWork work) throws DatabaseException, FileNotFoundException { log.debug("textExtractorHelper({})", work); Session session = null; Transaction tx = null; InputStream isContent = null; try { session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); if (FsDataStore.DATASTORE_BACKEND_FS.equals(Config.REPOSITORY_DATASTORE_BACKEND)) { isContent = FsDataStore.read(work.getDocVerUuid()); } else { NodeDocumentVersion nDocVer = (NodeDocumentVersion) session.load(NodeDocumentVersion.class, work.getDocVerUuid()); isContent = new ByteArrayInputStream(nDocVer.getContent()); } NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, work.getDocUuid()); try { // AUTOMATION - PRE Map<String, Object> env = new HashMap<String, Object>(); env.put(AutomationUtils.DOCUMENT_NODE, nDoc); AutomationManager.getInstance().fireEvent(AutomationRule.EVENT_TEXT_EXTRACTOR, AutomationRule.AT_PRE, env); String textExtracted = RegisteredExtractors.getText(work.getDocPath(), nDoc.getMimeType(), null, isContent); // AUTOMATION - POST env.put(AutomationUtils.TEXT_EXTRACTED, textExtracted); AutomationManager.getInstance().fireEvent(AutomationRule.EVENT_TEXT_EXTRACTOR, AutomationRule.AT_POST, env); textExtracted = (String) env.get(AutomationUtils.TEXT_EXTRACTED); // Need to replace 0x00 because PostgreSQL does not accept string containing 0x00 textExtracted = FormatUtil.fixUTF8(textExtracted); // Need to remove Unicode surrogate because of MySQL => SQL Error: 1366, SQLState: HY000 textExtracted = FormatUtil.trimUnicodeSurrogates(textExtracted); textExtracted = textExtracted.replaceAll("[^\\w\\s\\-_]", ""); nDoc.setText(textExtracted); try { Detector lt = DetectorFactory.create(); lt.append(textExtracted); nDoc.setLanguage(lt.detect()); } catch (LangDetectException e) { log.warn("Language detection problem: {}", e.getMessage(), e); } } catch (Exception e) { try { String docPath = NodeBaseDAO.getInstance().getPathFromUuid(nDoc.getUuid()); log.warn("There was a problem extracting text from '{}': {}", docPath, e.getMessage()); UserActivity.log(Config.SYSTEM_USER, "MISC_TEXT_EXTRACTION_FAILURE", nDoc.getUuid(), docPath, e.getMessage()); } catch (PathNotFoundException pnfe) { log.warn("Item not found: {}", nDoc.getUuid()); } } nDoc.setTextExtracted(true); session.update(nDoc); HibernateUtil.commit(tx); log.debug("textExtractorHelper: void"); } catch (HibernateException e) { HibernateUtil.rollback(tx); throw new DatabaseException(e.getMessage(), e); } finally { IOUtils.closeQuietly(isContent); HibernateUtil.close(session); } log.debug("textExtractorHelper: void"); } /** * Get extracted text. */ public String getExtractedText(Session session, String uuid) throws PathNotFoundException, DatabaseException { // Security Check NodeDocument nDoc = (NodeDocument) session.load(NodeDocument.class, uuid); SecurityHelper.checkRead(nDoc); return nDoc.getText(); } /** * Force initialization of a proxy */ public void initialize(NodeDocument nDocument, boolean initPropGroups) { if (nDocument != null) { Hibernate.initialize(nDocument); Hibernate.initialize(nDocument.getKeywords()); Hibernate.initialize(nDocument.getCategories()); Hibernate.initialize(nDocument.getSubscriptors()); Hibernate.initialize(nDocument.getUserPermissions()); Hibernate.initialize(nDocument.getRolePermissions()); if (initPropGroups) { Hibernate.initialize(nDocument.getProperties()); } } } /** * Force initialization of a proxy */ private void initialize(List<NodeDocument> nDocumentList) { for (NodeDocument nDocument : nDocumentList) { initialize(nDocument, false); } } }