head	1.44;
access;
symbols
	TIGRIS_1_1_0RC2:1.12.2.1.4.6.2.1
	TIGRIS_1_1_0RC1:1.12.2.1.4.6
	TIGRIS_1_1:1.12.2.1.4.6.0.2
	TIGRIS_1_0_8:1.12.2.1.4.6
	TIGRIS_1_0_8RC3:1.12.2.1.4.6
	TIGRIS_1_0_8RC2:1.12.2.1.4.6
	TIGRIS_1_0_8RC1:1.12.2.1.4.6
	TIGRIS_1_0_7:1.12.2.1.4.6
	TIGRIS_1_0_7RC3:1.12.2.1.4.6
	TIGRIS_1_0_7RC2:1.12.2.1.4.6
	TIGRIS_1_0_7RC1:1.12.2.1.4.6
	TIGRIS_1_0_6:1.12.2.1.4.6
	TIGRIS_1_0_6RC5:1.12.2.1.4.6
	TIGRIS_1_0_6RC4:1.12.2.1.4.6
	TIGRIS_1_0_6RC3:1.12.2.1.4.6
	TIGRIS_1_0_6RC2:1.12.2.1.4.6
	TIGRIS_1_0_6RC1:1.12.2.1.4.6
	TIGRIS_1_0_5:1.12.2.1.4.5
	TIGRIS_1_0_5RC6:1.12.2.1.4.5
	TIGRIS_1_0_5RC5:1.12.2.1.4.5
	TIGRIS_1_0_5RC4:1.12.2.1.4.5
	TIGRIS_1_0_5RC3:1.12.2.1.4.5
	TIGRIS_1_0_5RC2:1.12.2.1.4.5
	TIGRIS_1_0_5RC1:1.12.2.1.4.5
	TIGRIS_1_0_4:1.12.2.1.4.5
	TIGRIS_1_0_3:1.12.2.1.4.5
	TIGRIS_1_0_2:1.12.2.1.4.5
	TIGRIS_1_0_1:1.12.2.1.4.1
	TIGRIS_1_0:1.12.2.1.0.4
	TIGRIS_1_0_0:1.12.2.1
	TIGRIS_1_0_0_RC1:1.12.0.2
	dlr:1.1.1
	HELM_PEER_PORT_BRANCH:1.1.1.1;
locks; strict;
comment	@# @;


1.44
date	2001.07.16.02.23.42;	author jrobbins;	state dead;
branches;
next	1.43;

1.43
date	2001.06.13.21.58.06;	author elicia;	state Exp;
branches;
next	1.42;

1.42
date	2001.06.13.19.10.47;	author elicia;	state Exp;
branches;
next	1.41;

1.41
date	2001.06.12.23.10.43;	author leonardr;	state Exp;
branches;
next	1.40;

1.40
date	2001.06.07.22.06.24;	author elicia;	state Exp;
branches;
next	1.39;

1.39
date	2001.06.07.01.04.28;	author dlr;	state Exp;
branches;
next	1.38;

1.38
date	2001.06.06.23.57.08;	author dlr;	state Exp;
branches;
next	1.37;

1.37
date	2001.06.06.00.19.28;	author elicia;	state Exp;
branches;
next	1.36;

1.36
date	2001.06.05.01.47.48;	author elicia;	state Exp;
branches;
next	1.35;

1.35
date	2001.06.01.00.32.53;	author elicia;	state Exp;
branches;
next	1.34;

1.34
date	2001.05.31.21.14.25;	author elicia;	state Exp;
branches;
next	1.33;

1.33
date	2001.05.31.19.12.27;	author elicia;	state Exp;
branches;
next	1.32;

1.32
date	2001.05.25.16.57.15;	author leonardr;	state Exp;
branches;
next	1.31;

1.31
date	2001.05.23.01.50.13;	author dlr;	state Exp;
branches;
next	1.30;

1.30
date	2001.05.18.02.05.32;	author dlr;	state Exp;
branches;
next	1.29;

1.29
date	2001.05.18.02.02.34;	author dlr;	state Exp;
branches;
next	1.28;

1.28
date	2001.05.18.01.56.49;	author dlr;	state Exp;
branches;
next	1.27;

1.27
date	2001.05.18.01.56.38;	author dlr;	state Exp;
branches;
next	1.26;

1.26
date	2001.05.18.01.56.16;	author dlr;	state Exp;
branches;
next	1.25;

1.25
date	2001.04.25.01.08.29;	author dlr;	state Exp;
branches;
next	1.24;

1.24
date	2001.04.24.19.52.08;	author dlr;	state Exp;
branches;
next	1.23;

1.23
date	2001.04.24.18.11.10;	author dlr;	state Exp;
branches;
next	1.22;

1.22
date	2001.04.24.17.53.36;	author dlr;	state Exp;
branches;
next	1.21;

1.21
date	2001.04.24.15.34.05;	author dlr;	state Exp;
branches;
next	1.20;

1.20
date	2001.04.24.10.33.27;	author ms;	state Exp;
branches;
next	1.19;

1.19
date	2001.04.24.03.57.43;	author dlr;	state Exp;
branches;
next	1.18;

1.18
date	2001.04.24.00.57.54;	author dlr;	state Exp;
branches;
next	1.17;

1.17
date	2001.04.20.23.09.40;	author dlr;	state Exp;
branches;
next	1.16;

1.16
date	2001.04.19.23.43.26;	author elicia;	state Exp;
branches;
next	1.15;

1.15
date	2001.04.19.01.38.53;	author dlr;	state Exp;
branches;
next	1.14;

1.14
date	2001.04.14.03.07.25;	author elicia;	state Exp;
branches;
next	1.13;

1.13
date	2001.03.28.19.10.44;	author dlr;	state Exp;
branches;
next	1.12;

1.12
date	2001.03.08.03.51.51;	author dlr;	state Exp;
branches
	1.12.2.1;
next	1.11;

1.11
date	2001.03.08.03.30.42;	author dlr;	state Exp;
branches;
next	1.10;

1.10
date	2001.03.07.01.53.22;	author lucas;	state Exp;
branches;
next	1.9;

1.9
date	2001.02.27.23.16.25;	author elicia;	state Exp;
branches;
next	1.8;

1.8
date	2001.02.27.02.17.56;	author elicia;	state Exp;
branches;
next	1.7;

1.7
date	2001.02.26.20.21.18;	author dlr;	state Exp;
branches;
next	1.6;

1.6
date	2001.02.24.11.43.01;	author dlr;	state Exp;
branches;
next	1.5;

1.5
date	2001.02.24.03.59.53;	author dlr;	state Exp;
branches;
next	1.4;

1.4
date	2001.02.22.01.25.44;	author dlr;	state Exp;
branches;
next	1.3;

1.3
date	2001.02.22.00.38.46;	author dlr;	state Exp;
branches;
next	1.2;

1.2
date	2001.02.21.03.02.22;	author edk;	state Exp;
branches;
next	1.1;

1.1
date	2001.01.28.01.18.22;	author dlr;	state dead;
branches
	1.1.1.1
	1.1.2.1;
next	;

1.1.1.1
date	2001.02.21.00.32.58;	author dlr;	state Exp;
branches;
next	;

1.1.2.1
date	2001.01.28.01.18.22;	author dlr;	state Exp;
branches;
next	1.1.2.2;

1.1.2.2
date	2001.02.13.19.12.50;	author elicia;	state Exp;
branches;
next	1.1.2.3;

1.1.2.3
date	2001.02.13.20.23.04;	author dlr;	state Exp;
branches;
next	1.1.2.4;

1.1.2.4
date	2001.02.13.22.45.20;	author elicia;	state Exp;
branches;
next	1.1.2.5;

1.1.2.5
date	2001.02.16.03.01.27;	author dlr;	state Exp;
branches;
next	1.1.2.6;

1.1.2.6
date	2001.02.16.20.02.06;	author elicia;	state Exp;
branches;
next	1.1.2.7;

1.1.2.7
date	2001.02.16.20.28.19;	author dlr;	state Exp;
branches;
next	1.1.2.8;

1.1.2.8
date	2001.02.17.00.21.29;	author elicia;	state Exp;
branches;
next	1.1.2.9;

1.1.2.9
date	2001.02.17.20.32.42;	author elicia;	state Exp;
branches;
next	1.1.2.10;

1.1.2.10
date	2001.02.18.00.52.29;	author elicia;	state Exp;
branches;
next	1.1.2.11;

1.1.2.11
date	2001.02.20.00.24.36;	author dlr;	state Exp;
branches;
next	1.1.2.12;

1.1.2.12
date	2001.02.20.00.32.06;	author dlr;	state Exp;
branches;
next	1.1.2.13;

1.1.2.13
date	2001.02.20.02.06.10;	author dlr;	state Exp;
branches;
next	1.1.2.14;

1.1.2.14
date	2001.02.20.02.16.11;	author dlr;	state Exp;
branches;
next	1.1.2.15;

1.1.2.15
date	2001.02.20.04.53.54;	author elicia;	state Exp;
branches;
next	;

1.12.2.1
date	2001.03.28.23.30.11;	author dlr;	state Exp;
branches
	1.12.2.1.4.1;
next	;

1.12.2.1.4.1
date	2001.04.17.10.40.25;	author jrobbins;	state Exp;
branches;
next	1.12.2.1.4.2;

1.12.2.1.4.2
date	2001.04.20.21.46.29;	author edk;	state Exp;
branches;
next	1.12.2.1.4.3;

1.12.2.1.4.3
date	2001.04.23.19.46.33;	author jrobbins;	state Exp;
branches;
next	1.12.2.1.4.4;

1.12.2.1.4.4
date	2001.04.24.20.31.22;	author dlr;	state Exp;
branches;
next	1.12.2.1.4.5;

1.12.2.1.4.5
date	2001.04.25.01.08.36;	author dlr;	state Exp;
branches;
next	1.12.2.1.4.6;

1.12.2.1.4.6
date	2001.06.07.02.31.36;	author edk;	state Exp;
branches
	1.12.2.1.4.6.2.1;
next	;

1.12.2.1.4.6.2.1
date	2001.08.07.20.36.45;	author edk;	state Exp;
branches;
next	;


desc
@@


1.44
log
@factoring project documents out to project nidaba.tigris.org
@
text
@package org.tigris.helm.om;

import java.io.*;
import java.util.*;
import java.security.MessageDigest;

import org.apache.turbine.om.*;
import org.apache.turbine.om.peer.BasePeer;
import org.apache.turbine.util.db.Criteria;
import org.apache.turbine.util.ObjectUtils;
import org.apache.turbine.util.StringUtils;
import org.apache.turbine.util.ParameterParser;
import org.apache.turbine.util.Log;
import org.apache.turbine.util.TurbineException;
import org.apache.turbine.util.TurbineException;
import org.apache.turbine.util.db.pool.DBConnection;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.services.velocity.TurbineVelocity;

import com.oreilly.servlet.multipart.FilePart;
import org.apache.velocity.context.Context;

import org.joist.util.URL;

import org.tigris.helm.*;
import org.tigris.helm.om.*;
import org.tigris.helm.security.*;
import org.tigris.helm.tool.DBFlag;
import org.tigris.helm.tool.FileArtifactTool;
import org.tigris.helm.tool.HelmEmailer;
import org.tigris.helm.tool.TemplateTool;
import org.tigris.helm.tool.HtAccess;
import org.tigris.helm.tool.FormatDate;

/** 
 * Project document business object.
 *
 * @@author <a href="mailto:elicia@@collab.net">Elicia David</a>
 * @@version $Id: ProjectDocument.java,v 1.43 2001/06/13 21:58:06 elicia Exp $
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 */
public class ProjectDocument extends BaseProjectDocument
    implements ProposableFileArtifact, ViewableBy
{
    /**
     * The buffer size used when computing the MD5 checksum of a file.
     */
    private static final int MD5_BUF_SIZE = 4096;

    /**
     * The document approval permission.
     */
    private static final String APPROVE_PERM = "Project Document - Approve";

    /**
     * The primary key of the document.
     */
    private static final String DOCUMENT_ID = "document_id"; 

    /**
     * The primary key of the section in the document-section join table.
     */
    private static final String SECTION_ID = "section_id"; 

    /**
     * The name of the template used to create the body of the document 
     * creation announcement email.
     */
    private static final String CREATED_TMPL =
        TemplateTool.getPathToMessageTemplate("ProjectCreated.vm");

    /**
     * The name of the template used to create the body of the document 
     * disapproval email.
     */
    private static final String DISAPPROVE_TMPL =
        TemplateTool.getPathToMessageTemplate("ProjectDocumentDisapprove.vm");

    /**
     * Determines whether a document has been approved
     */
    public boolean isApproved()
        throws Exception
    {
        return !getApprovedBy().equals(UserPeer.getNobodyUser().getUserId());
    }

    /**
     * Checks whether a publicly accessible document.
     *
     * @@return Whether public document.
     */
    public boolean isPublic()
    {
        return DBFlag.booleanValueOf(getIsPublic());
    }

    /**
     * Gets user that proposed the document.
     */
    public final User getProposedByUser()
        throws Exception
    {
        return getUserRelatedByProposedBy();
    }

    /**
     * Gets user that modified the document.
     */
    public final User getModifiedByUser()
        throws Exception
    {
        return getUserRelatedByModifiedBy();
    }

    /**
     * Gets created date in short format, as a string.
     */
    public final String getCreatedDateString()
        throws Exception
    {
        return FormatDate.format("yyyy-MM-dd hh:mm:ss.S", 
                                 "MMM d, yyyy", 
                                 getCreatedDate().toString());
    }


    /**
     * Gets modified date in short format, as a string.
     */
    public final String getModifiedDateString()
        throws Exception
    {
        return FormatDate.format("yyyy-MM-dd hh:mm:ss.S", 
                                 "MMM d, yyyy", 
                                 getModifiedDate().toString());
    }

    /**
     * Returns the link to the file.
     */
    public String getDownloadLink (Project project) 
    {
        String link = null;
        StringBuffer argBuffer = null;
        String arg = null;

        argBuffer = new StringBuffer("dcID=");
        argBuffer.append(getID()).append("&action=download");
        arg = argBuffer.toString();
        link = project.getProjectPageURL("ProjectDocumentList", 
                                          arg);
        return link;
     }
          

    // 
    // Database methods
    //

    /**
     * Returns the sectionID this document is filed under.
     * If document is top-level, sectionID=0
     */
    public int getSectionID()
        throws Exception
    {        
        List sectionIDs = null;
        int sectionID = 0;
        Criteria c = new Criteria()
            .add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID());
        sectionIDs =  ProjectDocumentSectionPeer.doSelect(c);
        if (!sectionIDs.isEmpty())
        { 
            ProjectDocumentSection sec = 
               (ProjectDocumentSection)sectionIDs.get(0);
            sectionID = Integer.parseInt(sec.getSectionId().toString());
        }
        return sectionID;
    }

    /**
     * Adds a new document.
     *
     * @@param acl The ACL to check for permission.
     */
    public static ProjectDocument add(AccessControlList acl, 
                                      Project project, String name,
                                      String status, String descrip,                                             String sectionID)
        throws ACLException, Exception, InterruptedException, IOException
    {
        ProjectDocument dc = new ProjectDocument();
        dc.setProjectId(project.getProjectId());
        //dc.assertAddPermission(acl);

        dc.setName(name);
        dc.setStatus(status);
        dc.setDescription(descrip);
        User proposedBy = acl.getUser();
        dc.setUserRelatedByProposedBy(proposedBy);
        User approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                           proposedBy : 
                           UserPeer.getNobodyUser());
        dc.setUserRelatedByApprovedBy(approvedBy);

        dc.setCreatedDate(new Date());
        dc.setModifiedDate(new Date());
        dc.save();

        // Add to document-section join table
        if (sectionID != null) dc.addToSection(sectionID);

        return dc;
    }



    /**
     * Adds a new document.
     *
     * @@param acl The ACL to check for permission.
     */
    public static ProjectDocument add(AccessControlList acl, 
                                      Project project, String name,
                                      String status, String descrip, 
                                      String url, String text, 
                                      String sectionID, String isPublic)
        throws ACLException, Exception, InterruptedException, IOException
    {
        ProjectDocument dc = new ProjectDocument();
        dc.setProjectId(project.getProjectId());
        //dc.assertAddPermission(acl);

        dc.setName(name);
        dc.setStatus(status);
        dc.setDescription(descrip);
        dc.setUrl(url);
        dc.setText(text);
        User proposedBy = acl.getUser();
        dc.setUserRelatedByProposedBy(proposedBy);
        dc.setUserRelatedByModifiedBy(proposedBy);
        User approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                           proposedBy : 
                           UserPeer.getNobodyUser());
        dc.setUserRelatedByApprovedBy(approvedBy);
        dc.setCreatedDate(new Date());
        dc.setModifiedDate(new Date());
        dc.setIsPublic(DBFlag.flagValueOf(isPublic));
        dc.save();

        // Add to document-section join table
        if (sectionID != null) dc.addToSection(sectionID);

        return dc;
    }

    /**
     * Associates document with a section.
     * Adds record to HELM_DOCUMENT_SECTION join table.
    */
    private void addToSection(String sectionID)
        throws Exception
    {
        // If document is already associated with a section, delete record
        this.deleteFromSection();

        ProjectDocumentSection mapping = new ProjectDocumentSection();
        mapping.setDocumentId(this.getDocumentId());
        mapping.setSectionId(new NumberKey(sectionID));
        mapping.save();
    }

    /**
     * Removes associates between document and section.
     * Deletes record in document-section join table.
    */
    private void deleteFromSection()
        throws Exception
    {
       Criteria c = new Criteria().
           add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID());
       ProjectDocumentSectionPeer.doDelete(c);
    }

    /**
     * Moves a document to top level (removes association with section)
     * Deletes record in document-section join table
     * And adds a record with sectionId = 0
    */
    public void moveToTop()
        throws Exception
    {
        deleteFromSection();
        addToSection("0");
    }

    /**
     * Updates a document.
     *
     * @@param acl           The access control list of the current user.
     * @@exception ACLException
     */
    public void edit(AccessControlList acl, String name, String status,
                     String description, String url, String text, 
                     String sectionID, File f, String isPublic, String htURL)
        throws ACLException, Exception
    {
        assertEditPermission(acl);

        if (name != null) setName(name);
        if (status != null) setStatus(status);
        if (description != null) setDescription(description);
        if (sectionID != null) addToSection(sectionID);
        if (url != null) setUrl(url);
        if (text != null) setText(text);
        setIsPublic(DBFlag.flagValueOf(isPublic));

        if ((new Date()).compareTo(getCreatedDate()) != 0)
        {
            setModifiedDate(new Date());
            User modifiedBy = acl.getUser();
            setUserRelatedByModifiedBy(modifiedBy);
        }

        if (f != null && f.exists())
        {
            FileArtifactTool.fillInAttributes(this, f);
            save();
            // write .htaccess file that controls access to uploaded files
            Project p = getProject();
            HtAccess.writeHtaccessFile(HtAccess.getHtaccess(this),
                                htURL, p.getDocuments(), p.getID());
        }
        save();
    }

    /**
     * Approves the document in the name of the approving user..
     *
     * @@param acl The ACL of the user approving the document.
     *
     * @@exception ACLException The ACL does not have approval permission.
     * @@exception DoesNotExist If the specified project is invalid.
     * @@exception Exception    If a database error occurs.
     */
    public void approve(AccessControlList acl)
        throws ACLException, DoesNotExist, Exception
    {
        if (acl != null)
        {
            acl.assertPermission(APPROVE_PERM, getProject());

            setApprovedBy(acl.getUser().getUserId());
            save();
        }
    }

    /**
     * Deletes an unapproved document, sending email to the owners
     * about it.
     *
     * @@param acl   The ACL to check for permission.
     * @@param htURL The URL for auth and timeout.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void disapprove(AccessControlList acl, String htURL,
                           String rationale)
        throws ACLException, DoesNotExist, Exception
    {

        acl.assertPermission(APPROVE_PERM, getProject());

        String subject = "Download for Project " + getProject().getName() +
            " disapproved.";
        Context ctx = TurbineVelocity.getContext();
        ctx.put("disapprovingUser", acl.getUser());
        ctx.put("document", this);
        ctx.put("rationale", rationale);
        String body = TurbineVelocity.handleRequest(ctx, DISAPPROVE_TMPL);
        HelmEmailer emailer = new HelmEmailer();
        emailer.sendEmail(getProposedByUser().getEmail(), subject, body);

        delete(acl, true, htURL);
    }
    
    /**
     * Deletes this document.
     *
     * @@param acl            The ACL to check for permission.
     * @@param fromFilesystem Whether to delete from the file system as well.
     * @@param htURL          The URL for auth and timeout.
     */
    public void delete(AccessControlList acl, boolean fromFilesystem,
                       String htURL)
        throws Exception
    {
        assertDeletableBy(acl);
        if (fromFilesystem)
            deleteFromFilesystem(acl, htURL);
        delete();
        deleteFromSection();
    }

    /**
     * Deletes the document attachment from the filesystem.
     */ 
    public void deleteFromFilesystem(AccessControlList acl, String htURL)
        throws Exception
    {
        File victim =
            new File(getLocation() + File.separatorChar + getFileName());
        if (victim.exists())
        {
            victim.delete();
            Project p = getProject();
            HtAccess.writeHtaccessFile(HtAccess.getHtaccess(this),
                                htURL, p.getDocuments(), 
                                getProject().getID());
        }
    }

    /**
     * Asserts that this file is deletable by the user associated with the
     * specified ACL.  First checks whether the user proposed the download,
     * then check the usual permission assertion.
     */
    private final void assertDeletableBy(AccessControlList acl)
        throws ACLException, Exception
    {
        if (!getUserRelatedByProposedBy().equals(acl.getUser()))
        {
            acl.assertPermission("Project Document - Delete", getProject());
        }
    }

    private void delete()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDocumentPeer.DOCUMENT_ID, getDocumentId());
        ProjectDocumentPeer.doDelete(c);
    }


    //
    // Permission methods
    //

    /**
     * Asserts addition and/or approval permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public final void assertAddPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        acl.assertPermission("Project Document - Suggest", getProject());
    }

    /**
     * Asserts edit permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public final void assertEditPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        assertPermission(acl, "Project Document - Edit");
    }

    /**
     * Asserts deletion and/or disapproval permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public final void assertDeletePermission(AccessControlList acl)
        throws ACLException, Exception
    {
        assertPermission(acl, "Project Document - Delete");
    }

    /**
     * Asserts generic permission for this document.
     *
     * @@param acl The ACL to check for permission.
     * @@param nonProposerPerm The permission to check for user ACLs other
     *                        than that of the proposing user.
     */
    private void assertPermission(AccessControlList acl,
                                  String nonProposerPerm)
        throws ACLException, Exception
    {
        if (getProposedBy().equals(acl.getUser().getUserId()))
        {
            acl.assertPermission("Project Document - View", getProject());
        }
        else
        {
            acl.assertPermission(nonProposerPerm, getProject());
        }
    }

    /**
     * Returns true if the given ACL can see this document.
     */
    public boolean isViewableBy(AccessControlList acl)
        throws Exception
    {
        return (acl.hasPermission(requiredViewPermission(acl), getProject()));
    }

    /**
     * Returns the appropriate permission needed 
     */
    public String requiredViewPermission(AccessControlList acl)
        throws Exception
    {
        String permission;
        if (!isApproved() &&
            !getProposedBy().equals(acl.getUser().getUserId()))
        {
            permission = "Project Document - Approve";
        }
        else
        {
            permission = (isPublic() ?
                          "Project Document - View" :
                          "Private Project Document - View");
        }
        return permission;
    }

    /**
     * Returns a string describing the type of this file artifact.
     */
    public final String getFileArtifactType()
    {
        return "Document";
    }

    /**
     * Gets the directory to save uploads to.
     *
     * @@param baseDir The base directory to build the upload directory off of.
     * @@param user    The user to save a file for.
     * @@return        The directory to save uploads to.
     */
    public String getUploadDirectory(String baseDir)
    {
        // Save to /pub-fileserver/documentID//fileNameAsUploaded.
        return (baseDir + File.separatorChar + getID());
    }

    /**
     * Returns the type of the attached file, based on filename extension.
     * Files are grouped by MIME types to associate an icon with them.
     *
     * @@param f The file to extract path information from.
     * @@return  The file type category.
     */
    public String getIconType()
    {
        String fileName = this.getFileName();
        String type = "other";
        if (fileName.lastIndexOf(".") > -1)
        {
            String extension = fileName.substring(fileName.lastIndexOf("."));
            if (extension.equals(".html") || extension.equals(".htm") 
                || extension.equals(".xml") )
            {
                type = "html";
            } else if (extension.equals(".txt") || extension.equals(".doc")) {
                type="txt";
            } else if (extension.equals(".gif") ||  extension.equals(".jpg")
                 ||  extension.equals(".jpe") ||  extension.equals(".jpeg")) {
                type="image";
            } else if (extension.equals(".pdf")) {
                 type="pdf";
            } else if (extension.equals(".zip")) {
                 type="zip";
            }
        }

        return type;
    }
}
@


1.43
log
@removed cruft
@
text
@d39 1
a39 1
 * @@version $Id: ProjectDocument.java,v 1.42 2001/06/13 19:10:47 elicia Exp $
@


1.42
log
@calling htaccess methods from the tool utility class instead of on Project om.
@
text
@d39 1
a39 1
 * @@version $Id: ProjectDocument.java,v 1.41 2001/06/12 23:10:43 leonardr Exp $
a416 2
            List artifacts = FileArtifactTool.artifactsProposedBy
                (acl.getUser(), p.getProjectDownloads());
@


1.41
log
@PeerBackedList performance boost and refactoring. This may be more complicated than it needs to be; rather than getting ever-increasing proportions of the table, it might be faster in most cases to get the whole table, so long as you stop processing results when the list is full enough.
@
text
@d32 1
d39 1
a39 1
 * @@version $Id: ProjectDocument.java,v 1.40 2001/06/07 22:06:24 elicia Exp $
d189 1
a189 1
                                      String status, String descrip,                                                 String sectionID)
d331 2
a332 2
            p.writeHtaccessFile(p.getHtaccess(this),
                                htURL, p.getDocuments());
d419 3
a421 2
            p.writeHtaccessFile(p.getHtaccess(this),
                                htURL, p.getDocuments());
@


1.40
log
@changed getMimeType() to getIconType() for clarity.
@
text
@d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.39 2001/06/07 01:04:28 dlr Exp $
d42 1
a42 1
    implements ProposableFileArtifact
@


1.39
log
@Corrected equality test for objects (thanks edk!).
@
text
@d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.38 2001/06/06 23:57:08 dlr Exp $
d556 2
a557 1
     * Returns MIME type of attached file, based on filename extension.
d560 1
a560 1
     * @@return  The extracted path information.
d562 1
a562 1
    public String getMimeType()
@


1.38
log
@Added support for private project documents so that the anonymous user
can be prevented from being handed a mod_auth_mda MDAAuth cookie for a
private document.
@
text
@d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.37 2001/06/06 00:19:28 elicia Exp $
d520 2
a521 1
        if (!isApproved() && getProposedBy() != acl.getUser().getUserId())
@


1.37
log
@checking for null conditions in getSectionID() and getMimeType()
@
text
@d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.36 2001/06/05 01:47:48 elicia Exp $
d519 2
a520 2
        String permission = "Project Document - View";
        if ((!isApproved()) && (getProposedBy() != acl.getUser().getUserId()))
d523 6
@


1.36
log
@added getmimeType method
@
text
@d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.35 2001/06/01 00:32:53 elicia Exp $
d172 6
a177 2
        ProjectDocumentSection sec = (ProjectDocumentSection)sectionIDs.get(0);
        sectionID = Integer.parseInt(sec.getSectionId().toString());
a556 1
        String extension = fileName.substring(fileName.lastIndexOf("."));
d558 1
a558 2
        if (extension.equals("html") || extension.equals("htm") 
            || extension.equals("xml") )
d560 15
a574 10
            type = "html";
        } else if (extension.equals(".txt") || extension.equals(".doc")) {
            type="txt";
        } else if (extension.equals(".gif") ||  extension.equals(".jpg")
             ||  extension.equals(".jpe") ||  extension.equals(".jpeg")) {
            type="image";
        } else if (extension.equals(".pdf")) {
             type="pdf";
        } else if (extension.equals(".zip")) {
             type="zip";
@


1.35
log
@added methods to return the date fields in shortened, String form
@
text
@d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.34 2001/05/31 21:14:25 elicia Exp $
d542 29
@


1.34
log
@added htURL argument to deleteFromFilesystem method
@
text
@d32 1
d38 1
a38 1
 * @@version $Id: ProjectDocument.java,v 1.33 2001/05/31 19:12:27 elicia Exp $
d116 23
d200 1
d202 1
@


1.33
log
@Many changes to the Project Documents component.  It is now replacing ProjectDownloads (will remove it from cvs after a while). Took out the "type" variable so that a Document can have a file upload attachment and/or a remote URL and/or pasted text, instead of only one of the three. Added fields for modified by and modified date. Also added isPublic field for file uploads, and a status field.

Document file uploads are now being saved in helm/data/fileserv/documents/[document_id]. Refactored htAccess file code to reflect that and to fix other bugs.
Dropped $type parameter from URL arguments."

UI has changed: ProjectDocumentList now has a 2-pane UI with a folder tree on the left pane and the document list on the right.  When in the list you have a "root folder" that is the root of the tree.  Folders can now be infinitely nested instead of just two levels deep.  You add a document or subfolder directly to the root section.
@
text
@d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.32 2001/05/25 16:57:15 leonardr Exp $
d369 1
a369 1
            deleteFromFilesystem(acl);
d377 1
a377 1
    public void deleteFromFilesystem(AccessControlList acl)
@


1.32
log
@.wm is now .vm
@
text
@d20 1
d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.31 2001/05/23 01:50:13 dlr Exp $
d106 9
d117 1
a117 1
    public String getLink (Project project) 
a121 1
        String type = getType();
d123 5
a127 21
        if (type.equals("url"))
        {
           link = getUrl();
        } 
        else if (type.equals("text"))
        {
           argBuffer = new StringBuffer("documentID=");
           argBuffer.append(getID());
           arg = argBuffer.toString();
           link = project.getProjectPageURL("ProjectDocumentView", 
                                            arg);
        }
        else
        {
           argBuffer = new StringBuffer("dcID=");
           argBuffer.append(getID()).append("&action=download");
           arg = argBuffer.toString();
           link = project.getProjectPageURL("ProjectDocumentList", 
                                                   arg);
        }
   
d158 37
a194 3
    public static ProjectDocument add(AccessControlList acl, Project project,
                                      String name, String descrip, 
                                      String type, File f, 
d196 2
a197 2
                                      String sectionID, String htURL)
        throws ACLException, Exception
d201 1
a201 1
        dc.assertAddPermission(acl);
d204 1
a205 1
        dc.setType(type);
d210 1
d215 4
a218 6
        dc.setIsPublic(DBFlag.flagValueOf("N"));
        if (f != null)
        {
            dc.setUploadedDate(new Date());
            FileArtifactTool.fillInAttributes(dc, f);
        }
a219 1
        dc.save();
a222 9
        // write .htaccess file that controls access to uploaded files
        if (f != null && f.exists())
        {
            List artifacts = FileArtifactTool.artifactsProposedBy
                (proposedBy, project.getProjectDownloads());
            project.writeHtaccessFile(Project.getHtaccess(dc), htURL,
                                      artifacts);
        }

d272 3
a274 3
    public void edit(AccessControlList acl, String name, String description,
                     String type, String url, String text, String sectionID,
                     File f)
d280 1
a281 1
        if (type != null) setType(type);
d285 3
a287 1
        if (f != null)
d289 3
a291 2
           FileArtifactTool.fillInAttributes(this, f);
           setUploadedDate(new Date());
d294 9
d369 1
a369 13
        {
            File victim =
                new File(getLocation() + File.separatorChar + getFileName());
            if (victim.exists())
            {
                victim.delete();
                Project p = getProject();
                List artifacts = FileArtifactTool.artifactsProposedBy
                    (acl.getUser(), p.getProjectDownloads());
                p.writeHtaccessFile(Project.getHtaccess(this), htURL,
                                    artifacts);
            }
        }
d374 18
d503 13
@


1.31
log
@Ported Helm from WebMacro to Velocity.
@
text
@d36 1
a36 1
 * @@version $Id: ProjectDocument.java,v 1.30 2001/05/18 02:05:32 dlr Exp $
d67 1
a67 1
        TemplateTool.getPathToMessageTemplate("ProjectCreated.wm");
d74 1
a74 1
        TemplateTool.getPathToMessageTemplate("ProjectDocumentDisapprove.wm");
@


1.30
log
@Re-added necessary import of HelmEmailer.
@
text
@d14 2
d18 1
a18 1
import org.apache.turbine.services.webmacro.TurbineWebMacro;
d20 1
a20 1
import org.webmacro.servlet.WebContext;
d36 1
a36 1
 * @@version $Id: ProjectDocument.java,v 1.29 2001/05/18 02:02:34 dlr Exp $
d317 1
a317 1
        WebContext ctx = TurbineWebMacro.getContext();
d321 1
a321 1
        String body = TurbineWebMacro.handleRequest(ctx, DISAPPROVE_TMPL);
@


1.29
log
@.htaccess file are now be written to <project.id>/<user.id>/<file_name>.
@
text
@d27 1
d34 1
a34 1
 * @@version $Id: ProjectDocument.java,v 1.28 2001/05/18 01:56:49 dlr Exp $
@


1.28
log
@Removed duplicate WebContext import.
@
text
@d33 1
a33 1
 * @@version $Id: ProjectDocument.java,v 1.27 2001/05/18 01:56:38 dlr Exp $
d200 2
a201 2
            project.writeHtaccessFile(Project.getHtaccess(dc.getLocation()),
                                      htURL, artifacts);
d347 2
a348 2
                p.writeHtaccessFile(Project.getHtaccess(getLocation()),
                                    htURL, artifacts);
@


1.27
log
@Removed duplicate tool and om imports.
@
text
@a18 1
import org.webmacro.servlet.WebContext;
d33 1
a33 1
 * @@version $Id: ProjectDocument.java,v 1.26 2001/05/18 01:56:16 dlr Exp $
@


1.26
log
@.htaccess file should now only contain entries for a single user
(written to <project.id>/<user.id>/<file_name>).
@
text
@a25 2
import org.tigris.helm.tool.*;
import org.tigris.helm.om.*;
d34 1
a34 1
 * @@version $Id: ProjectDocument.java,v 1.25 2001/04/25 01:08:29 dlr Exp $
@


1.25
log
@Streamlined a couple permission checking routines.
@
text
@d29 1
d36 1
a36 1
 * @@version $Id: ProjectDocument.java,v 1.24 2001/04/24 19:52:08 dlr Exp $
d40 1
a40 1
    implements ProjectFileArtifact
d201 2
d204 1
a204 1
                                      htURL, project.getProjectDocuments());
d348 2
d351 1
a351 1
                                    htURL, p.getProjectDocuments());
@


1.24
log
@Implemented clean OO-style suggested by edk instead of my quick hack.
@
text
@d35 2
a36 1
 * @@version $Id: ProjectDocument.java,v 1.23 2001/04/24 18:11:10 dlr Exp $
d290 1
a290 1
                                          
d386 1
a386 1
    public void assertAddPermission(AccessControlList acl)
d397 1
a397 1
    public void assertEditPermission(AccessControlList acl)
d400 1
a400 8
        if (getProposedBy().equals(acl.getUser().getUserId()))
        {
            acl.assertPermission("Project Document - View", getProject());
        }
        else
        {
            acl.assertPermission("Project Document - Edit", getProject());
        }
d408 15
a422 1
    public void assertDeletePermission(AccessControlList acl)
d431 1
a431 1
            acl.assertPermission("Project Document - Delete", getProject());
@


1.23
log
@Ed and I incorrectly assumed that documents were getting written to the same place.  Since such is not the case, we can safely write .htaccess files consisting of just objects of a given file artifact type.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.22 2001/04/24 17:53:36 dlr Exp $
d450 7
@


1.22
log
@Modifed Project's writeHtaccessFile() instance method to take inputs (rather than decide what data to act on by itself).  Stil does the same dumb 'write both documents and downloads to the same directory tree' business.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.21 2001/04/24 15:34:05 dlr Exp $
a198 2
            List artifacts = project.getProjectDocuments();
            artifacts.addAll(project.getProjectDownloads());
d200 1
a200 1
                                      htURL, artifacts);
a343 2
                List artifacts = p.getProjectDocuments();
                artifacts.addAll(p.getProjectDownloads());
d345 1
a345 1
                                    htURL, artifacts);
@


1.21
log
@Removed unused htURL param from the signature of the edit() instance
method.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.20 2001/04/24 10:33:27 ms Exp $
d199 4
a202 2
            dc.getProject().writeHtaccessFile
                    (Project.getHtaccess(dc.getLocation()), htURL, "DOCUMENTS");
d345 5
a349 2
                getProject().writeHtaccessFile
                    (Project.getHtaccess(getLocation()), htURL, "DOCUMENTS");
@


1.20
log
@Be more intelligent about what data gets written to what .htaccess file.
The way it's distinguished betwen DOCUMENTS and DOWNLOADS is kind of stupid but
ignoring downloads for documents and vice versa is going to save much more time
then speeding up the distinguishing though.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.19 2001/04/24 03:57:43 dlr Exp $
d252 3
a254 4
    public void edit (AccessControlList acl, String name, 
                      String description, String type,
                      String url, String text, String sectionID,
                      File f, String htURL)
@


1.19
log
@* Cleaned up getSectionID().

* Made use of FileArtifactTool.fillInAttributes in add().  Also now
setting uploaded date.

* Minor brace placement reformatting.

* Removed uploadFile().  Deprecated by FileArtifactTool.fillInAttributes
class method.

* Made use of FileArtifactTool.fillInAttributes in edit().  Also now
setting uploaded date when a file is supplied.

* Removed extractLocation().  It lives in FileArtifactTool.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.18 2001/04/24 00:57:54 dlr Exp $
d199 2
a200 2
            dc.getProject().writeHtaccessFile(Project.getHtaccess
                                              (dc.getLocation()), htURL);
d345 1
a345 1
                    (Project.getHtaccess(getLocation()), htURL);
@


1.18
log
@Implemented ProjectFileArtifact.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.17 2001/04/20 23:09:40 dlr Exp $
d148 1
a148 1
        Vector sectionIDs = null;
d153 2
a154 2
        ProjectDocumentSection rec = (ProjectDocumentSection)sectionIDs.elementAt(0);
        sectionID = Integer.parseInt(rec.getSectionId().toString());
d186 4
a189 3

        if (f != null && f.exists()) {
            dc.uploadFile(f);
d197 2
a198 1
        if (f != null && f.exists()) {
a206 41
     * Handles file upload.
     * <p>
     * HELP: Elicia, please bring some clarity to my poor description.
     */
    private void uploadFile(File f)
        throws Exception
    {
        // Handle fields inferred from the File.
        setFileName(f.getName());
        setLocation(extractLocation(f));

        // Compute the file MD5 checksum and size.
        int size = -1;
        String md5Checksum = null;
        try {
            if (f.canRead()) {
                FileInputStream in = new FileInputStream(f);
                MessageDigest md5 = MessageDigest.getInstance
                    (CryptoProviderService.MD5,
                     CryptoProviderService.CRYPTIX_PROVIDER);
                byte[] buf = new byte[MD5_BUF_SIZE];
                int read = 0;
                while ((read = in.read(buf)) != -1)
                {
                    size += read;
                    md5.update(buf, 0, read);
                }
                in.close();
                md5Checksum = ByteToHex.transform(md5.digest());
                //dc.setMd5(md5Checksum);
                //if (size != -1) dc.setSize(size);
            }
        }
        catch (Exception e) {
            Log.error("Couldn't determine file MD5 checksum or " + 
                      "size: " + f.getAbsolutePath() + ": " +
                      e.getMessage());
        }
    }

    /**
d266 4
a269 2
        if (f != null && f.exists()) {
           uploadFile(f);
d287 2
a288 1
        if (acl != null) {
d337 2
a338 1
        if (fromFilesystem) {
d341 2
a342 1
            if (victim.exists()) {
a373 13


    /**
     * Extracts the directory path to the file.
     *
     * @@param f The file to extract path information from.
     * @@return  The extracted path information.
     */
    public static final String extractLocation(File f)
    {
        return f.getParentFile().getAbsolutePath();
    }

@


1.17
log
@Write .htaccess files per project instead of per user.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.16 2001/04/19 23:43:26 elicia Exp $
d38 1
@


1.16
log
@checking to make sure there is a file to upload before writing .htaccess file (in add method)
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.15 2001/04/19 01:38:53 dlr Exp $
d196 2
a197 1
            dc.getProject().writeHtaccessFile(dc.getLocation(), htURL);
d377 2
a378 1
                getProject().writeHtaccessFile(getLocation(), htURL);
@


1.15
log
@The proposing user should be able to delete their proposed file
whether they have 'Project Document - Delete' or not.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.14 2001/04/14 03:07:25 elicia Exp $
a190 2

        dc.getProject().writeHtaccessFile(dc.getLocation(), htURL);
d193 5
@


1.14
log
@changed add method so that saving the new record happens before the .htaccess file is written
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.13 2001/03/28 19:10:44 dlr Exp $
d367 1
a367 1
        acl.assertPermission("Project Document - Delete", getProject());
d378 15
@


1.13
log
@Added JavaDoc.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.12 2001/03/08 03:51:51 dlr Exp $
d187 1
a187 1
            dc.uploadFile(f, htURL);
d192 1
d204 1
a204 1
    private void uploadFile(File f, String htURL)
a230 1
                getProject().writeHtaccessFile(getLocation(), htURL);
d301 1
a301 1
           uploadFile(f, htURL);
@


1.12
log
@Use equals() instead of == for SimpleKey instances.  Memory address
comparisons no longer work since primary key change from int to
ObjectKey.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.11 2001/03/08 03:30:42 dlr Exp $
d331 2
a332 2
     * @@param acl The ACL to check for permission.
     * @@param htURL
d361 1
@


1.12.2.1
log
@Merged in bug fixes and clean up from HEAD.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.13 2001/03/28 19:10:44 dlr Exp $
d331 2
a332 2
     * @@param acl   The ACL to check for permission.
     * @@param htURL The URL for auth and timeout.
a360 1
     * @@param htURL          The URL for auth and timeout.
@


1.12.2.1.4.1
log
@buddied MDA .htaccess changes from head to branch
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.14 2001/04/14 03:07:25 elicia Exp $
d187 1
a187 1
            dc.uploadFile(f);
a191 1
        dc.getProject().writeHtaccessFile(dc.getLocation(), htURL);
d203 1
a203 1
    private void uploadFile(File f)
d230 1
d301 1
a301 1
           uploadFile(f);
@


1.12.2.1.4.2
log
@Port some of dlr's bug fixes back to the branch.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.12.2.1.4.1 2001/04/17 10:40:25 jrobbins Exp $
d367 1
a367 1
        assertDeletableBy(acl);
a377 15
    }


    /**
     * Asserts that this file is deletable by the user associated with the
     * specified ACL.  First checks whether the user proposed the download,
     * then check the usual permission assertion.
     */
    private final void assertDeletableBy(AccessControlList acl)
        throws ACLException, Exception
    {
        if (!getUserRelatedByProposedBy().equals(acl.getUser()))
        {
            acl.assertPermission("Project Document - Delete", getProject());
        }
@


1.12.2.1.4.3
log
@buddied elicias change from head to branch
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.16 2001/04/19 23:43:26 elicia Exp $
d191 2
a194 5

        // write .htaccess file that controls access to uploaded files
        if (f != null && f.exists()) {
            dc.getProject().writeHtaccessFile(dc.getLocation(), htURL);
        }
@


1.12.2.1.4.4
log
@Implemented ProjectFileArtifact interface and refactored to make use of tool.FileArtifactTool helper class.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.24 2001/04/24 19:52:08 dlr Exp $
a37 1
    implements ProjectFileArtifact
d147 1
a147 1
        List sectionIDs = null;
d152 2
a153 2
        ProjectDocumentSection sec = (ProjectDocumentSection)sectionIDs.get(0);
        sectionID = Integer.parseInt(sec.getSectionId().toString());
d185 3
a187 4
        if (f != null)
        {
            dc.setUploadedDate(new Date());
            FileArtifactTool.fillInAttributes(dc, f);
d195 2
a196 4
        if (f != null && f.exists())
        {
            project.writeHtaccessFile(Project.getHtaccess(dc.getLocation()),
                                      htURL, project.getProjectDocuments());
d203 41
d289 4
a292 3
    public void edit(AccessControlList acl, String name, String description,
                     String type, String url, String text, String sectionID,
                     File f)
d303 2
a304 4
        if (f != null)
        {
           FileArtifactTool.fillInAttributes(this, f);
           setUploadedDate(new Date());
d322 1
a322 2
        if (acl != null)
        {
d371 1
a371 2
        if (fromFilesystem)
        {
d374 1
a374 2
            if (victim.exists())
            {
d376 1
a376 3
                Project p = getProject();
                p.writeHtaccessFile(Project.getHtaccess(getLocation()),
                                    htURL, p.getProjectDocuments());
d407 13
a493 7
    /**
     * Returns a string describing the type of this file artifact.
     */
    public final String getFileArtifactType()
    {
        return "Document";
    }
@


1.12.2.1.4.5
log
@Streamlined a couple permission checking routines.
@
text
@d35 1
a35 2
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 * @@version $Id: ProjectDocument.java,v 1.12.2.1.4.4 2001/04/24 20:31:22 dlr Exp $
d289 1
a289 1

d385 1
a385 1
    public final void assertAddPermission(AccessControlList acl)
d396 1
a396 1
    public final void assertEditPermission(AccessControlList acl)
d399 8
a406 1
        assertPermission(acl, "Project Document - Edit");
d414 1
a414 15
    public final void assertDeletePermission(AccessControlList acl)
        throws ACLException, Exception
    {
        assertPermission(acl, "Project Document - Delete");
    }

    /**
     * Asserts generic permission for this document.
     *
     * @@param acl The ACL to check for permission.
     * @@param nonProposerPerm The permission to check for user ACLs other
     *                        than that of the proposing user.
     */
    private void assertPermission(AccessControlList acl,
                                  String nonProposerPerm)
d423 1
a423 1
            acl.assertPermission(nonProposerPerm, getProject());
@


1.12.2.1.4.6
log
@port dlr's changes to support private documents and sections
@
text
@d36 1
a36 1
 * @@version $Id: ProjectDocument.java,v 1.12.2.1.4.5 2001/04/25 01:08:36 dlr Exp $
d450 2
a451 3
        String permission;
        if (!isApproved() &&
                !getProposedBy().equals(acl.getUser().getUserId()))
a453 6
        }
        else
        {
            permission = (isPublic() ?
                          "Project Document - View" :
                          "Private Project Document - View");
@


1.12.2.1.4.6.2.1
log
@project documents should default to being public (since private project
documents aren't yet supported in 1.0.x / 1.1.0)
@
text
@d36 1
a36 1
 * @@version $Id: ProjectDocument.java,v 1.12.2.1.4.6 2001/06/07 02:31:36 edk Exp $
d186 1
a186 1
        dc.setIsPublic(DBFlag.flagValueOf("Y"));
@


1.11
log
@Pushed getID() method into base class as a final method.
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.10 2001/03/07 01:53:22 lucas Exp $
d89 1
a89 1
	    return DBFlag.booleanValueOf(getIsPublic());
d427 3
a429 1
        } else {
d442 1
a442 1
        if (getProposedBy() == acl.getUser().getUserId())
d445 3
a447 1
        } else {
@


1.10
log
@Corrected regex madness for Torque upgrade.  -dlr
@
text
@d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.9 2001/02/27 23:16:25 elicia Exp $
a71 9

    //
    // Accessor methods
    //

    public String getID()
    {
        return getPrimaryKey().toString();
    }
@


1.9
log
@changed equality test for getProposedBy to use .equals instead of =
@
text
@a24 1
import org.tigris.helm.om.peer.*;
d27 1
a27 2
import org.tigris.helm.om.peer.*;
import org.tigris.helm.om.base.*;
d35 1
a35 1
 * @@version $Id: ProjectDocument.java,v 1.8 2001/02/27 02:17:56 elicia Exp $
@


1.8
log
@updated disapprove method to send emails
@
text
@d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.7 2001/02/26 20:21:18 dlr Exp $
d435 1
a435 1
        if (getProposedBy() == acl.getUser().getUserId())
@


1.7
log
@Changes to keep in step with the latest Torque-generated code.
@
text
@d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.6 2001/02/24 11:43:01 dlr Exp $
d73 1
a73 1
        TemplateTool.getPathToMessageTemplate("ProjectDisapprove.wm");
d90 1
a90 1
        return getApprovedBy() != UserPeer.getNobodyUser().getUserId();
d347 2
a348 1
    public void disapprove(AccessControlList acl, String htURL)
a350 1
        delete(acl, true, htURL);
d352 4
a355 3
        //Send email to the owners.
        User disapproving = acl.getUser();
        String subject = "Document " + getName() + " disapproved.";
d357 1
d359 1
a359 1
        ctx.put("disapprovingUser", disapproving);
d362 3
a364 8
        try {
            emailer.messageUsersWithProjectOwnership(getProject(), subject,
                                                     body);
        }
        catch (Exception e) {
            Log.error
                ("Unable to mail project owner about document disapproval", e);
        }
@


1.6
log
@Make use of the TurbineWebMacro facade of WebMacroService for a more convienient interface.
@
text
@d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.5 2001/02/24 03:59:53 dlr Exp $
d263 1
a263 1
        mapping.setSectionId(new SimpleKey(sectionID));
@


1.5
log
@Sync'd with latest Turbine changes.  Mostly this consists of the use of the new SimpleKey class to handle primary database keys.
@
text
@d16 1
a16 1
import org.apache.turbine.services.webmacro.WebMacroService;
d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.4 2001/02/22 01:25:44 dlr Exp $
d355 1
a355 3
        WebMacroService wmSrvc = (WebMacroService)
            TurbineServices.getInstance().getService(WebMacroService.SERVICE_NAME);
        WebContext ctx = wmSrvc.getContext();
d358 1
a358 1
        String body = wmSrvc.handleRequest(ctx, DISAPPROVE_TMPL);
@


1.4
log
@Find templates in the right place.
@
text
@d7 1
a7 1
import org.apache.turbine.om.BaseObject;
d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.3 2001/02/22 00:38:46 dlr Exp $
d81 1
a81 7
        return (String)getPrimaryKey();
    }

    public Project getProject()
         throws Exception
    {
        return ProjectPeer.getInstance(Integer.toString(getProjectId()));
d106 1
a106 1
    public User getProposedByUser()
d109 1
a109 3
        return (getProposedBy() == 0) ?
                UserPeer.getAnonymousUser() :
                UserPeer.retrieveByPK(getProposedBy());
d164 1
a164 1
        sectionID = rec.getSectionId();   
d189 6
a194 6
        int proposedBy = acl.getUser().getUserId();
        dc.setProposedBy(proposedBy);
        int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                          proposedBy : 
                          UserPeer.getNobodyUser().getUserId());
        dc.setApprovedBy(approvedBy);
a195 1
   
d263 1
a263 1
        mapping.setSectionId(Integer.parseInt(sectionID));
@


1.3
log
@Now using TurbineWebMacroService instead of TemplateInterpolator.
@
text
@d31 1
d37 1
a37 1
 * @@version $Id: ProjectDocument.java,v 1.2 2001/02/21 03:02:22 edk Exp $
d65 2
a66 1
    private static final String CREATED_TMPL = "ProjectCreated.wm";
d73 1
a73 1
        "project/ProjectDisapprove.wm";
@


1.2
log
@adding files from the branch to the head
@
text
@d15 2
d19 1
a19 1
import org.webmacro.engine.BuildContext;
d36 1
a36 1
 * @@version $Id: ProjectDocument.java,v 1.1.1.1 2001/02/21 00:32:58 dlr Exp $
d362 3
a364 1
        BuildContext ctx = TemplateInterpolator.createContext();
d367 1
a367 2
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
@


1.1
log
@file ProjectDocument.java was initially added on branch HELM_PEER_PORT_BRANCH.
@
text
@d1 491
@


1.1.1.1
log
@Replacing the HEAD with the HELM_PEER_PORT_BRANCH.
@
text
@a0 491
package org.tigris.helm.om;

import java.io.*;
import java.util.*;
import java.security.MessageDigest;

import org.apache.turbine.om.BaseObject;
import org.apache.turbine.om.peer.BasePeer;
import org.apache.turbine.util.db.Criteria;
import org.apache.turbine.util.ObjectUtils;
import org.apache.turbine.util.StringUtils;
import org.apache.turbine.util.ParameterParser;
import org.apache.turbine.util.Log;
import org.apache.turbine.util.db.pool.DBConnection;

import org.webmacro.servlet.WebContext;
import org.webmacro.engine.BuildContext;

import org.joist.util.URL;

import org.tigris.helm.*;
import org.tigris.helm.om.*;
import org.tigris.helm.om.peer.*;
import org.tigris.helm.security.*;
import org.tigris.helm.tool.*;
import org.tigris.helm.om.peer.*;
import org.tigris.helm.om.base.*;
import org.tigris.helm.tool.DBFlag;

/** 
 * Project document business object.
 *
 * @@author <a href="mailto:elicia@@collab.net">Elicia David</a>
 * @@version $Id: ProjectDocument.java,v 1.1.2.15 2001/02/20 04:53:54 elicia Exp $
 */
public class ProjectDocument extends BaseProjectDocument
{
    /**
     * The buffer size used when computing the MD5 checksum of a file.
     */
    private static final int MD5_BUF_SIZE = 4096;

    /**
     * The document approval permission.
     */
    private static final String APPROVE_PERM = "Project Document - Approve";

    /**
     * The primary key of the document.
     */
    private static final String DOCUMENT_ID = "document_id"; 

    /**
     * The primary key of the section in the document-section join table.
     */
    private static final String SECTION_ID = "section_id"; 

    /**
     * The name of the template used to create the body of the document 
     * creation announcement email.
     */
    private static final String CREATED_TMPL = "ProjectCreated.wm";

    /**
     * The name of the template used to create the body of the document 
     * disapproval email.
     */
    private static final String DISAPPROVE_TMPL =
        "project/ProjectDisapprove.wm";

    //
    // Accessor methods
    //

    public String getID()
    {
        return (String)getPrimaryKey();
    }

    public Project getProject()
         throws Exception
    {
        return ProjectPeer.getInstance(Integer.toString(getProjectId()));
    }

    /**
     * Determines whether a document has been approved
     */
    public boolean isApproved()
        throws Exception
    {
        return getApprovedBy() != UserPeer.getNobodyUser().getUserId();
    }

    /**
     * Checks whether a publicly accessible document.
     *
     * @@return Whether public document.
     */
    public boolean isPublic()
    {
	    return DBFlag.booleanValueOf(getIsPublic());
    }

    /**
     * Gets user that proposed the document.
     */
    public User getProposedByUser()
        throws Exception
    {
        return (getProposedBy() == 0) ?
                UserPeer.getAnonymousUser() :
                UserPeer.retrieveByPK(getProposedBy());
    }

    /**
     * Returns the link to the file.
     */
    public String getLink (Project project) 
    {
        String link = null;
        StringBuffer argBuffer = null;
        String arg = null;
        String type = getType();

        if (type.equals("url"))
        {
           link = getUrl();
        } 
        else if (type.equals("text"))
        {
           argBuffer = new StringBuffer("documentID=");
           argBuffer.append(getID());
           arg = argBuffer.toString();
           link = project.getProjectPageURL("ProjectDocumentView", 
                                            arg);
        }
        else
        {
           argBuffer = new StringBuffer("dcID=");
           argBuffer.append(getID()).append("&action=download");
           arg = argBuffer.toString();
           link = project.getProjectPageURL("ProjectDocumentList", 
                                                   arg);
        }
   
        return link;
     }
          

    // 
    // Database methods
    //

    /**
     * Returns the sectionID this document is filed under.
     * If document is top-level, sectionID=0
     */
    public int getSectionID()
        throws Exception
    {        
        Vector sectionIDs = null;
        int sectionID = 0;
        Criteria c = new Criteria()
            .add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID());
        sectionIDs =  ProjectDocumentSectionPeer.doSelect(c);
        ProjectDocumentSection rec = (ProjectDocumentSection)sectionIDs.elementAt(0);
        sectionID = rec.getSectionId();   
        return sectionID;
    }

    /**
     * Adds a new document.
     *
     * @@param acl The ACL to check for permission.
     */
    public static ProjectDocument add(AccessControlList acl, Project project,
                                      String name, String descrip, 
                                      String type, File f, 
                                      String url, String text, 
                                      String sectionID, String htURL)
        throws ACLException, Exception
    {
        ProjectDocument dc = new ProjectDocument();
        dc.setProjectId(project.getProjectId());
        dc.assertAddPermission(acl);

        dc.setName(name);
        dc.setDescription(descrip);
        dc.setType(type);
        dc.setUrl(url);
        dc.setText(text);
        int proposedBy = acl.getUser().getUserId();
        dc.setProposedBy(proposedBy);
        int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                          proposedBy : 
                          UserPeer.getNobodyUser().getUserId());
        dc.setApprovedBy(approvedBy);
        dc.setIsPublic(DBFlag.flagValueOf("N"));
   

        if (f != null && f.exists()) {
            dc.uploadFile(f, htURL);
        }

        dc.save();

        // Add to document-section join table
        if (sectionID != null) dc.addToSection(sectionID);

        return dc;
    }

    /**
     * Handles file upload.
     * <p>
     * HELP: Elicia, please bring some clarity to my poor description.
     */
    private void uploadFile(File f, String htURL)
        throws Exception
    {
        // Handle fields inferred from the File.
        setFileName(f.getName());
        setLocation(extractLocation(f));

        // Compute the file MD5 checksum and size.
        int size = -1;
        String md5Checksum = null;
        try {
            if (f.canRead()) {
                FileInputStream in = new FileInputStream(f);
                MessageDigest md5 = MessageDigest.getInstance
                    (CryptoProviderService.MD5,
                     CryptoProviderService.CRYPTIX_PROVIDER);
                byte[] buf = new byte[MD5_BUF_SIZE];
                int read = 0;
                while ((read = in.read(buf)) != -1)
                {
                    size += read;
                    md5.update(buf, 0, read);
                }
                in.close();
                md5Checksum = ByteToHex.transform(md5.digest());
                //dc.setMd5(md5Checksum);
                //if (size != -1) dc.setSize(size);
                getProject().writeHtaccessFile(getLocation(), htURL);
            }
        }
        catch (Exception e) {
            Log.error("Couldn't determine file MD5 checksum or " + 
                      "size: " + f.getAbsolutePath() + ": " +
                      e.getMessage());
        }
    }

    /**
     * Associates document with a section.
     * Adds record to HELM_DOCUMENT_SECTION join table.
    */
    private void addToSection(String sectionID)
        throws Exception
    {
        // If document is already associated with a section, delete record
        this.deleteFromSection();

        ProjectDocumentSection mapping = new ProjectDocumentSection();
        mapping.setDocumentId(this.getDocumentId());
        mapping.setSectionId(Integer.parseInt(sectionID));
        mapping.save();
    }

    /**
     * Removes associates between document and section.
     * Deletes record in document-section join table.
    */
    private void deleteFromSection()
        throws Exception
    {
       Criteria c = new Criteria().
           add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID());
       ProjectDocumentSectionPeer.doDelete(c);
    }

    /**
     * Moves a document to top level (removes association with section)
     * Deletes record in document-section join table
     * And adds a record with sectionId = 0
    */
    public void moveToTop()
        throws Exception
    {
        deleteFromSection();
        addToSection("0");
    }

    /**
     * Updates a document.
     *
     * @@param acl           The access control list of the current user.
     * @@exception ACLException
     */
    public void edit (AccessControlList acl, String name, 
                      String description, String type,
                      String url, String text, String sectionID,
                      File f, String htURL)
        throws ACLException, Exception
    {
        assertEditPermission(acl);

        if (name != null) setName(name);
        if (description != null) setDescription(description);
        if (type != null) setType(type);
        if (sectionID != null) addToSection(sectionID);
        if (url != null) setUrl(url);
        if (text != null) setText(text);
        if (f != null && f.exists()) {
           uploadFile(f, htURL);
        }

        save();
    }

    /**
     * Approves the document in the name of the approving user..
     *
     * @@param acl The ACL of the user approving the document.
     *
     * @@exception ACLException The ACL does not have approval permission.
     * @@exception DoesNotExist If the specified project is invalid.
     * @@exception Exception    If a database error occurs.
     */
    public void approve(AccessControlList acl)
        throws ACLException, DoesNotExist, Exception
    {
        if (acl != null) {
            acl.assertPermission(APPROVE_PERM, getProject());
                                          
            setApprovedBy(acl.getUser().getUserId());
            save();
        }
    }

    /**
     * Deletes an unapproved document, sending email to the owners
     * about it.
     *
     * @@param acl The ACL to check for permission.
     * @@param htURL
     *
     * @@exception ACLException Insufficient permission.
     */
    public void disapprove(AccessControlList acl, String htURL)
        throws ACLException, DoesNotExist, Exception
    {
        delete(acl, true, htURL);

        //Send email to the owners.
        User disapproving = acl.getUser();
        String subject = "Document " + getName() + " disapproved.";
        BuildContext ctx = TemplateInterpolator.createContext();
        ctx.put("document", this);
        ctx.put("disapprovingUser", disapproving);
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
        HelmEmailer emailer = new HelmEmailer();
        try {
            emailer.messageUsersWithProjectOwnership(getProject(), subject,
                                                     body);
        }
        catch (Exception e) {
            Log.error
                ("Unable to mail project owner about document disapproval", e);
        }
    }
    
    /**
     * Deletes this document.
     *
     * @@param acl            The ACL to check for permission.
     * @@param fromFilesystem Whether to delete from the file system as well.
     */
    public void delete(AccessControlList acl, boolean fromFilesystem,
                       String htURL)
        throws Exception
    {
        acl.assertPermission("Project Document - Delete", getProject());
        if (fromFilesystem) {
            File victim =
                new File(getLocation() + File.separatorChar + getFileName());
            if (victim.exists()) {
                victim.delete();
                getProject().writeHtaccessFile(getLocation(), htURL);
            }
        }
        delete();
        deleteFromSection();
    }

    private void delete()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDocumentPeer.DOCUMENT_ID, getDocumentId());
        ProjectDocumentPeer.doDelete(c);
    }


    /**
     * Extracts the directory path to the file.
     *
     * @@param f The file to extract path information from.
     * @@return  The extracted path information.
     */
    public static final String extractLocation(File f)
    {
        return f.getParentFile().getAbsolutePath();
    }



    //
    // Permission methods
    //

    /**
     * Asserts addition and/or approval permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertAddPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        acl.assertPermission("Project Document - Suggest", getProject());
    }

    /**
     * Asserts edit permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertEditPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        if (getProposedBy() == acl.getUser().getUserId())
        {
            acl.assertPermission("Project Document - View", getProject());
        } else {
            acl.assertPermission("Project Document - Edit", getProject());
        }
    }

    /**
     * Asserts deletion and/or disapproval permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertDeletePermission(AccessControlList acl)
        throws ACLException, Exception
    {
        if (getProposedBy() == acl.getUser().getUserId())
        {
            acl.assertPermission("Project Document - View", getProject());
        } else {
            acl.assertPermission("Project Document - Delete", getProject());
        }
    }

    /**
     * Returns true if the given ACL can see this document.
     */
    public boolean isViewableBy(AccessControlList acl)
        throws Exception
    {
        return (acl.hasPermission(requiredViewPermission(acl), getProject()));
    }

    /**
     * Returns the appropriate permission needed 
     */
    public String requiredViewPermission(AccessControlList acl)
        throws Exception
    {
        String permission = "Project Document - View";
        if ((!isApproved()) && (getProposedBy() != acl.getUser().getUserId()))
        {
            permission = "Project Document - Approve";
        }
        return permission;
    }

}
@


1.1.2.1
log
@Classes ported to the Turbine Peer system. -dlr and leonardr
@
text
@a0 20
package org.tigris.helm.om;

import java.util.*;

import org.apache.turbine.om.BaseObject;
import org.apache.turbine.om.peer.BasePeer;
import org.apache.turbine.util.db.Criteria;
import org.apache.turbine.util.ObjectUtils;
import org.apache.turbine.util.StringUtils;
import org.apache.turbine.util.ParameterParser;
import org.apache.turbine.util.Log;
import org.apache.turbine.util.db.pool.DBConnection;

import org.tigris.helm.om.peer.*;

/** 
 */
public class ProjectDocument extends BaseProjectDocument
{
}
@


1.1.2.2
log
@added isPublic() methods
@
text
@a14 1
import org.tigris.helm.tool.DBFlag;
a19 9
    /**
     * Checks whether a publicly accessible document.
     *
     * @@return Whether public document.
     */
    public boolean isPublic()
    {
	    return DBFlag.booleanValueOf(getIsPublic());
    }
@


1.1.2.3
log
@Made isPublic() final.
@
text
@a17 1
 * @@version $Id: $
d26 1
a26 1
    public final boolean isPublic()
d28 1
a28 1
        return DBFlag.booleanValueOf(getIsPublic());
@


1.1.2.4
log
@added permission methods
@
text
@a13 1
import org.tigris.helm.security.*;
d18 1
a18 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.3 2001/02/13 20:23:04 dlr Exp $
a21 25

    //
    // Accessor methods
    //

    public String getID()
    {
        return (String)getPrimaryKey();
    }

    public Project getProject()
         throws Exception
    {
        return ProjectPeer.getInstance(Integer.toString(getProjectId()));
    }

    /**
     * Determines whether a news item has been approved
     */
    public boolean isApproved()
        throws Exception
    {
        return getApprovedBy() != UserPeer.getNobodyUser().getUserId();
    }

d27 1
a27 82
    public boolean isPublic()
    {
	    return DBFlag.booleanValueOf(getIsPublic());
    }


    //
    // Database methods
    //

    public void delete(AccessControlList acl)
        throws ACLException, Exception
    {
        if (acl == null) 
        {
            throw new Exception("No ACL provided.");
        }
        assertDeletePermission(acl);
        deleteNC();
    }

    private void deleteNC()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDocumentPeer.DOCUMENT_ID, getDocumentId());
        NewsItemPeer.doDelete(c);
    }


    //
    // Permission methods
    //

    /**
     * Asserts addition and/or approval permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertAddPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        acl.assertPermission("Project Document - Suggest", getProject());
    }

    /**
     * Asserts edit permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertEditPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        if (getProposedBy() == acl.getUser().getUserId())
        {
            acl.assertPermission("Project Document - View", getProject());
        } else {
            acl.assertPermission("Project Document - Edit", getProject());
        }
    }

    /**
     * Asserts deletion and/or disapproval permission for this document.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertDeletePermission(AccessControlList acl)
        throws ACLException, Exception
    {
        if (getProposedBy() == acl.getUser().getUserId())
        {
            acl.assertPermission("Project Document - View", getProject());
        } else {
            acl.assertPermission("Project Document - Delete", getProject());
        }
    }

    /**
     * Returns true if the given ACL can see this document.
     */
    public boolean isViewableBy(AccessControlList acl)
        throws Exception
d29 1
a29 1
        return (acl.hasPermission(requiredViewPermission(acl), getProject()));
a30 15

    /**
     * Returns the appropriate permission needed 
     */
    public String requiredViewPermission(AccessControlList acl)
        throws Exception
    {
        String permission = "Project Document - View";
        if ((!isApproved()) && (getProposedBy() != acl.getUser().getUserId()))
        {
            permission = "Project Document - Approve";
        }
        return permission;
    }

@


1.1.2.5
log
@Added new imports necessitated by Torque.
@
text
@a15 1
import org.tigris.helm.om.base.*;
d19 1
a19 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.4 2001/02/13 22:45:20 elicia Exp $
@


1.1.2.6
log
@added getLink() and getSection() methods
@
text
@a2 1
import java.io.*;
a3 1
import java.security.MessageDigest;
a13 6
import org.webmacro.servlet.WebContext;

import org.joist.util.URL;

import org.tigris.helm.om.*;
import org.tigris.helm.om.peer.*;
a14 1
import org.tigris.helm.tool.*;
d20 1
a20 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.5 2001/02/16 03:01:27 dlr Exp $
a24 20
    /**
     * The buffer size used when computing the MD5 checksum of a file.
     */
    private static final int MD5_BUF_SIZE = 4096;

    /**
     * The document approval permission.
     */
    private static final String APPROVE_PERM = "Project Document - Approve";

    /**
     * The primary key of the document.
     */
    private static final String DOCUMENT_ID = "document_id"; 

    /**
     * The primary key of the section in the document-section join table.
     */
    private static final String SECTION_ID = "section_id"; 

a58 9
    /**
     * Returns the link to the file.
     */
    public String getLink (Project project) 
    {
        String link = null;
        StringBuffer argBuffer = null;
        String arg = null;
        String type = getType();
d60 1
a60 26
        if (type.equals("url"))
        {
           link = getUrl();
        } 
        else if (type.equals("text"))
        {
           argBuffer = new StringBuffer("documentID=");
           argBuffer.append(getID());
           arg = argBuffer.toString();
           link = project.getProjectPageURL("ProjectDocumentView", 
                                            arg);
        }
        else
        {
           argBuffer = new StringBuffer("dcID=");
           argBuffer.append(getID()).append("&action=download");
           arg = argBuffer.toString();
           link = project.getProjectPageURL("ProjectDocumentList", 
                                                   arg);
        }
   
        return link;
     }
          

    // 
d64 1
a64 31
    /**
     * Returns the section this document is filed under.
     * If document is top-level (not under a section, return null
     */
    public ProjectSection getSection()
        throws Exception
    {        
        Vector sections = null;
        ProjectSection section = null;
        Criteria c = new Criteria()
            .add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID())
            .addJoin(ProjectSectionPeer.SECTION_ID,
                     ProjectDocumentSectionPeer.SECTION_ID);
        sections =  ProjectSectionPeer.doSelect(c);
        if (!sections.isEmpty())
        {
           section = (ProjectSection)sections.elementAt(0);
        }
        return section;
    }

    /**
     * Adds a new document.
     *
     * @@param acl The ACL to check for permission.
     */
    public static ProjectDocument add(AccessControlList acl, Project project,
                                      String name, String descrip, 
                                      String type, File f, 
                                      String url, String text, 
                                      String sectionID, String htURL)
d67 3
a69 58
        ProjectDocument dc = new ProjectDocument();
        dc.setProjectId(project.getProjectId());
        dc.assertAddPermission(acl);

        dc.setName(name);
        dc.setDescription(descrip);
        dc.setType(type);
        int proposedBy = acl.getUser().getUserId();
        dc.setProposedBy(proposedBy);
        int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                          proposedBy : 
                          UserPeer.getNobodyUser().getUserId());
        dc.setApprovedBy(approvedBy);
        dc.setIsPublic(DBFlag.flagValueOf("N"));
   
        // Add to document-section join table
        ProjectDocumentSection mapping = new ProjectDocumentSection();
        mapping.setDocumentId(dc.getDocumentId());
            Log.debug("Secid=" + sectionID);
        mapping.setSectionId(Integer.parseInt(sectionID));
        mapping.save();

        if (f != null && f.exists()) {
            // Handce fields inferred from the File.
            dc.setFileName(f.getName());
            dc.setLocation(extractLocation(f));

            // Compute the file MD5 checksum and size.
            int size = -1;
            String md5Checksum = null;
            try {
                if (f.canRead()) {
                    FileInputStream in = new FileInputStream(f);
                    MessageDigest md5 = MessageDigest.getInstance
                        (CryptoProviderService.MD5,
                         CryptoProviderService.CRYPTIX_PROVIDER);
                    byte[] buf = new byte[MD5_BUF_SIZE];
                    int read = 0;
                    while ((read = in.read(buf)) != -1)
                    {
                        size += read;
                        md5.update(buf, 0, read);
                    }
                    in.close();
                    md5Checksum = ByteToHex.transform(md5.digest());
                    //dc.setMd5(md5Checksum);
                    //if (size != -1) dc.setSize(size);
                    project.writeHtaccessFile(dc.getLocation(), htURL);
                }
            } catch (Exception e) {
                Log.error("Couldn't determine file MD5 checksum or " + 
                          "size: " + f.getAbsolutePath() + ": " +
                          e.getMessage());
            }
        } else {
            // If no file, document must be set by URL or text
            if (url != null) dc.setUrl(url);
            if (text != null) dc.setText(text);
d71 2
a72 40

        dc.save();
        return dc;
    }

    /**
     * Deletes this document.
     *
     * @@param acl            The ACL to check for permission.
     * @@param fromFilesystem Whether to delete from the file system as well.
     * @@param ctx            TODO: CHANGE THIS PARAM AND TYPE
     */
    public void delete(AccessControlList acl, boolean fromFilesystem,
                       WebContext ctx)
        throws Exception
    {
        Project project = ProjectPeer.retrieveByPK(getProjectId());
        acl.assertPermission("Project Document - Delete", project);
        if (fromFilesystem) {
            File victim =
                new File(getLocation() + File.separatorChar + getFileName());
            if (victim.exists()) {
                victim.delete();
            }
            String htURL = URL.schemeAndServer(ctx) +
                "/servlets/ProjectDocuments";
            project.writeHtaccessFile(getLocation(), htURL);
        }
        ProjectDocumentPeer.doDelete(this);
    }

    /**
     * Extracts the directory path to the file.
     *
     * @@param f The file to extract path information from.
     * @@return  The extracted path information.
     */
    public static final String extractLocation(File f)
    {
        return f.getParentFile().getAbsolutePath();
@


1.1.2.7
log
@* Slightly reorg'd getSection() for clarity.
* Prefer List interface.
@
text
@d29 1
a29 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.6 2001/02/16 20:02:06 elicia Exp $
d134 1
d140 1
a140 1
        List sections = ProjectSectionPeer.doSelect(c);
d143 1
a143 1
           section = (ProjectSection)sections.get(0);
@


1.1.2.8
log
@added disapprove, approve, and getProposedByUser methods
@
text
@a16 1
import org.webmacro.engine.BuildContext;
a19 1
import org.tigris.helm.*;
a53 12
    /**
     * The name of the template used to create the body of the document 
     * creation announcement email.
     */
    private static final String CREATED_TMPL = "ProjectCreated.wm";

    /**
     * The name of the template used to create the body of the document 
     * disapproval email.
     */
    private static final String DISAPPROVE_TMPL = "project/ProjectDisapprove.wm";

d70 1
a70 1
     * Determines whether a document has been approved
a88 11
     * Gets user that proposed the document.
     */
    public User getProposedByUser()
        throws Exception
    {
        return (getProposedBy() == 0) ?
                UserPeer.getAnonymousUser() :
                UserPeer.retrieveByPK(getProposedBy());
    }

    /**
a133 1
        Vector sections = null;
d139 1
a139 1
        sections =  ProjectSectionPeer.doSelect(c);
d142 1
a142 1
           section = (ProjectSection)sections.elementAt(0);
d177 1
a223 48
     * Approves the document in the name of the approving user..
     *
     * @@param acl The ACL of the user approving the document.
     *
     * @@exception ACLException The ACL does not have approval permission.
     * @@exception DoesNotExist If the specified project is invalid.
     * @@exception Exception    If a database error occurs.
     */
    public void approve(AccessControlList acl)
        throws ACLException, DoesNotExist, Exception
    {
        if (acl != null) {
            acl.assertPermission(APPROVE_PERM, getProject());
                                          
            setApprovedBy(acl.getUser().getUserId());
            save();
        }
    }

    /**
     * Deletes an unapproved document, sending email to the owners
     * about it.  
     */
    public void disapprove(AccessControlList acl, String htURL)
        throws ACLException, DoesNotExist, Exception
    {
        delete(acl, true, htURL);
        /*
        //Send email to the owners.
        User disapproving = acl.getUser();
        String subject = "Document " + getName() + " disapproved.";
        BuildContext ctx = TemplateInterpolator.createContext();
        ctx.put("document", this);
        ctx.put("disapprovingUser", disapproving);
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
        HelmEmailer emailer = new HelmEmailer();
         try {
             emailer.messageUsersWithProjectOwnership(getProject(), subject, body);
         }
         catch (Exception e) {
             Log.error
                 ("Unable to mail project owner about document disapproval", e);
         }
         */
    }
    
    /**
d231 1
a231 1
                       String htURL)
a240 1
                project.writeHtaccessFile(getLocation(), htURL);
d242 3
@


1.1.2.9
log
@added edit, addToSection, deleteFromSection
@
text
@d31 1
a31 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.8 2001/02/17 00:21:29 elicia Exp $
d200 5
d207 31
a237 1
            dc.uploadFile(f, htURL);
a244 4

        // Add to document-section join table
        dc.addToSection(sectionID);

a245 94
    }

    private void uploadFile(File f, String htURL)
        throws Exception
    {
        // Handle fields inferred from the File.
        setFileName(f.getName());
        setLocation(extractLocation(f));

        // Compute the file MD5 checksum and size.
        int size = -1;
        String md5Checksum = null;
        try {
            if (f.canRead()) {
                FileInputStream in = new FileInputStream(f);
                MessageDigest md5 = MessageDigest.getInstance
                    (CryptoProviderService.MD5,
                     CryptoProviderService.CRYPTIX_PROVIDER);
                byte[] buf = new byte[MD5_BUF_SIZE];
                int read = 0;
                while ((read = in.read(buf)) != -1)
                {
                    size += read;
                    md5.update(buf, 0, read);
                }
                in.close();
                md5Checksum = ByteToHex.transform(md5.digest());
                //dc.setMd5(md5Checksum);
                //if (size != -1) dc.setSize(size);
                getProject().writeHtaccessFile(getLocation(), htURL);
            }
        } catch (Exception e) {
            Log.error("Couldn't determine file MD5 checksum or " + 
                      "size: " + f.getAbsolutePath() + ": " +
                      e.getMessage());
        }
    }

    /**
     * Associates document with a section.
     * Adds record to HELM_DOCUMENT_SECTION join table.
    */
    private void addToSection(String sectionID)
        throws Exception
    {
        // If document is already associated with a section, delete record
        this.deleteFromSection();

        ProjectDocumentSection mapping = new ProjectDocumentSection();
        mapping.setDocumentId(this.getDocumentId());
        mapping.setSectionId(Integer.parseInt(sectionID));
        mapping.save();
    }

    /**
     * Removes associates between document and section.
     * Deletes record in document-section join table.
    */
    private void deleteFromSection()
        throws Exception
    {
       Criteria c = new Criteria().
           add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID());
        ProjectDocumentSectionPeer.doDelete(c); 
    }


    /**
     * Updates a document.
     *
     * @@param acl           The access control list of the current user.
     * @@exception ACLException
     */
    public void edit (AccessControlList acl, String name, 
                      String description, String type,
                      String url, String text, String sectionID,
                      File f, String htURL)
        throws ACLException, Exception
    {
        assertEditPermission(acl);

        if (name != null) setName(name);
        if (description != null) setDescription(description);
        if (type != null) setType(type);
        if (sectionID != null) addToSection(sectionID);
        if (f != null && f.exists()) {
           uploadFile(f, htURL);
        } else {
            // If no file, document must be set by URL or text
            if (url != null) setUrl(url);
            if (text != null) setText(text);
        }

        save();
@


1.1.2.10
log
@changed getSection method to getSectionID
@
text
@d31 1
a31 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.9 2001/02/17 20:32:42 elicia Exp $
d153 2
a154 2
     * Returns the sectionID this document is filed under.
     * If document is top-level, sectionID=0
d156 1
a156 1
    public int getSectionID()
d159 2
a160 2
        Vector sectionIDs = null;
        int sectionID = 0;
d162 9
a170 5
            .add(ProjectDocumentSectionPeer.DOCUMENT_ID, getID());
        sectionIDs =  ProjectDocumentSectionPeer.doSelect(c);
        ProjectDocumentSection rec = (ProjectDocumentSection)sectionIDs.elementAt(0);
        sectionID = rec.getSectionId();   
        return sectionID;
a191 2
        dc.setUrl(url);
        dc.setText(text);
d203 4
d212 1
a212 1
        if (sectionID != null) dc.addToSection(sectionID);
d273 1
a273 1
    public void deleteFromSection()
a299 2
        if (url != null) setUrl(url);
        if (text != null) setText(text);
d302 4
d364 1
d370 2
a371 3
        //Project project = ProjectPeer.retrieveByPK(getProjectId());
        acl.assertPermission("Project Document - Delete", getProject());
          Log.debug("in delete");
d377 1
a377 1
                getProject().writeHtaccessFile(getLocation(), htURL);
d380 1
a380 1
        deleteNC();
a382 9
    private void deleteNC()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDocumentPeer.DOCUMENT_ID, getDocumentId());
        ProjectDocumentPeer.doDelete(c);
    }


d394 7
@


1.1.2.11
log
@Uncommented code in disapprove().
@
text
@d31 1
a31 4
 * Project document business object.
 *
 * @@author <a href="mailto:elicia@@collab.net">Elicia David</a>
 * @@version $Id: ProjectDocument.java,v 1.1.2.10 2001/02/18 00:52:29 elicia Exp $
d35 1
d66 1
a66 2
    private static final String DISAPPROVE_TMPL =
        "project/ProjectDisapprove.wm";
d325 1
a325 6
     * about it.
     *
     * @@param acl The ACL to check for permission.
     * @@param htURL
     *
     * @@exception ACLException Insufficient permission.
d331 1
a331 1

d341 8
a348 8
        try {
            emailer.messageUsersWithProjectOwnership(getProject(), subject,
                                                     body);
        }
        catch (Exception e) {
            Log.error
                ("Unable to mail project owner about document disapproval", e);
        }
@


1.1.2.12
log
@* Added note for documentation help.
* Start and close of different blocks of code should never happen on
  the same line.
@
text
@d34 1
a34 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.11 2001/02/20 00:24:36 dlr Exp $
a213 5
    /**
     * Handles file upload.
     * <p>
     * HELP: Elicia, please bring some clarity to my poor description.
     */
d243 1
a243 2
        }
        catch (Exception e) {
@


1.1.2.13
log
@Removed extraneous space.
@
text
@d34 1
a34 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.12 2001/02/20 00:32:06 dlr Exp $
d283 1
@


1.1.2.14
log
@* Renamed deleteNC() to delete().
* Made use of getProject() method.
@
text
@d34 1
a34 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.13 2001/02/20 02:06:10 dlr Exp $
d374 1
d376 1
d385 1
a385 1
        delete();
d388 1
a388 1
    private void delete()
@


1.1.2.15
log
@added moveToTop method to make a document top levedl
@
text
@d34 1
a34 1
 * @@version $Id: ProjectDocument.java,v 1.1.2.14 2001/02/20 02:16:11 dlr Exp $
d276 1
a276 1
    private void deleteFromSection()
d281 1
a281 13
       ProjectDocumentSectionPeer.doDelete(c);
    }

    /**
     * Moves a document to top level (removes association with section)
     * Deletes record in document-section join table
     * And adds a record with sectionId = 0
    */
    public void moveToTop()
        throws Exception
    {
        deleteFromSection();
        addToSection("0");
a383 1
        deleteFromSection();
@


