From 06e342af0c2aa3766376b4253f9312611caf09de Mon Sep 17 00:00:00 2001 From: tosmers Date: Wed, 16 Dec 2015 21:58:47 +0000 Subject: [PATCH] CCM_NG - docrepo - adds additional classes from docrepo to ccm_ng - adds two classes with massive errors, sorry, was necessary git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3774 8810af33-2d31-482b-a856-94f89814c4df --- .../AbstractAuditedEntityRepository.java | 7 +- .../arsdigita/docrepo/ui/FileActionPane.java | 20 +- .../arsdigita/docrepo/ui/FileEditForm.java | 2 - .../docrepo/ui/FileInfoHistoryPane.java | 2 +- .../docrepo/ui/FileRevisionsTable.java | 201 +++++++++++ .../docrepo/ui/FileSendColleagueForm.java | 240 +++++++++++++ .../arsdigita/docrepo/ui/FileUploadForm.java | 315 ++++++++++++++++++ .../docrepo/RepositoryRepository.java | 21 +- .../libreccm/docrepo/ResourceRepository.java | 47 ++- 9 files changed, 818 insertions(+), 37 deletions(-) create mode 100644 ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileRevisionsTable.java create mode 100644 ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileSendColleagueForm.java create mode 100644 ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileUploadForm.java diff --git a/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java b/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java index 3068e9424..0846703f0 100644 --- a/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java +++ b/ccm-core/src/main/java/org/libreccm/auditing/AbstractAuditedEntityRepository.java @@ -70,14 +70,13 @@ public abstract class AbstractAuditedEntityRepository * @return A list of revision numbers, at which the entity was modified, * sorted in ascending order (so older revisions come first). * - * @throws NotAuditedException When entities of the given class are not audited. + * @throws NotAuditedException When entities of the given class are not + * audited. * @throws IllegalArgumentException If cls or primaryKey is null. * @throws IllegalStateException If the associated entity manager is closed. */ public List retrieveRevisionNumbersOfEntity(final T entity, - final Long objectId) - throws IllegalArgumentException, NotAuditedException, - IllegalStateException { + final Long objectId) { return auditReader.getRevisions(entity.getClass(), objectId); } diff --git a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileActionPane.java b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileActionPane.java index 14a25d9ae..cb49c402e 100644 --- a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileActionPane.java +++ b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileActionPane.java @@ -29,7 +29,6 @@ import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.dispatcher.DispatcherHelper; -import com.arsdigita.docrepo.util.GlobalizationUtil; import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.web.Web; import org.apache.log4j.Logger; @@ -38,7 +37,6 @@ import org.libreccm.docrepo.File; import org.libreccm.docrepo.ResourceRepository; import java.io.IOException; -import java.util.Arrays; /** @@ -69,23 +67,7 @@ public class FileActionPane extends ColumnPanel implements Constants { m_parent = parent; - m_fileData = new RequestLocal() { - protected File initialValue(PageState state) { - Long fileId = (Long) state.getValue - (FILE_ID_PARAM); - - final CdiUtil cdiUtil = new CdiUtil(); - final ResourceRepository resourceRepository = cdiUtil - .findBean(ResourceRepository.class); - final File file = (File) resourceRepository.findById(fileId); - if (file == null) { - log.error(GlobalizationUtil.globalize("db.notfound.file", - Arrays.asList(fileId).toArray())); - } - - return file; - } - }; + m_fileData = new DocRepoRequestLocal(); m_newVersion = addActionLink(FILE_NEW_VERSION_LINK); diff --git a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileEditForm.java b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileEditForm.java index 464401e08..03fc5b0d5 100644 --- a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileEditForm.java +++ b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileEditForm.java @@ -44,8 +44,6 @@ import org.libreccm.docrepo.ResourceRepository; import java.util.Arrays; -//import com.arsdigita.docrepo.File; -//import com.arsdigita.docrepo.Folder; /** * This component allows to change the file name and the description of a diff --git a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileInfoHistoryPane.java b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileInfoHistoryPane.java index e0b57817c..9f1842059 100644 --- a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileInfoHistoryPane.java +++ b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileInfoHistoryPane.java @@ -24,7 +24,7 @@ import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.RequestLocal; import com.arsdigita.bebop.SegmentedPanel; import com.arsdigita.bebop.SimpleContainer; -import com.arsdigita.docrepo.File; +import org.libreccm.docrepo.File; import org.apache.log4j.Logger; /** diff --git a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileRevisionsTable.java b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileRevisionsTable.java new file mode 100644 index 000000000..5fd4d540e --- /dev/null +++ b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileRevisionsTable.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.docrepo.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import org.libreccm.docrepo.File; +import com.arsdigita.util.LockableImpl; +import org.apache.log4j.Logger; + +/** + * This component lists all file revisions in tabular form. + * The right-most column has a button to download that particular + * version. + * + * @author Stefan Deusch + * @author Tobias Osmers + */ + +public class FileRevisionsTable extends Table implements TableActionListener, + Constants { + + private static Logger log = Logger.getLogger(FileRevisionsTable.class); + + private FileInfoHistoryPane m_parent; + private static String[] s_tableHeaders = + {"", "Author", "Date", "Comments", ""}; + + /** + * Constructor. Creates a file revision table for a given file info + * history pane. + * + * @param parent The fileInfoHisoryPane + */ + public FileRevisionsTable(FileInfoHistoryPane parent) { + + super(new FileRevisionsTableModelBuilder(parent), s_tableHeaders); + m_parent = parent; + + setClassAttr("AlternateTable"); + setWidth("100%"); + setCellRenderers(); + addTableActionListener(this); + } + + public void cellSelected(TableActionEvent e) { + } + + + public void headSelected(TableActionEvent e) { + throw new UnsupportedOperationException(); + } + + private void setCellRenderers() { + getColumn(4).setCellRenderer(new LinkRenderer()); + } + + private final class LinkRenderer implements TableCellRenderer { + public Component getComponent(Table table, PageState state, + Object value, boolean isSelected, + Object key, int row, int column) { + if (value != null) { + + File file = m_parent.getFile(state); + + Link link = new Link("Download", "download/?" + FILE_ID_PARAM + .getName() + "=" + file.getObjectId() + "&trans_id=" + key); + link.setClassAttr("downloadLink"); + return link; + + } else { + return new Label(); + } + } + } + + private final class FileRevisionsTableModelBuilder extends LockableImpl + implements TableModelBuilder { + + private FileInfoHistoryPane m_parent; + + FileRevisionsTableModelBuilder(FileInfoHistoryPane parent) { + m_parent = parent; + } + + public TableModel makeModel(Table t, PageState state) { + return new FileRevisionsTableModel(m_parent.getFile(state), state); + } + } + + private final class FileRevisionsTableModel implements TableModel, + Constants { + + private FileInfoHistoryPane m_parent; + private File m_file; + private PageState m_state; + private TransactionCollection m_tc; + private Transaction m_transaction; + private Transaction m_lastContentChange; + private int m_row; + private int m_last = 2; + + FileRevisionsTableModel(File file, PageState state) { + m_file = file; + m_state = state; + + m_tc = m_file.getRevision(); + m_row = (int) m_tc.size() + 1; + m_last = m_row; + + // separate collection from last content changes + } + + public int getColumnCount() { + return 5; + } + + public Object getElementAt(int columnIndex) { + switch (columnIndex) { + case 0: + return new BigDecimal(m_row); + case 1: { + com.arsdigita.kernel.User user = m_file.getLastModifiedUser(); + if (null == user) { + return "Unknown"; + } else { + return user.getPersonName().toString(); + } + } + case 2: + if (m_row == 0) + return Utils.DateFormat.format(m_file.getCreationDate()); + else + return Utils.DateFormat.format(m_file.getLastModifiedDate()); + case 3: { + StringBuffer sb = new StringBuffer(); + TagCollection tc = m_transaction.getTags(); + int counter = 0; + while (tc.next()) { + counter++; + Tag t = tc.getTag(); + sb.append(counter + ") " + t.getDescription() + " "); + } + return sb.toString(); + } + case 4: + return "download"; + default: + break; + } + return null; + } + + public Object getKeyAt(int columnIndex) { + if (columnIndex == 4) { + if (m_row == m_last - 1) { + return "current"; + } else { + return m_transaction.getID(); + } + } else { + return m_file.getID() + "." + (m_row); + } + } + + public boolean nextRow() { + m_row--; + if (m_tc.next()) { + m_transaction = m_tc.getTransaction(); + return true; + } else { + m_tc.close(); + return false; + } + } + } +} diff --git a/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileSendColleagueForm.java b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileSendColleagueForm.java new file mode 100644 index 000000000..228d97a49 --- /dev/null +++ b/ccm-docrepo/src/main/java/com/arsdigita/docrepo/ui/FileSendColleagueForm.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.docrepo.ui; + +import com.arsdigita.bebop.ColumnPanel; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; +import com.arsdigita.docrepo.File; +import com.arsdigita.mail.Mail; +import com.arsdigita.util.StringUtils; +import org.apache.log4j.Logger; + +import javax.mail.MessagingException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +//import com.arsdigita.bebop.FormProcessException; + +/** + * This component allows the user to send the document to + * someone by e-mail. The document is enclosed as an attachment + * and send using the com.arsdigita.mail package services, this + * package is built ontop of javax.mail. + * + * @see com.arsdigita.mail + * + * @author Stefan Deusch + * @author David Dao + * @author Stefan Deusch + * @author '" + fileName + "'"); + log.debug("description == '" + fileDescription + "'"); + log.debug("path == '" + filePath + "'"); + } + + java.io.File src = null; + + if (filePath != null && filePath.length() > 0) { + HttpServletRequest mreq = e.getPageState().getRequest(); + + // Assert.assertTrue(mreq instanceof MultipartHttpServletRequest, + Assert.isTrue(mreq instanceof MultipartHttpServletRequest, + "I got a " + mreq + " when I was " + + "expecting a MultipartHttpServletRequest"); + + src = ((MultipartHttpServletRequest) mreq).getFile(FILE_UPLOAD); + log.debug("file == '" + src + "'"); + } + + Folder parent = null; + String selKey = (String) m_tree.getSelectedKey(state); + + final CdiUtil cdiUtil = new CdiUtil(); + final ResourceRepository resourceRepository = cdiUtil.findBean( + ResourceRepository.class); + + if (selKey == null) { + parent = Utils.getRootFolder(state); + } else { + Long folderID = new Long(selKey); + + final Resource resource = resourceRepository.findById(folderID); + parent = resource != null && resource.isFolder() + ? (Folder) resource : null; + } + + // insert the file in the database below parent + final File file = new File; + + file.setParent(parent); + file.setName(fileName); + file.setDescription(fileDescription); + file.setIsFolder(false); + file.setPath(filePath); + file.setMimeType(mimeType); + file.setContent(new BlobObject().setContent(src)); + + // annotate first file upload as initial version + file.setDescription(FILE_UPLOAD_INITIAL_TRANSACTION_DESCRIPTION. + localize(req).toString()); + + //file.applyTag(FILE_UPLOAD_INITIAL_TRANSACTION_DESCRIPTION. + //localize(req).toString()); + + file.save(); + + new KernelExcursion() { + protected void excurse() { + Party currentParty = Kernel.getContext().getParty(); + setParty(Kernel.getSystemParty()); + PermissionService.grantPermission(new PermissionDescriptor(PrivilegeDescriptor.ADMIN, + file, + currentParty)); + Application app = Web.getWebContext().getApplication(); + Assert.exists(app, Application.class); + PermissionService.setContext(file, app); + }}.run(); + + return file.getID(); + } + + public void init(FormSectionEvent e) { + PageState state = e.getPageState(); + + if ( Kernel.getContext().getParty() == null ) { + Util.redirectToLoginPage(state); + } + + } + + /** + * Post the file to a temporary file on the server and + * insert it into the database + */ + public void process(FormSectionEvent e) + throws FormProcessException { + log.debug("Processing form submission"); + + insertFile(e); + + if (m_parent != null) { + m_parent.displayFolderContentPanel(e.getPageState()); + } + + } + + /** + * Gets either the file name from the widget + * or takes the filename from the upload + * widget in this order. + */ + protected String getFileName(FormSectionEvent e) { + FormData data = e.getFormData(); + String filename = (String) data.get(FILE_UPLOAD); + return Utils.extractFileName(filename, e.getPageState()); + } + + + /** + * Verify that the parent folder exists and does not contain any + * other files or sub folders with the same name as the file being + * uploaded. + */ + + public void validate(FormSectionEvent e) throws FormProcessException { + PageState state = e.getPageState(); + FormData data = e.getFormData(); + HttpServletRequest req = state.getRequest(); + + String fname = Utils.extractFileName(getFileName(e), state); + + // XXX Not localized as the other errors are. + if (fname.length() > 200) { + data.addError + (FILE_UPLOAD, + "This filename is too long. It must be fewer than 200 " + + "characters."); + } + + Folder parent = null; + String selKey = (String) m_tree.getSelectedKey(state); + + if (selKey == null) { + parent = Utils.getRootFolder(state); + } else { + BigDecimal folderID = new BigDecimal(selKey); + try { + parent = new Folder(folderID); + } catch(DataObjectNotFoundException nf) { + throw new ObjectNotFoundException(FOLDER_PARENTNOTFOUND_ERROR + .localize(req).toString()); + } + } + + try { + parent.getResourceID(fname); + data.addError(FILE_UPLOAD, + RESOURCE_EXISTS_ERROR + .localize(req).toString()); + } catch(DataObjectNotFoundException nf) { + // ok here + } catch(InvalidNameException ex) { + data.addError(FILE_UPLOAD, + ex.getMessage()); + } + } +} diff --git a/ccm-docrepo/src/main/java/org/libreccm/docrepo/RepositoryRepository.java b/ccm-docrepo/src/main/java/org/libreccm/docrepo/RepositoryRepository.java index 2df56e129..9ffc08f44 100644 --- a/ccm-docrepo/src/main/java/org/libreccm/docrepo/RepositoryRepository.java +++ b/ccm-docrepo/src/main/java/org/libreccm/docrepo/RepositoryRepository.java @@ -19,6 +19,8 @@ package org.libreccm.docrepo; import org.libreccm.auditing.AbstractAuditedEntityRepository; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.PermissionChecker; import org.libreccm.security.User; import javax.enterprise.context.RequestScoped; @@ -26,6 +28,7 @@ import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import java.util.List; +import java.util.stream.Collectors; /** * Repository class for retrieving, storing and deleting {@code Repository}s. @@ -58,6 +61,22 @@ public class RepositoryRepository extends return entity.getObjectId() == 0; } + /** + * Checks if the current subject has permissions grating him the + * privilege to read the requested {@link Repository}(s) and removes the + * ones he is not allowed to access. + * + * @param repositories The requested {@link Resource}s, found in the database + * @return A list of {@link Resource}s the subject is allowed to access + */ + private List permissionFilter(List repositories) { + final CdiUtil cdiUtil = new CdiUtil(); + final PermissionChecker permissionChecker = cdiUtil.findBean( + PermissionChecker.class); + return repositories.stream().filter(repository -> permissionChecker + .isPermitted("read", repository)).collect(Collectors.toList()); + } + /** * Retrieve all {@link Repository}s a given {@link User} ownes. * @@ -70,7 +89,7 @@ public class RepositoryRepository extends "DocRepo.findRepositoriesForOwner", Repository.class); query.setParameter("owner", owner); - return query.getResultList(); + return permissionFilter(query.getResultList()); } } diff --git a/ccm-docrepo/src/main/java/org/libreccm/docrepo/ResourceRepository.java b/ccm-docrepo/src/main/java/org/libreccm/docrepo/ResourceRepository.java index 520632292..9dd98aaa2 100644 --- a/ccm-docrepo/src/main/java/org/libreccm/docrepo/ResourceRepository.java +++ b/ccm-docrepo/src/main/java/org/libreccm/docrepo/ResourceRepository.java @@ -20,14 +20,17 @@ package org.libreccm.docrepo; import org.libreccm.auditing.AbstractAuditedEntityRepository; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.PermissionChecker; import org.libreccm.security.User; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; - +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * Repository class for retrieving, storing and deleting {@code Resource}s. @@ -59,6 +62,35 @@ public class ResourceRepository extends AbstractAuditedEntityRepository permissionFilter(List resources) { + final CdiUtil cdiUtil = new CdiUtil(); + final PermissionChecker permissionChecker = cdiUtil.findBean( + PermissionChecker.class); + return resources.stream().filter(resource -> permissionChecker + .isPermitted("read", resource)).collect(Collectors.toList()); + } + + /** + * Checks if the current subject has permissions grating him the + * privilege to read the one requested {@link Resource} and removes it if + * he is not allowed to access. + * + * @param resource The requested {@link Resource}, found in the database + * @return A list of at most one {@link Resource} the subject is allowed to + * access + */ + private Resource permissionFilter(Resource resource) { + return permissionFilter(Arrays.asList(resource)).get(0); + } + /** * Retrieve a {@code Resource} by its {@code path}. * @@ -72,12 +104,7 @@ public class ResourceRepository extends AbstractAuditedEntityRepository result = query.getResultList(); - - //Check if the result list is empty and if not return the first - //element. If their is a result than there can only be one because - //the path column of resource has a unique constraint. - return result.isEmpty() ? null : result.get(0); + return permissionFilter(query.getSingleResult()); } /** @@ -93,7 +120,7 @@ public class ResourceRepository extends AbstractAuditedEntityRepository