head	1.33;
access;
symbols
	TIGRIS_1_1_0RC2:1.10.2.1.4.5
	TIGRIS_1_1_0RC1:1.10.2.1.4.5
	TIGRIS_1_1:1.10.2.1.4.5.0.2
	TIGRIS_1_0_8:1.10.2.1.4.5
	TIGRIS_1_0_8RC3:1.10.2.1.4.5
	TIGRIS_1_0_8RC2:1.10.2.1.4.5
	TIGRIS_1_0_8RC1:1.10.2.1.4.5
	TIGRIS_1_0_7:1.10.2.1.4.5
	TIGRIS_1_0_7RC3:1.10.2.1.4.5
	TIGRIS_1_0_7RC2:1.10.2.1.4.5
	TIGRIS_1_0_7RC1:1.10.2.1.4.5
	TIGRIS_1_0_6:1.10.2.1.4.5
	TIGRIS_1_0_6RC5:1.10.2.1.4.5
	TIGRIS_1_0_6RC4:1.10.2.1.4.5
	TIGRIS_1_0_6RC3:1.10.2.1.4.5
	TIGRIS_1_0_6RC2:1.10.2.1.4.5
	TIGRIS_1_0_6RC1:1.10.2.1.4.5
	TIGRIS_1_0_5:1.10.2.1.4.4
	TIGRIS_1_0_5RC6:1.10.2.1.4.4
	TIGRIS_1_0_5RC5:1.10.2.1.4.4
	TIGRIS_1_0_5RC4:1.10.2.1.4.4
	TIGRIS_1_0_5RC3:1.10.2.1.4.4
	TIGRIS_1_0_5RC2:1.10.2.1.4.4
	TIGRIS_1_0_5RC1:1.10.2.1.4.4
	TIGRIS_1_0_4:1.10.2.1.4.4
	TIGRIS_1_0_3:1.10.2.1.4.4
	TIGRIS_1_0_2:1.10.2.1.4.4
	TIGRIS_1_0_1:1.10.2.1.4.1
	TIGRIS_1_0:1.10.2.1.0.4
	TIGRIS_1_0_0:1.10.2.1
	TIGRIS_1_0_0_RC1:1.10.0.2
	dlr:1.1.1
	HELM_PEER_PORT_BRANCH:1.1.1.1;
locks; strict;
comment	@# @;


1.33
date	2001.06.13.19.55.09;	author elicia;	state dead;
branches;
next	1.32;

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

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

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

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

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

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

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

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

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

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

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

1.21
date	2001.04.24.17.53.36;	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.52.19;	author dlr;	state Exp;
branches;
next	1.18;

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

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

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

1.15
date	2001.04.19.01.38.28;	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.29.03.06.36;	author elicia;	state Exp;
branches;
next	1.12;

1.12
date	2001.03.28.19.11.01;	author dlr;	state Exp;
branches;
next	1.11;

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

1.10
date	2001.03.10.03.50.40;	author edk;	state Exp;
branches
	1.10.2.1;
next	1.9;

1.9
date	2001.03.08.03.30.42;	author dlr;	state Exp;
branches;
next	1.8;

1.8
date	2001.03.07.01.53.22;	author lucas;	state Exp;
branches;
next	1.7;

1.7
date	2001.02.27.02.17.56;	author elicia;	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.26.32;	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.02.55.00;	author dlr;	state Exp;
branches;
next	1.1.2.3;

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

1.1.2.4
date	2001.02.13.20.19.46;	author dlr;	state Exp;
branches;
next	1.1.2.5;

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

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

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

1.1.2.8
date	2001.02.13.22.49.50;	author dlr;	state Exp;
branches;
next	1.1.2.9;

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

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

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

1.1.2.12
date	2001.02.18.00.50.31;	author elicia;	state Exp;
branches;
next	1.1.2.13;

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

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

1.1.2.15
date	2001.02.20.00.36.59;	author dlr;	state Exp;
branches;
next	1.1.2.16;

1.1.2.16
date	2001.02.20.02.02.47;	author dlr;	state Exp;
branches;
next	1.1.2.17;

1.1.2.17
date	2001.02.20.02.19.22;	author dlr;	state Exp;
branches;
next	1.1.2.18;

1.1.2.18
date	2001.02.20.22.13.45;	author dlr;	state Exp;
branches;
next	1.1.2.19;

1.1.2.19
date	2001.02.20.22.52.22;	author elicia;	state Exp;
branches;
next	1.1.2.20;

1.1.2.20
date	2001.02.20.23.32.47;	author elicia;	state Exp;
branches;
next	;

1.10.2.1
date	2001.03.28.23.30.11;	author dlr;	state Exp;
branches
	1.10.2.1.4.1;
next	;

1.10.2.1.4.1
date	2001.04.17.10.40.25;	author jrobbins;	state Exp;
branches;
next	1.10.2.1.4.2;

1.10.2.1.4.2
date	2001.04.20.21.46.29;	author edk;	state Exp;
branches;
next	1.10.2.1.4.3;

1.10.2.1.4.3
date	2001.04.24.20.31.22;	author dlr;	state Exp;
branches;
next	1.10.2.1.4.4;

1.10.2.1.4.4
date	2001.04.25.01.00.50;	author dlr;	state Exp;
branches;
next	1.10.2.1.4.5;

1.10.2.1.4.5
date	2001.06.07.02.31.36;	author edk;	state Exp;
branches;
next	;


desc
@@


1.33
log
@Deleting the deprecated ProjectDownload servlets. Pointing them at their ProjectDocument counterparts
@
text
@package org.tigris.helm.om;

import java.io.*;
import java.util.*;

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 org.apache.velocity.context.Context;

import org.joist.util.URL;

import org.tigris.helm.om.*;
import org.tigris.helm.security.*;
import org.tigris.helm.tool.*;

/** 
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 * @@author <a href="mailto:elicia@@collab.net">Elicia David</a>
 */
public class ProjectDownload extends BaseProjectDownload
    implements ProposableFileArtifact, ViewableBy
{
    /**
     * The download approval permission.
     */
    private static final String APPROVE_PERM = "Project Download - Approve";

    /**
     * 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("ProjectDownloadDisapprove.vm");

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

    /**
     * Gets user that proposed the download.
     *
     * @@return The proposing user.
     */
    public User getProposedByUser()
        throws Exception
    {
        return UserPeer.retrieveByPK(getProposedBy());
    }

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

    // 
    // Database methods
    //

    /**
     * Adds a new download.
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
     */
    public static ProjectDownload add(AccessControlList acl, Project project,
                                      String descrip, File f, String isPublic,
                                      String url)
        throws ACLException, Exception
    {
        ProjectDownload dl = new ProjectDownload();
        dl.setProjectId(project.getProjectId());
        dl.assertAddPermission(acl);

        User proposedBy = acl.getUser();
        dl.setUserRelatedByProposedBy(proposedBy);
        User approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                           proposedBy : 
                           UserPeer.getNobodyUser());
        dl.setUserRelatedByApprovedBy(approvedBy);
        dl.setIsPublic(DBFlag.flagValueOf(isPublic));
        dl.setDescription(descrip);
        dl.setUploadedDate(new Date());
        FileArtifactTool.fillInAttributes(dl, f);

        dl.save();
        List artifacts = FileArtifactTool.artifactsProposedBy
            (acl.getUser(), project.getProjectDownloads());
        project.writeHtaccessFile(Project.getHtaccess(dl), url, artifacts);
        return dl;
    }

    /**
     * Updates a download.
     *
     * @@param f The file artifact to replace the previous one with, or
     *          <code>null</code> if not replacing the file.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void edit(AccessControlList acl, String descrip,
                     User u, String isPublic, String dlURL, File f)
        throws ACLException, Exception
    {
        assertEditPermission(acl);

        if (isPublic != null) setIsPublic(DBFlag.flagValueOf(isPublic));
        if (descrip != null) setDescription(descrip);
        if (f != null)
        {
            // Replacing the file associated with this download.
            FileArtifactTool.fillInAttributes(this, f);
            setUploadedDate(new Date());
        }
        save();
    }

    /**
     * Deletes this download.
     *
     * @@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.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void delete(AccessControlList acl, boolean fromFilesystem,
                       String htURL)
        throws ACLException, Exception
    {
        assertDeletableBy(acl);
        if (fromFilesystem)
        {
            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);
        }
        delete();
    }

    /**
     * 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 Download - Delete", getProject());
        }
    }

    /**
     * Performs a delete with no ACL checking.
     */
    private void delete()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDownloadPeer.DOWNLOAD_ID, getDownloadId());
        ProjectDownloadPeer.doDelete(c);
    }

    /**
     * Approves this download.
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void approve(AccessControlList acl)
        throws ACLException, Exception
    {
        if (acl != null) 
        {
            acl.assertPermission(APPROVE_PERM, getProject());
            setApprovedBy(acl.getUser().getUserId());
            save();
        }
    }

    /**
     * Disapproves this download.
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void disapprove(AccessControlList acl, String htURL,
                           String rationale)
        throws ACLException, Exception
    {
        if (acl == null) 
        {
            throw new Exception("No ACL provided.");
        }

        acl.assertPermission(APPROVE_PERM, getProject());

        String subject = "Download for Project " + getProject().getName() +
            " disapproved.";
        Context ctx = TurbineVelocity.getContext();
        ctx.put("disapprovingUser", acl.getUser());
        ctx.put("download", this);
        ctx.put("rationale", rationale);
        String body = TurbineVelocity.handleRequest(ctx, DISAPPROVE_TMPL);
        HelmEmailer emailer = new HelmEmailer();
        emailer.sendEmail(UserPeer.getInstance(String.valueOf(getProposedBy()))
                          .getEmail(), subject, body);
        delete(acl, true, htURL);
    }


    //
    // Permission methods
    //

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

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

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

    /**
     * Asserts generic permission for this download.
     *
     * @@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 Download - View", getProject());
        }
        else
        {
            acl.assertPermission(nonProposerPerm, getProject());
        }
    }

    /**
     * Returns true if the given ACL can see this download.
     */
    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 Download - View";
        if (!isApproved() &&
            !getProposedBy().equals(acl.getUser().getUserId()))
        {
            permission = "Project Download - Approve";
        }
        return permission;
    }

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


1.32
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
@@


1.31
log
@.wm is now .vm
@
text
@d32 1
a32 1
    implements ProposableFileArtifact
@


1.30
log
@Ported Helm from WebMacro to Velocity.
@
text
@d44 1
a44 1
        TemplateTool.getPathToMessageTemplate("ProjectCreated.wm");
d51 1
a51 1
        TemplateTool.getPathToMessageTemplate("ProjectDownloadDisapprove.wm");
@


1.29
log
@.htaccess file are now be written to <project.id>/<user.id>/<file_name>.
@
text
@d13 2
d17 1
a17 1
import org.apache.turbine.services.webmacro.TurbineWebMacro;
d19 1
a19 1
import org.webmacro.servlet.WebContext;
d239 1
a239 1
        WebContext ctx = TurbineWebMacro.getContext();
d243 1
a243 1
        String body = TurbineWebMacro.handleRequest(ctx, DISAPPROVE_TMPL);
@


1.28
log
@Removed duplicate WebContext import.
@
text
@d115 1
a115 2
        project.writeHtaccessFile(Project.getHtaccess(dl.getLocation()), url,
                                  artifacts);
d169 1
a169 2
            p.writeHtaccessFile(Project.getHtaccess(getLocation()), htURL,
                                artifacts);
@


1.27
log
@.htaccess file should now only contain entries for a single user
(written to <project.id>/<user.id>/<file_name>).
@
text
@a17 1
import org.webmacro.servlet.WebContext;
@


1.26
log
@Elicia has worked on this class as well as I.
@
text
@d31 1
a31 1
    implements ProjectFileArtifact
d114 2
d117 1
a117 1
                                  project.getProjectDownloads());
d169 2
d172 1
a172 1
                                p.getProjectDownloads());
@


1.25
log
@Removed extraneous line feed.
@
text
@d28 1
@


1.24
log
@Merged in bug fix from the trunk HEAD for download replacement via
edit().
@
text
@a212 1

@


1.23
log
@Implemented clean OO-style suggested by edk instead of my quick hack.
@
text
@d257 1
a257 1
    public void assertAddPermission(AccessControlList acl)
d268 1
a268 1
    public void assertEditPermission(AccessControlList acl)
d271 1
a271 6
        if (getProposedBy() == acl.getUser().getUserId())
        {
            acl.assertPermission("Project Download - View", getProject());
        } else {
            acl.assertPermission("Project Download - Edit", getProject());
        }
d279 15
a293 1
    public void assertDeletePermission(AccessControlList acl)
d296 1
a296 1
        if (getProposedBy() == acl.getUser().getUserId())
d299 4
a302 2
        } else {
            acl.assertPermission("Project Download - Delete", getProject());
d322 2
a323 1
        if ((!isApproved()) && (!getProposedBy().equals(acl.getUser().getUserId())))
@


1.22
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
@d317 8
@


1.21
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
@a112 2
        List artifacts = project.getProjectDownloads();
        artifacts.addAll(project.getProjectDocuments());
d114 1
a114 1
                                  artifacts);
a165 2
            List artifacts = p.getProjectDownloads();
            artifacts.addAll(p.getProjectDocuments());
d167 1
a167 1
                                artifacts);
@


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
@d113 4
a116 2
        dl.getProject().writeHtaccessFile
            (Project.getHtaccess(dl.getLocation()), url, "DOWNLOADS");
d167 5
a171 2
            getProject().writeHtaccessFile
                (Project.getHtaccess(getLocation()), htURL, "DOWNLOADS");
@


1.19
log
@Added File param to edit() instance method to support replacement of
existing files on the file system in addition to description editting.
@
text
@d114 1
a114 1
            (Project.getHtaccess(dl.getLocation()), url);
d166 1
a166 1
                (Project.getHtaccess(getLocation()), htURL);
@


1.18
log
@Refactored ProjectDownload addition into FileArtifactTool.fillInAttributes()
routine.
@
text
@d120 4
d127 1
a127 1
                     User u, String isPublic, String dlURL)
d134 6
@


1.17
log
@Implemented ProjectFileArtifact.
@
text
@a4 1
import java.security.MessageDigest;
a32 5
     * The buffer size used when computing the MD5 checksum of a file.
     */
    private static final int MD5_BUF_SIZE = 4096;

    /**
d110 1
a111 38
        if (f != null && f.exists())
        {
            // Handle fields inferred from the File.
            dl.setFileName(f.getName());
            dl.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());
                }
            }
            catch (Exception e)
            {
                Log.error("Couldn't determine file MD5 checksum or " + 
                          "size: " + f.getAbsolutePath() + ": " +
                          e.getMessage());
            }

            if (size != -1) dl.setSize(size);
            dl.setMd5(md5Checksum);
        }
a233 12
    }


    /**
     * 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.16
log
@Write .htaccess files per project instead of per user.
@
text
@d31 1
@


1.15
log
@The proposing user should be able to delete their proposed file
whether they have 'Project Download - Delete' or not.
@
text
@d155 2
a156 1
        dl.getProject().writeHtaccessFile(dl.getLocation(), url);
d197 2
a198 1
            getProject().writeHtaccessFile(getLocation(), htURL);
@


1.14
log
@changed add method so that saving the new record happens before the .htaccess file is written
@
text
@d187 1
a187 1
        acl.assertPermission("Project Download - Delete", getProject());
d199 14
@


1.13
log
@changed equality test for requiredViewPermission method
@
text
@a152 1
            project.writeHtaccessFile(dl.getLocation(), url);
d155 1
@


1.12
log
@Added JavaDoc.
@
text
@d338 1
a338 1
        if ((!isApproved()) && (getProposedBy() != acl.getUser().getUserId()))
@


1.11
log
@Consistant use of brace positioning.
@
text
@d97 1
a97 2
    public static ProjectDownload add(AccessControlList acl,
                                      Project project,
d179 1
a179 1
     * @@param htURL          TODO : what is this?
@


1.10
log
@cleanup/update TODOs in comments slightly.
@
text
@d117 2
a118 1
        if (f != null && f.exists()) {
d126 4
a129 2
            try {
                if (f.canRead()) {
d145 2
a146 1
            catch (Exception e) {
d189 2
a190 1
        if (fromFilesystem) {
d193 2
a194 1
            if (victim.exists()) {
@


1.10.2.1
log
@Merged in bug fixes and clean up from HEAD.
@
text
@d97 2
a98 1
    public static ProjectDownload add(AccessControlList acl, Project project,
d117 1
a117 2
        if (f != null && f.exists())
        {
d125 2
a126 4
            try
            {
                if (f.canRead())
                {
d142 1
a142 2
            catch (Exception e)
            {
d176 1
a176 1
     * @@param htURL          The URL for auth and timeout.
d185 1
a185 2
        if (fromFilesystem)
        {
d188 1
a188 2
            if (victim.exists())
            {
@


1.10.2.1.4.1
log
@buddied MDA .htaccess changes from head to branch
@
text
@d153 1
a155 2
        Log.debug("url=" + url);
        dl.getProject().writeHtaccessFile(dl.getLocation(), url + "?");
d338 1
a338 1
        if ((!isApproved()) && (!getProposedBy().equals(acl.getUser().getUserId())))
@


1.10.2.1.4.2
log
@Port some of dlr's bug fixes back to the branch.
@
text
@d188 1
a188 1
        assertDeletableBy(acl);
a199 14
    }

    /**
     * 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 Download - Delete", getProject());
        }
@


1.10.2.1.4.3
log
@Implemented ProjectFileArtifact interface and refactored to make use of tool.FileArtifactTool helper class.
@
text
@d5 1
a30 1
    implements ProjectFileArtifact
d33 5
a114 1
        FileArtifactTool.fillInAttributes(dl, f);
d116 38
d155 2
a156 2
        project.writeHtaccessFile(Project.getHtaccess(dl.getLocation()), url,
                                  project.getProjectDownloads());
a161 4
     *
     * @@param f The file artifact to replace the previous one with, or
     *          <code>null</code> if not replacing the file.
     *
d165 1
a165 1
                     User u, String isPublic, String dlURL, File f)
a171 6
        if (f != null)
        {
            // Replacing the file associated with this download.
            FileArtifactTool.fillInAttributes(this, f);
            setUploadedDate(new Date());
        }
d197 1
a197 3
            Project p = getProject();
            p.writeHtaccessFile(Project.getHtaccess(getLocation()), htURL,
                                p.getProjectDownloads());
d278 12
a357 8
    }

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


1.10.2.1.4.4
log
@Merged in bug fix from the trunk HEAD for download replacement via
edit().
@
text
@d257 1
a257 1
    public final void assertAddPermission(AccessControlList acl)
d268 1
a268 1
    public final void assertEditPermission(AccessControlList acl)
d271 6
a276 1
        assertPermission(acl, "Project Download - Edit");
d284 1
a284 15
    public final void assertDeletePermission(AccessControlList acl)
        throws ACLException, Exception
    {
        assertPermission(acl, "Project Download - Delete");
    }

    /**
     * Asserts generic permission for this download.
     *
     * @@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)
d287 1
a287 1
        if (getProposedBy().equals(acl.getUser().getUserId()))
d290 2
a291 4
        }
        else
        {
            acl.assertPermission(nonProposerPerm, getProject());
d311 1
a311 2
        if (!isApproved() &&
            !getProposedBy().equals(acl.getUser().getUserId()))
@


1.10.2.1.4.5
log
@port dlr's changes to support private documents and sections
@
text
@d321 3
a323 3
        String permission;
        if (!isApproved() && 
                !getProposedBy().equals(acl.getUser().getUserId()))
a325 6
        }
        else
        {
            permission = (isPublic() ?
                          "Project Download - View" :
                          "Private Project Download - View");
@


1.9
log
@Pushed getID() method into base class as a final method.
@
text
@d176 1
a176 1
     * @@param ctx            TODO: CHANGE THIS PARAM AND TYPE
@


1.8
log
@Corrected regex madness for Torque upgrade.  -dlr
@
text
@a76 8
     * Returns the primary database key.
     */
    public final String getID()
    {
        return String.valueOf(getDownloadId());
    }

    /**
@


1.7
log
@updated disapprove method to send emails
@
text
@a23 2
import org.tigris.helm.om.peer.*;
import org.tigris.helm.om.base.*;
@


1.6
log
@Make use of the TurbineWebMacro facade of WebMacroService for a more convienient interface.
@
text
@d56 1
a56 1
        TemplateTool.getPathToMessageTemplate("ProjectDisapprove.wm");
d64 1
a64 1
        return (getApprovedBy() != UserPeer.getNobodyUser().getUserId());
d243 2
a244 2
    public void disapprove(AccessControlList acl, String rationale,
                           String htURL)
d258 1
a258 1
        ctx.put("news", this);
@


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;
d256 1
a256 3
        WebMacroService wmSrvc = (WebMacroService)
            TurbineServices.getInstance().getService(WebMacroService.SERVICE_NAME);
        WebContext ctx = wmSrvc.getContext();
d260 1
a260 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;
a95 9
    /**
     * Gets the project.
     */
    public Project getProject()
         throws Exception
    {
        return ProjectPeer.getInstance(Integer.toString(getProjectId()));
    }

d117 6
a122 6
        int proposedBy = acl.getUser().getUserId();
        dl.setProposedBy(proposedBy);
        int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                          proposedBy : 
                          UserPeer.getNobodyUser().getUserId());
        dl.setApprovedBy(approvedBy);
@


1.3
log
@Now using TurbineWebMacroService instead of TemplateInterpolator.
@
text
@d46 7
d56 1
a56 1
        "project/ProjectDisapprove.wm";
a65 6

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


1.2
log
@adding files from the branch to the head
@
text
@d15 2
d19 1
a19 1
import org.webmacro.engine.BuildContext;
d264 3
a266 1
        BuildContext ctx = TemplateInterpolator.createContext();
d270 1
a270 2
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
@


1.1
log
@file ProjectDownload.java was initially added on branch HELM_PEER_PORT_BRANCH.
@
text
@d1 356
@


1.1.1.1
log
@Replacing the HEAD with the HELM_PEER_PORT_BRANCH.
@
text
@a0 356
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.om.*;
import org.tigris.helm.om.peer.*;
import org.tigris.helm.om.base.*;
import org.tigris.helm.security.*;
import org.tigris.helm.tool.*;

/** 
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 */
public class ProjectDownload extends BaseProjectDownload
{
    /**
     * The buffer size used when computing the MD5 checksum of a file.
     */
    private static final int MD5_BUF_SIZE = 4096;

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

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

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

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

    /**
     * Gets user that proposed the download.
     *
     * @@return The proposing user.
     */
    public User getProposedByUser()
        throws Exception
    {
        return UserPeer.retrieveByPK(getProposedBy());
    }

    /**
     * Returns the primary database key.
     */
    public final String getID()
    {
        return String.valueOf(getDownloadId());
    }

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

    /**
     * Gets the project.
     */
    public Project getProject()
         throws Exception
    {
        return ProjectPeer.getInstance(Integer.toString(getProjectId()));
    }

    // 
    // Database methods
    //

    /**
     * Adds a new download.
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
     */
    public static ProjectDownload add(AccessControlList acl,
                                      Project project,
                                      String descrip, File f, String isPublic,
                                      String url)
        throws ACLException, Exception
    {
        ProjectDownload dl = new ProjectDownload();
        dl.setProjectId(project.getProjectId());
        dl.assertAddPermission(acl);

        int proposedBy = acl.getUser().getUserId();
        dl.setProposedBy(proposedBy);
        int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                          proposedBy : 
                          UserPeer.getNobodyUser().getUserId());
        dl.setApprovedBy(approvedBy);
        dl.setIsPublic(DBFlag.flagValueOf(isPublic));
        dl.setDescription(descrip);
        dl.setUploadedDate(new Date());

        if (f != null && f.exists()) {
            // Handle fields inferred from the File.
            dl.setFileName(f.getName());
            dl.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());
                }
            }
            catch (Exception e) {
                Log.error("Couldn't determine file MD5 checksum or " + 
                          "size: " + f.getAbsolutePath() + ": " +
                          e.getMessage());
            }

            if (size != -1) dl.setSize(size);
            dl.setMd5(md5Checksum);
            project.writeHtaccessFile(dl.getLocation(), url);
        }
        dl.save();
        return dl;
    }

    /**
     * Updates a download.
     * @@exception ACLException Insufficient permission.
     */
    public void edit(AccessControlList acl, String descrip,
                     User u, String isPublic, String dlURL)
        throws ACLException, Exception
    {
        assertEditPermission(acl);

        if (isPublic != null) setIsPublic(DBFlag.flagValueOf(isPublic));
        if (descrip != null) setDescription(descrip);
        save();
    }

    /**
     * Deletes this download.
     *
     * @@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
     *
     * @@exception ACLException Insufficient permission.
     */
    public void delete(AccessControlList acl, boolean fromFilesystem,
                       String htURL)
        throws ACLException, Exception
    {
        acl.assertPermission("Project Download - Delete", getProject());
        if (fromFilesystem) {
            File victim =
                new File(getLocation() + File.separatorChar + getFileName());
            if (victim.exists()) {
                victim.delete();
            }
            getProject().writeHtaccessFile(getLocation(), htURL);
        }
        delete();
    }

    /**
     * Performs a delete with no ACL checking.
     */
    private void delete()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDownloadPeer.DOWNLOAD_ID, getDownloadId());
        ProjectDownloadPeer.doDelete(c);
    }

    /**
     * Approves this download.
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void approve(AccessControlList acl)
        throws ACLException, Exception
    {
        if (acl != null) 
        {
            acl.assertPermission(APPROVE_PERM, getProject());
            setApprovedBy(acl.getUser().getUserId());
            save();
        }

    }

    /**
     * Disapproves this download.
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void disapprove(AccessControlList acl, String rationale,
                           String htURL)
        throws ACLException, Exception
    {
        if (acl == null) 
        {
            throw new Exception("No ACL provided.");
        }

        acl.assertPermission(APPROVE_PERM, getProject());

        String subject = "Download for Project " + getProject().getName() +
            " disapproved.";
        BuildContext ctx = TemplateInterpolator.createContext();
        ctx.put("disapprovingUser", acl.getUser());
        ctx.put("news", this);
        ctx.put("rationale", rationale);
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
        HelmEmailer emailer = new HelmEmailer();
        emailer.sendEmail(UserPeer.getInstance(String.valueOf(getProposedBy()))
                          .getEmail(), subject, body);
        delete(acl, true, htURL);
    }


    /**
     * 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 download.
     *
     * @@param acl The ACL to check for permission.
     */
    public void assertAddPermission(AccessControlList acl)
        throws ACLException, Exception
    {
        acl.assertPermission("Project Download - Suggest", getProject());
    }

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

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

    /**
     * Returns true if the given ACL can see this download.
     */
    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 Download - View";
        if ((!isApproved()) && (getProposedBy() != acl.getUser().getUserId()))
        {
            permission = "Project Download - 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 ProjectDownload extends BaseProjectDownload
{
}
@


1.1.2.2
log
@Ported add() method for Elicia.
@
text
@a2 1
import java.io.*;
a3 1
import java.security.MessageDigest;
a14 2
import org.tigris.helm.security.*;
import org.tigris.helm.tool.*;
a16 1
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
a19 95
    /**
     * The buffer size used when computing the MD5 checksum of a file.
     */
    private static final int MD5_BUF_SIZE = 4096;

    /**
     * The download suggestion permission.
     */
    private static final String SUGGEST_PERM = "Project Download - Suggest";

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

    /**
     * Adds a new download.
     */
    public static ProjectDownload add(AccessControlList acl, Project project,
                                      String descrip, File f, String isPublic,
                                      String url)
        throws ACLException, Exception
    {
        // To add a download you need either Suggest or Approve permission.
        if (acl.hasPermission(SUGGEST_PERM, project) ||
            acl.hasPermission(APPROVE_PERM, project))
        {
                ProjectDownload dl = new ProjectDownload();

                dl.setProjectId(project.getProjectId());
                int proposedBy = acl.getUser().getUserId();
                dl.setProposedBy(proposedBy);
                int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                                  proposedBy : 
                                  UserPeer.getNobodyUser().getUserId());
                dl.setApprovedBy(approvedBy);
                dl.setIsPublic(DBFlag.flagValueOf(isPublic));
                dl.setDescription(descrip);
                dl.setUploadedDate(new Date());

                if (f != null && f.exists()) {
                    // Handle fields inferred from the File.
                    dl.setFileName(f.getName());
                    dl.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());
                        }
                    }
                    catch (Exception e) {
                        Log.error("Couldn't determine file MD5 checksum or " + 
                                  "size: " + f.getAbsolutePath() + ": " +
                                  e.getMessage());
                    }

                    if (size != -1) dl.setSize(size);
                    dl.setMd5(md5Checksum);
                }

                return dl;
        }
        else {
            // Assert a permission we know they don't have to cause an
            // exception.
            acl.assertPermission(SUGGEST_PERM, project);
            return null;
        }
    }

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


1.1.2.3
log
@added isPublic() methods
@
text
@a110 10
     * Checks whether a publicly accessible download.
     *
     * @@return Whether public download.
     */
    public boolean isPublic()
    {
	    return DBFlag.booleanValueOf(getIsPublic());
    }

    /**
@


1.1.2.4
log
@Made isPublic() final.
@
text
@d115 1
a115 1
    public final boolean isPublic()
d117 1
a117 1
        return DBFlag.booleanValueOf(getIsPublic());
@


1.1.2.5
log
@Added delete() method.
@
text
@a41 2
     *
     * @@param acl The ACL to check for permission.
a107 13
    }

    /**
     * Deletes this project.
     *
     * @@param acl The ACL to check for permission.
     */
    public void delete(AccessControlList acl)
        throws Exception
    {
        acl.assertPermission("Project Download - Delete",
                             ProjectPeer.retrieveByPK(getProjectId()));
        ProjectDownloadPeer.doDelete(this);
@


1.1.2.6
log
@added permission methods
@
text
@d31 1
a31 1
     * The download approval permission.
d33 1
a33 1
    private static final String APPROVE_PERM = "Project Download - Approve";
d36 1
a36 1
     * Determines whether a news item has been approved
d38 1
a38 28
    public boolean isApproved()
        throws Exception
    {
        return getApprovedBy() != UserPeer.getNobodyUser().getUserId();
    }

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

    /**
     * Gets the project.
     */
    public Project getProject()
         throws Exception
    {
        return ProjectPeer.getInstance(Integer.toString(getProjectId()));
    }

    // 
    // Database methods
    //
d50 5
a54 2
        ProjectDownload dl = new ProjectDownload();
        dl.assertAddPermission(acl);
d56 40
a95 31
        dl.setProjectId(project.getProjectId());
        int proposedBy = acl.getUser().getUserId();
        dl.setProposedBy(proposedBy);
        int approvedBy = (acl.hasPermission(APPROVE_PERM, project) ?
                          proposedBy : 
                          UserPeer.getNobodyUser().getUserId());
        dl.setApprovedBy(approvedBy);
        dl.setIsPublic(DBFlag.flagValueOf(isPublic));
        dl.setDescription(descrip);
        dl.setUploadedDate(new Date());

        if (f != null && f.exists()) {
            // Handle fields inferred from the File.
            dl.setFileName(f.getName());
            dl.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);
d97 3
a99 2
                    in.close();
                    md5Checksum = ByteToHex.transform(md5.digest());
a100 6
            }
            catch (Exception e) {
                Log.error("Couldn't determine file MD5 checksum or " + 
                          "size: " + f.getAbsolutePath() + ": " +
                          e.getMessage());
            }
d102 7
a108 2
            if (size != -1) dl.setSize(size);
            dl.setMd5(md5Checksum);
a109 2

        return dl;
d126 1
a126 1
     * Extracts the directory path to the file.
d128 1
a128 2
     * @@param f The file to extract path information from.
     * @@return  The extracted path information.
d130 1
a130 1
    public static final String extractLocation(File f)
d132 1
a132 1
        return f.getParentFile().getAbsolutePath();
a134 5

    //
    // Permission methods
    //

d136 1
a136 1
     * Asserts addition and/or approval permission for this download.
d138 2
a139 1
     * @@param acl The ACL to check for permission.
d141 1
a141 2
    public void assertAddPermission(AccessControlList acl)
        throws ACLException, Exception
d143 1
a143 17
        acl.assertPermission("Project Download - Suggest", getProject());
    }

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

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

    /**
     * Returns true if the given ACL can see this download.
     */
    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 Download - View";
        if ((!isApproved()) && (getProposedBy() != acl.getUser().getUserId()))
        {
            permission = "Project Download - Approve";
        }
        return permission;
    }

@


1.1.2.7
log
@Ported file deletion capabilities to delete() method.
@
text
@a15 4
import org.webmacro.servlet.WebContext;

import org.joist.util.URL;

d132 1
a132 3
     * @@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
d134 1
a134 2
    public void delete(AccessControlList acl, boolean fromFilesystem,
                       WebContext ctx)
d137 2
a138 12
        Project project = ProjectPeer.retrieveByPK(getProjectId());
        acl.assertPermission("Project Download - 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);
        }
@


1.1.2.8
log
@Prefer parens to denote evaluation.
@
text
@d45 1
a45 1
        return (getApprovedBy() != UserPeer.getNobodyUser().getUserId());
@


1.1.2.9
log
@minor comments change
@
text
@a19 1
import org.tigris.helm.om.*;
d134 1
a134 1
     * Deletes this download.
@


1.1.2.10
log
@added getProposedByUser method

added save statement to add method
@
text
@a49 9
     * Gets user that proposed the download.
     */
    public User getProposedByUser()
        throws Exception
    {
        return UserPeer.retrieveByPK(getProposedBy());
    }

    /**
d77 1
a77 2
    public static ProjectDownload add(AccessControlList acl,
                                      Project project,
a82 1
        dl.setProjectId(project.getProjectId());
d85 1
a128 1
            project.writeHtaccessFile(dl.getLocation(), url);
d130 1
a130 1
        dl.save();
@


1.1.2.11
log
@Added new imports necessitated by Torque.
@
text
@a21 1
import org.tigris.helm.om.base.*;
@


1.1.2.12
log
@added approve and disapprove methods
@
text
@a16 1
import org.webmacro.engine.BuildContext;
a41 7
     * The name of the template used to create the body of the document 
     * disapproval email.
     */
    private static final String DISAPPROVE_TMPL = "project/ProjectDisapprove.wm";


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

    /**
a169 50
    }

    /**
     * Approves this news item.
     */
    public void approve(AccessControlList acl)
        throws ACLException, Exception
    {
        if (acl != null) 
        {
            acl.assertPermission(APPROVE_PERM, getProject());
            setApprovedBy(acl.getUser().getUserId());
            save();
        }

    }

    /**
     * Disapproves this news item.
     */
    public void disapprove(AccessControlList acl, String rationale)
        throws ACLException, Exception
    {
        if (acl == null) 
        {
            throw new Exception("No ACL provided.");
        }

        acl.assertPermission(APPROVE_PERM, getProject());

        String subject = "Download for Project " + getProject().getName() +
            " disapproved.";
        BuildContext ctx = TemplateInterpolator.createContext();
        ctx.put("disapprovingUser", acl.getUser());
        ctx.put("news", this);
        ctx.put("rationale", rationale);
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
        HelmEmailer emailer = new HelmEmailer();
        emailer.sendEmail(UserPeer.getInstance(String.valueOf(getProposedBy()))
                          .getEmail(), subject, body);
        deleteNC();
    }

    private void deleteNC()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDownloadPeer.DOWNLOAD_ID, getDownloadId());
        NewsItemPeer.doDelete(c);
@


1.1.2.13
log
@Corrected servlet URL.
@
text
@d180 1
a180 1
                "/servlets/ProjectDownloadList";
@


1.1.2.14
log
@Added JavaDoc.
@
text
@a99 2
     *
     * @@exception ACLException Insufficient permission.
a165 2
     *
     * @@exception ACLException Insufficient permission.
d169 1
a169 1
        throws ACLException, Exception
a187 4
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
a202 4
     *
     * @@param acl The ACL to check for permission.
     *
     * @@exception ACLException Insufficient permission.
@


1.1.2.15
log
@Broke long line.
@
text
@d46 2
a47 2
    private static final String DISAPPROVE_TMPL =
        "project/ProjectDisapprove.wm";
@


1.1.2.16
log
@Renamed deleteNc() to delete().
@
text
@d237 1
a237 1
        delete();
d240 1
a240 1
    private void delete()
@


1.1.2.17
log
@* Added a edit() stub (non-functional).
* Corrected delete().
* Added JavaDoc.
@
text
@a65 2
     *
     * @@return The proposing user.
a162 25
     * Updates a download.
     * <p>
     * WARNING: Non-functional, just here to compile against.
     *
     * @@exception ACLException Insufficient permission.
     */
    public void edit(AccessControlList acl, String descrip, User u,
                     String isPublic, String dlURL)
        throws ACLException, Exception
    {
        assertEditPermission(acl);

        /* TODO: FIXME
        if (isPublic != null) setIsPublic(DBFlag.flagValueOf(isPublic));
        if (descrip != null) setDescription(descrip);
        setUploadedDate(new Date());
        if (f != null && f.exists()) {
           uploadFile(f, dlURL);
        }
        */

        save();
    }

    /**
d175 2
a176 1
        acl.assertPermission("Project Download - Delete", getProject());
d185 1
a185 1
            getProject().writeHtaccessFile(getLocation(), htURL);
a239 3
    /**
     * Performs a delete with no ACL checking.
     */
d329 1
@


1.1.2.18
log
@Added getID() method.
@
text
@a75 8
     * Returns the primary database key.
     */
    public final String getID()
    {
        return String.valueOf(getDownloadId());
    }

    /**
@


1.1.2.19
log
@fixed edit method. added disapprove method.
@
text
@d50 1
a50 1
     * Determines whether a download has been approved
d174 3
d179 2
a180 2
    public void edit(AccessControlList acl, String descrip,
                     User u, String isPublic, String dlURL)
d185 1
d188 6
d225 1
a225 12
     * Performs a delete with no ACL checking.
     */
    private void delete()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(ProjectDownloadPeer.DOWNLOAD_ID, getDownloadId());
        NewsItemPeer.doDelete(c);
    }

    /**
     * Approves this download.
d244 1
a244 1
     * Disapproves this download.
d274 10
@


1.1.2.20
log
@made disapprove method functional
@
text
@d197 1
a197 1
                       String htURL)
d207 2
d211 1
a211 1
        delete();
d222 1
a222 1
        ProjectDownloadPeer.doDelete(c);
d251 1
a251 2
    public void disapprove(AccessControlList acl, String rationale,
                           String htURL)
d272 1
a272 1
        delete(acl, true, htURL);
@


