head	1.141;
access;
symbols
	TIGRIS_0_9_2_4:1.123.2.3
	TIGRIS_0_9_2_3:1.123.2.2
	HELM_PEER_PORT_BRANCH:1.133.0.2
	TURBINE_PEER:1.133
	TIGRIS_0_9_2_1:1.133
	TIGRIS_0_9_2:1.123.0.2
	TIGRIS_0_9_0:1.96.0.2
	TIGRIS_0_8_4:1.71.0.2
	NEWHELM:1.1.1.1
	TIGRIS_NOV_12_2000:1.1.1;
locks; strict;
comment	@# @;


1.141
date	2001.02.21.03.23.57;	author edk;	state dead;
branches;
next	1.140;

1.140
date	2001.02.13.17.02.36;	author jrobbins;	state Exp;
branches;
next	1.139;

1.139
date	2001.02.08.02.38.38;	author elicia;	state Exp;
branches;
next	1.138;

1.138
date	2001.02.06.21.37.33;	author elicia;	state Exp;
branches;
next	1.137;

1.137
date	2001.02.06.19.57.35;	author elicia;	state Exp;
branches;
next	1.136;

1.136
date	2001.02.01.00.29.13;	author elicia;	state Exp;
branches;
next	1.135;

1.135
date	2001.01.30.02.37.26;	author elicia;	state Exp;
branches;
next	1.134;

1.134
date	2001.01.29.23.54.39;	author leonardr;	state Exp;
branches;
next	1.133;

1.133
date	2001.01.27.02.34.46;	author elicia;	state Exp;
branches
	1.133.2.1;
next	1.132;

1.132
date	2001.01.26.18.29.04;	author edk;	state Exp;
branches;
next	1.131;

1.131
date	2001.01.26.05.24.06;	author edk;	state dead;
branches;
next	1.130;

1.130
date	2001.01.25.01.42.37;	author lucas;	state Exp;
branches;
next	1.129;

1.129
date	2001.01.24.23.06.05;	author leonardr;	state Exp;
branches;
next	1.128;

1.128
date	2001.01.24.21.41.49;	author leonardr;	state Exp;
branches;
next	1.127;

1.127
date	2001.01.24.20.42.49;	author dlr;	state Exp;
branches;
next	1.126;

1.126
date	2001.01.23.02.21.10;	author elicia;	state Exp;
branches;
next	1.125;

1.125
date	2001.01.22.22.45.12;	author leonardr;	state Exp;
branches;
next	1.124;

1.124
date	2001.01.19.06.43.28;	author leonardr;	state Exp;
branches;
next	1.123;

1.123
date	2001.01.17.23.22.18;	author dlr;	state Exp;
branches
	1.123.2.1;
next	1.122;

1.122
date	2001.01.17.22.07.33;	author leonardr;	state Exp;
branches;
next	1.121;

1.121
date	2001.01.17.18.36.19;	author leonardr;	state Exp;
branches;
next	1.120;

1.120
date	2001.01.17.18.25.06;	author elicia;	state Exp;
branches;
next	1.119;

1.119
date	2001.01.17.03.19.26;	author dlr;	state Exp;
branches;
next	1.118;

1.118
date	2001.01.17.01.01.39;	author leonardr;	state Exp;
branches;
next	1.117;

1.117
date	2001.01.16.23.06.16;	author elicia;	state Exp;
branches;
next	1.116;

1.116
date	2001.01.16.21.36.19;	author leonardr;	state Exp;
branches;
next	1.115;

1.115
date	2001.01.16.20.06.01;	author leonardr;	state Exp;
branches;
next	1.114;

1.114
date	2001.01.12.22.55.55;	author elicia;	state Exp;
branches;
next	1.113;

1.113
date	2001.01.12.22.09.55;	author elicia;	state Exp;
branches;
next	1.112;

1.112
date	2001.01.12.18.48.23;	author leonardr;	state Exp;
branches;
next	1.111;

1.111
date	2001.01.09.19.03.59;	author leonardr;	state Exp;
branches;
next	1.110;

1.110
date	2001.01.09.17.15.10;	author leonardr;	state Exp;
branches;
next	1.109;

1.109
date	2001.01.05.21.42.38;	author leonardr;	state Exp;
branches;
next	1.108;

1.108
date	2001.01.05.00.13.13;	author kmaples;	state Exp;
branches;
next	1.107;

1.107
date	2001.01.03.00.37.50;	author dlr;	state Exp;
branches;
next	1.106;

1.106
date	2001.01.02.18.30.49;	author leonardr;	state Exp;
branches;
next	1.105;

1.105
date	2000.12.30.05.00.45;	author elicia;	state Exp;
branches;
next	1.104;

1.104
date	2000.12.29.21.36.10;	author dlr;	state Exp;
branches;
next	1.103;

1.103
date	2000.12.29.19.56.50;	author dlr;	state Exp;
branches;
next	1.102;

1.102
date	2000.12.29.17.11.53;	author leonardr;	state Exp;
branches;
next	1.101;

1.101
date	2000.12.29.02.41.14;	author dlr;	state Exp;
branches;
next	1.100;

1.100
date	2000.12.27.01.35.47;	author elicia;	state Exp;
branches;
next	1.99;

1.99
date	2000.12.26.20.00.08;	author dlr;	state Exp;
branches;
next	1.98;

1.98
date	2000.12.23.00.48.18;	author dlr;	state Exp;
branches;
next	1.97;

1.97
date	2000.12.22.03.02.43;	author dlr;	state Exp;
branches;
next	1.96;

1.96
date	2000.12.19.02.25.52;	author elicia;	state Exp;
branches;
next	1.95;

1.95
date	2000.12.19.00.51.32;	author leonardr;	state Exp;
branches;
next	1.94;

1.94
date	2000.12.18.17.41.46;	author leonardr;	state Exp;
branches;
next	1.93;

1.93
date	2000.12.15.01.15.41;	author elicia;	state Exp;
branches;
next	1.92;

1.92
date	2000.12.14.23.46.02;	author dlr;	state Exp;
branches;
next	1.91;

1.91
date	2000.12.14.23.43.18;	author dlr;	state Exp;
branches;
next	1.90;

1.90
date	2000.12.14.18.19.27;	author leonardr;	state Exp;
branches;
next	1.89;

1.89
date	2000.12.14.04.03.03;	author edk;	state Exp;
branches;
next	1.88;

1.88
date	2000.12.14.03.04.17;	author edk;	state Exp;
branches;
next	1.87;

1.87
date	2000.12.14.02.28.47;	author edk;	state Exp;
branches;
next	1.86;

1.86
date	2000.12.14.00.30.55;	author dlr;	state Exp;
branches;
next	1.85;

1.85
date	2000.12.13.02.57.37;	author leonardr;	state Exp;
branches;
next	1.84;

1.84
date	2000.12.13.01.32.42;	author dlr;	state Exp;
branches;
next	1.83;

1.83
date	2000.12.12.20.04.34;	author dlr;	state Exp;
branches;
next	1.82;

1.82
date	2000.12.09.02.55.11;	author edk;	state Exp;
branches;
next	1.81;

1.81
date	2000.12.08.01.01.41;	author kmaples;	state Exp;
branches;
next	1.80;

1.80
date	2000.12.07.22.27.24;	author leonardr;	state Exp;
branches;
next	1.79;

1.79
date	2000.12.06.18.31.16;	author dlr;	state Exp;
branches;
next	1.78;

1.78
date	2000.12.06.01.17.05;	author leonardr;	state Exp;
branches;
next	1.77;

1.77
date	2000.12.05.23.53.30;	author leonardr;	state Exp;
branches;
next	1.76;

1.76
date	2000.12.05.23.28.59;	author leonardr;	state Exp;
branches;
next	1.75;

1.75
date	2000.12.05.22.09.42;	author leonardr;	state Exp;
branches;
next	1.74;

1.74
date	2000.12.05.02.19.10;	author leonardr;	state Exp;
branches;
next	1.73;

1.73
date	2000.12.05.00.25.57;	author dlr;	state Exp;
branches;
next	1.72;

1.72
date	2000.12.04.20.01.42;	author leonardr;	state Exp;
branches;
next	1.71;

1.71
date	2000.12.04.04.25.52;	author edk;	state Exp;
branches
	1.71.2.1;
next	1.70;

1.70
date	2000.12.02.01.45.41;	author leonardr;	state Exp;
branches;
next	1.69;

1.69
date	2000.12.01.19.06.47;	author edk;	state Exp;
branches;
next	1.68;

1.68
date	2000.12.01.13.21.50;	author edk;	state Exp;
branches;
next	1.67;

1.67
date	2000.12.01.06.13.46;	author edk;	state Exp;
branches;
next	1.66;

1.66
date	2000.11.30.23.56.41;	author leonardr;	state Exp;
branches;
next	1.65;

1.65
date	2000.11.30.13.03.22;	author edk;	state Exp;
branches;
next	1.64;

1.64
date	2000.11.30.05.08.43;	author edk;	state Exp;
branches;
next	1.63;

1.63
date	2000.11.30.00.46.40;	author leonardr;	state Exp;
branches;
next	1.62;

1.62
date	2000.11.29.21.30.18;	author elicia;	state Exp;
branches;
next	1.61;

1.61
date	2000.11.29.21.10.26;	author edk;	state Exp;
branches;
next	1.60;

1.60
date	2000.11.29.19.59.34;	author leonardr;	state Exp;
branches;
next	1.59;

1.59
date	2000.11.29.01.20.56;	author elicia;	state Exp;
branches;
next	1.58;

1.58
date	2000.11.28.20.10.16;	author leonardr;	state Exp;
branches;
next	1.57;

1.57
date	2000.11.28.19.57.14;	author leonardr;	state Exp;
branches;
next	1.56;

1.56
date	2000.11.27.20.04.12;	author dlr;	state Exp;
branches;
next	1.55;

1.55
date	2000.11.23.11.11.16;	author dlr;	state Exp;
branches;
next	1.54;

1.54
date	2000.11.23.08.25.51;	author dlr;	state Exp;
branches;
next	1.53;

1.53
date	2000.11.23.06.25.58;	author dlr;	state Exp;
branches;
next	1.52;

1.52
date	2000.11.23.06.19.09;	author dlr;	state Exp;
branches;
next	1.51;

1.51
date	2000.11.23.04.07.59;	author elicia;	state Exp;
branches;
next	1.50;

1.50
date	2000.11.22.23.49.43;	author brian;	state Exp;
branches;
next	1.49;

1.49
date	2000.11.22.17.22.23;	author leonardr;	state Exp;
branches;
next	1.48;

1.48
date	2000.11.22.03.49.53;	author dlr;	state Exp;
branches;
next	1.47;

1.47
date	2000.11.22.03.43.50;	author dlr;	state Exp;
branches;
next	1.46;

1.46
date	2000.11.22.03.27.35;	author elicia;	state Exp;
branches;
next	1.45;

1.45
date	2000.11.22.02.28.52;	author elicia;	state Exp;
branches;
next	1.44;

1.44
date	2000.11.22.02.17.59;	author elicia;	state Exp;
branches;
next	1.43;

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

1.42
date	2000.11.21.23.32.49;	author leonardr;	state Exp;
branches;
next	1.41;

1.41
date	2000.11.21.02.42.07;	author dlr;	state Exp;
branches;
next	1.40;

1.40
date	2000.11.20.23.52.35;	author dlr;	state Exp;
branches;
next	1.39;

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

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

1.37
date	2000.11.20.20.07.33;	author leonardr;	state Exp;
branches;
next	1.36;

1.36
date	2000.11.20.19.59.12;	author dlr;	state Exp;
branches;
next	1.35;

1.35
date	2000.11.20.09.56.44;	author dlr;	state Exp;
branches;
next	1.34;

1.34
date	2000.11.19.21.57.20;	author dlr;	state Exp;
branches;
next	1.33;

1.33
date	2000.11.19.21.09.31;	author dlr;	state Exp;
branches;
next	1.32;

1.32
date	2000.11.19.07.15.06;	author dlr;	state Exp;
branches;
next	1.31;

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

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

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

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

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

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

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

1.24
date	2000.11.17.19.49.13;	author leonardr;	state Exp;
branches;
next	1.23;

1.23
date	2000.11.17.18.44.32;	author leonardr;	state Exp;
branches;
next	1.22;

1.22
date	2000.11.17.05.45.54;	author edk;	state Exp;
branches;
next	1.21;

1.21
date	2000.11.17.02.18.31;	author leonardr;	state Exp;
branches;
next	1.20;

1.20
date	2000.11.17.00.29.21;	author leonardr;	state Exp;
branches;
next	1.19;

1.19
date	2000.11.16.00.25.08;	author leonardr;	state Exp;
branches;
next	1.18;

1.18
date	2000.11.16.00.09.52;	author leonardr;	state Exp;
branches;
next	1.17;

1.17
date	2000.11.15.18.49.05;	author leonardr;	state Exp;
branches;
next	1.16;

1.16
date	2000.11.15.15.00.04;	author edk;	state Exp;
branches;
next	1.15;

1.15
date	2000.11.15.11.24.41;	author edk;	state Exp;
branches;
next	1.14;

1.14
date	2000.11.15.00.36.47;	author dlr;	state Exp;
branches;
next	1.13;

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

1.12
date	2000.11.14.23.09.00;	author elicia;	state Exp;
branches;
next	1.11;

1.11
date	2000.11.14.18.30.07;	author stack;	state Exp;
branches;
next	1.10;

1.10
date	2000.11.14.03.53.04;	author dlr;	state Exp;
branches;
next	1.9;

1.9
date	2000.11.14.02.08.40;	author stack;	state Exp;
branches;
next	1.8;

1.8
date	2000.11.14.00.59.16;	author leonardr;	state Exp;
branches;
next	1.7;

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

1.6
date	2000.11.13.23.54.24;	author elicia;	state Exp;
branches;
next	1.5;

1.5
date	2000.11.13.22.39.52;	author leonardr;	state Exp;
branches;
next	1.4;

1.4
date	2000.11.13.21.15.02;	author edk;	state Exp;
branches;
next	1.3;

1.3
date	2000.11.13.19.18.49;	author leonardr;	state Exp;
branches;
next	1.2;

1.2
date	2000.11.13.17.35.17;	author leonardr;	state Exp;
branches;
next	1.1;

1.1
date	2000.11.12.21.15.55;	author dlr;	state Exp;
branches
	1.1.1.1;
next	;

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

1.71.2.1
date	2000.12.05.06.34.17;	author jrobbins;	state Exp;
branches;
next	1.71.2.2;

1.71.2.2
date	2000.12.09.06.46.37;	author edk;	state Exp;
branches;
next	;

1.123.2.1
date	2001.01.27.00.11.39;	author stack;	state Exp;
branches;
next	1.123.2.2;

1.123.2.2
date	2001.01.30.00.36.20;	author leonardr;	state Exp;
branches;
next	1.123.2.3;

1.123.2.3
date	2001.02.01.18.49.24;	author jrobbins;	state Exp;
branches;
next	;

1.133.2.1
date	2001.01.28.01.02.18;	author dlr;	state dead;
branches;
next	;


desc
@@


1.141
log
@delete stuff from the head which is obsolete in the branch (more changes
are still needed for a clean compile)
@
text
@/* ================================================================
 * Copyright (c) 2000 CollabNet.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if
 * any, must include the following acknowlegement: "This product includes
 * software developed by CollabNet (http://www.collab.net/)."
 * Alternately, this acknowlegement may appear in the software itself, if
 * and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The hosted project names must not be used to endorse or promote
 * products derived from this software without prior written
 * permission. For written permission, please contact info@@collab.net.
 * 
 * 5. Products derived from this software may not use the "Tigris" name
 * nor may "Tigris" appear in their names without prior written
 * permission of CollabNet.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by many
 * individuals on behalf of CollabNet.
 */

package org.tigris.helm.project;

import java.math.BigInteger;
import java.io.*;
import java.util.*;
import java.text.*;
import java.util.Date;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.*;

import gnu.regexp.*;

import org.webmacro.util.Log;
import org.webmacro.servlet.*;
import org.webmacro.engine.BuildContext;

import com.workingdogs.village.*;

import org.joist.JoistException;
import org.joist.util.URL;
import org.joist.util.JoistProperties;
import org.joist.database.*;

import org.tigris.helm.*;
import org.tigris.helm.business.*;
import org.tigris.helm.database.*;
import org.tigris.helm.domain.*;
import org.tigris.helm.security.*;
import org.tigris.helm.tool.mail.MailingList;
import org.tigris.helm.tool.*;
import org.tigris.helm.tool.paginate.*;

public class Project extends BusinessObject implements Comparable
{
    /**
     * The default project name.
     */
    public static final String DEFAULT_NAME = "www";

    /**
     * The query string parameter name of a servlet display message.
     */
    public static final String MESSAGE = "msg";

    private static final boolean debug = true;

    private static Log log = new Log("proj", "Project");

    protected final String getTableName()
    {
        return ProjectManager.TABLE_NAME;
    }

    /**
     * The regular expression used to check project names for validity.
     */
    private static final String PROJECT_NAME_RE =
        "^[a-zA-Z0-9][-a-zA-Z0-9]{0,63}$";

    /**
     * The name of the file containing the project's main screen.
     */
    private static final String INDEX_FILE = "index.html";

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

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

    /**
     * A mutex for the addition of new projects.
     */
    private static Object addLock = new Object();

    /**
     * A hash of mutex objects for handling file write locking to .htaccess 
     * files (keyed by file name).
     */
    private static HashMap htaccessLocks = new HashMap();

    protected UserManager uMgr;
    protected UserUserGroupManager usrGrpMgr;
    protected ProjectManager pMgr;
    protected ProjectProjectGroupManager prjGrpMgr;
    protected UserRoleProjectManager urpMgr;
    protected DomainManager domMgr;
    protected ProjectDownloadManager dlMgr;
    protected ProjectNewsManager newsMgr;
    protected ProjectSectionManager secMgr;
    protected ProjectDocumentManager docMgr;
    protected ProjectDocumentSectionManager pdsMgr;
    protected RoleManager roleMgr;

    /**
     * The white bread version of the project word mark.
     */
    private String name;

    ////////////////////////////////////////////////////////////////////
    // Static methods.
    ////////////////////////////////////////////////////////////////////

    /**
     * Asserts that the specified project exists.
     *
     * @@param c        The JDBC connection to use.
     * @@param dMgr     The data manager to use.
     * @@param domainID The database kye of the domain that the project is in.
     * @@param name     The project name.
     *
     * @@exception AlreadyExists The project exists.
     */
    public static void assertNonexistance(Connection conn, DataManager dMgr, 
                                          String domainID, String name)
        throws DataSetException, SQLException, AlreadyExists
    {
        try
        {
            new Project(conn, dMgr, domainID, name);
        }
        catch (DoesNotExist success)
        {
            return;
        }
        throw new AlreadyExists("Project " + name, "in domain " + domainID);
    }

    /**
     * Checks whether a project name is valid.
     *
     * @@param name The project name to check.
     * @@return     Whether the name is valid.
     *
     * @@exception REException Malformed regular expression.
     */
    public static boolean isValidName (String name)
    {
        boolean isValid = false;

        if (name != null && name.length() > 0)
        {
            RE projectRE = null;
            try
            {
                projectRE= new RE(PROJECT_NAME_RE);
                isValid = projectRE.isMatch(name);
            }
            catch (REException e)
            {
                log.exception(e);
            }
        }

        return isValid;
    }

    /**
     * Macro which encapsulates transformation of a word mark to a
     * canonical name.
     */
    private static final String getName (String wordMark)
    {
        return wordMark.toLowerCase();
    }


    ////////////////////////////////////////////////////////////////////
    // Constructors.
    ////////////////////////////////////////////////////////////////////

    public Project (Connection conn, DataManager dMgr)
    {
        super(conn, dMgr);
    }

    public Project (Connection conn, DataManager dMgr, Record rec)
        throws DoesNotExist, DataSetException
    {
        super(conn, dMgr, rec);
    }

    /**
     * Constructor for a project which already exists -- accessed by
     * projectID.
     */
    public Project (Connection conn, DataManager dMgr, String projectID)
        throws SQLException, DataSetException, DoesNotExist
    {
        super(conn, dMgr);
        setRecord(pMgr.getProjectForID(conn, projectID));
    }

    /**
     * Constructor for a project which already exists -- accessed by
     * domainID and project name.
     */
     public Project (Connection c, DataManager dMgr, String domainID,
                     String name)
         throws SQLException, DataSetException, DoesNotExist
    {
        super(c, dMgr);
        setRecord(pMgr.getProjectForName(c, domainID, name));
    }

    /**
     * Constructor for a project which already exists -- accessed by
     * domainID and alias URL.
     */
    public Project (Connection c, DataManager dMgr, String domainID, 
                    String aliasURL, boolean ignore)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        super(c, dMgr);
        setRecord(pMgr.getProjectForAliasURL(c, domainID, aliasURL));
    }

    /**
     * Constructor for a new project.
     *
     * @@param wordMark The stylized name of the project.
     */
    public Project(Connection c, DataManager dMgr, AccessControlList acl,
                   ProjectProfile profile, String domainID, String wordMark, 
                   String license, 
                   String shortDescription, String longDescription, 
                   String useIndex, String status, String aliasURL,  
                   String proposedBy, String projectOwner)
        throws SQLException, DataSetException, JoistDatabaseException,
               AlreadyExists, UpdateException, ACLException, DoesNotExist,
               JoistException
    {
        super(c, dMgr);

        if (!acl.hasPermissionForDomain("Project - Suggest", domainID) &&
            !acl.hasPermissionForDomain("Project - Add", domainID))
        {
            throw new ACLException(acl, "Project - Suggest or Project - Add", 
                                   "Domain " + domainID, null);
        }

        String domainName;
        synchronized (addLock)
        {
            Project.assertNonexistance(conn, dMgr, domainID, wordMark);

            // Add the project to the database.
            String approvedBy = usrGrpMgr.getNobodyUserID(c);
            setRecord(pMgr.addProject(conn, profile, domainID, wordMark, 
                                      license, shortDescription, 
                                      longDescription, useIndex, "", aliasURL,
                                      proposedBy, approvedBy));

            domainName = domMgr.getDomainName(domainID);
        }

        // Add the project to CVS, Issuezilla, etc.
        runCreationScripts(acl.getUserID());
        
        //Give someone Project Owner role on this project.
        //
        //If the ACL has Project Approve permission, make
        //the owner whomever they designate.
        //
        //Otherwise, make the ACL's user the owner.        
        //Also -- store the User so we have an e-mail address to use
        //as owner of the mailing lists.
        User   newOwner   = null;
        String newOwnerID = null;
        if (projectOwner == null ||
            !acl.hasPermissionForDomain("Project - Approve", domainID))
        {
            newOwnerID = acl.getUserID();
            newOwner   = User.getInstance(conn, dMgr, newOwnerID);
        } else {
            if (debug) log.info("domainID=" + domainID);
            if (debug) log.info("projectOwner=" + projectOwner);
            newOwner   = new User(conn, dMgr, domainID, projectOwner);
            newOwnerID = newOwner.getID();
        }

        // HELP: special user for system-approved roles?
        String rootUserID = uMgr.getUserForLoginID(conn, "root")
            .getValue(UserManager.USER_ID).asString();
        urpMgr.grantNamedRole(conn, newOwnerID, "Project Owner", 
                              getID(), rootUserID);

        String name = getName(wordMark);
        AnzuTigrisTask.addProject(conn, dMgr, newOwnerID, domainID, name);
        AnzuTigrisTask.setOwnerAlias(conn, dMgr, newOwnerID, getID(), false);

        //Add the project to the appropriate groups.
        ProjectGroup.addToHostGroup(conn, dMgr, this);
        ProjectGroup.addToDomainGroup(conn, dMgr, this, getDomainID());

        //Approve the project, if user has the right permission.
        if (acl.hasPermissionForDomain("Project - Approve", domainID))
        {
            approve(acl);
        } else {
            //Send a message to the domain admin(s) informing them of
            //the newly requested project.
            User createdUser = User.getInstance(conn, dMgr, acl.getUserID());
            Role role = new Role(conn, dMgr, "Domain Admin", false);
            Domain domain = new Domain(conn, dMgr, domainID);
            String subject = "New unapproved project: " + wordMark;            
            BuildContext ctx = TemplateInterpolator.createContext();
            ctx.put("project", this);
            ctx.put("createdUser", createdUser);
            String body = TemplateInterpolator.interpolate(CREATED_TMPL, ctx, 
                                                           getClass());
            HelmEmailer emailer = new HelmEmailer(conn, dMgr);
            try 
            {
                emailer.messageUsersWithDomainRole(role, domain, subject, 
                                                   body);
            }
            catch (JoistException e)
            {
                log.info("Unable to mail domain admins about new project.");
            }
        }

        try
        {
            profile.addDefaultMailingLists(conn, dMgr, getID(), newOwner,
                                           Licenses.isProprietary(license));
        }
        catch (HandlerException e)
        {
            log.exception(e);
            if (debug) log.info("HandlerException adding default MLs: " +
                    e.getMessage());
            throw new UpdateException("HandlerException adding default MLs: " +
                    e.getMessage());
        }
    }

    /**
     * Helper method to run any scripts needed for the creation of the
     * project. It's public because the Tigris initialization task
     * needs to run it.
     */
    public void runCreationScripts(String initiatingUser)
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
    {
        for (Iterator i = expand().iterator(); i.hasNext();)
        {
            Project p = (Project)i.next();
            TigrisUpdate.addProject(conn, dMgr, initiatingUser, p);
            if (p.getProfile().isAutoPublishedToWeb())
            {
                TigrisUpdate.addModule(conn, dMgr, null, p, "www",
                                       "Web publishing module", "1");
            }
        }
    }

    protected void createManagers ()
    {
        this.dMgr = dMgr;
        this.uMgr = (UserManager)dMgr.getManager
            ("org.joist.database.UserManager");        
        this.pMgr = (ProjectManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectManager");
        this.prjGrpMgr = (ProjectProjectGroupManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectProjectGroupManager");
        this.usrGrpMgr = (UserUserGroupManager)dMgr.getManager
            ("org.tigris.helm.database.UserUserGroupManager");
        this.urpMgr = (UserRoleProjectManager)dMgr
            .getManager("org.tigris.helm.database.UserRoleProjectManager");
        this.domMgr = (DomainManager)dMgr
            .getManager("org.tigris.helm.database.DomainManager");
        this.dlMgr = (ProjectDownloadManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectDownloadManager");
        this.newsMgr = (ProjectNewsManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectNewsManager");
        this.roleMgr = (RoleManager)dMgr.getManager
            ("org.joist.database.RoleManager");
        this.secMgr = (ProjectSectionManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectSectionManager");
        this.docMgr = (ProjectDocumentManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectDocumentManager");
        this.pdsMgr = (ProjectDocumentSectionManager)dMgr.getManager
            ("org.tigris.helm.database.ProjectDocumentSectionManager");
    }


    ////////////////////////////////////////////////////////////////////
    // Writing functions.
    ////////////////////////////////////////////////////////////////////

    /**
     * Adds the project to a category.
     */
    public void addToCategory(Category cat)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        cat.addProject(this);
    }

    /**
     * Removes the project from a category.
     */
    public void removeFromCategory(Category cat)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        cat.removeProject(this);
    }

    public void addToGroup(AccessControlList acl, ProjectGroup g)
        throws SQLException, DataSetException, JoistDatabaseException,
               ACLException, DoesNotExist
    {
        g.addProject(acl, this);
    }

    public void removeFromGroup(AccessControlList acl, ProjectGroup g)
        throws SQLException, DataSetException, JoistDatabaseException,
               ACLException, DoesNotExist
    {
        g.removeProject(acl, this);
    }

    /**
     * Changes the project category--removes from all old categories
     * and adds to the new one.
     */
    public void changeCategory(Category newCat)
        throws DataSetException, SQLException, JoistDatabaseException,
               UpdateException, DoesNotExist
    {
        for (Iterator i = getCategories().iterator(); i.hasNext();)
        {
            removeFromCategory((Category)i.next());
        }
        //Add the project to the new category.
        addToCategory(newCat);
    }

    /**
     * Deletes the project.
     */
    public void delete(AccessControlList acl)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist, ACLException
    {
        if (isGroup())
            acl.assertPermissionForDomain("ProjectGroup - Delete", 
                                          getDomainID());
        else
            acl.assertPermissionForProject("Project - Delete", getID());
        DomainManager domMgr = (DomainManager)
            dMgr.getManager("org.tigris.helm.database.DomainManager");
        ProjectProjectGroupManager prjGrpMgr = (ProjectProjectGroupManager)
            dMgr.getManager
            ("org.tigris.helm.database.ProjectProjectGroupManager");

        // TODO: Delete this project's version controlled artifacts.

        List groups = getGroups();
        for (Iterator i = groups.iterator(); i.hasNext();)
        {
            ProjectGroup p = (ProjectGroup)i.next();
            if (debug) log.info("Removing project " + getWordMark() +
                                " from group " + p.getWordMark());
            p.removeProjectNoPerms(this);
        }

        //Remove all roles in the project.
        urpMgr.deleteRolesForProject(conn, getID());
        
        // delete the mailing lists
        Iterator mailingLists = getMailingLists().iterator();
        while (mailingLists.hasNext()) {
            MailingList ml = (MailingList) mailingLists.next();
            try {
                ml.delete();
            } catch (HandlerException e) {
                log.exception(e);
                if (debug) log.info("Unable to delete mailing list " +
                                    ml.getName() + " in project " +
                                    getWordMark() + ": " + e);
            }
        }

        // delete the directory in the anzu project as well
        AnzuTigrisTask.deleteProject(conn, dMgr, acl.getUserID(),
                getDomainID(), getName());

        //TODO: Remove all other references to it. (Downloads etc.)

        //TODO: Delete this project's download directory.

        //Delete the project itself, along with its CVS repository
        //and whatnot.
        pMgr.deleteProject(conn, getID());
        TigrisUpdate.deleteProject (conn, dMgr, acl.getUserID(), this);
    }

    /**
     * Approves the project.
     */
    public void approve(AccessControlList acl)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist, ACLException
    {
        String action = "Project - Approve";
        if (!acl.hasPermissionForProject(action, getID()))
        {
            return;
        }
        acl.assertPermissionForProject(action, getID());
        pMgr.approveProject(conn, getID(), acl.getUserID());
        //Add the project to the list of public projects, if it's not
        //proprietary.
        if (!isProprietary())
        {
            ProjectGroup.addToPublicGroup(conn, dMgr, this, getDomainID());
        }
    }

    /**
     * Sends email and deletes the project.
     */
    public void disapprove(AccessControlList acl)
        throws SQLException, DataSetException, JoistDatabaseException,
               JoistException, DoesNotExist, ACLException
    {
        String action = "Project - Delete";
        if (!acl.hasPermissionForProject(action, getID()))
        {
            return;
        }
        acl.assertPermissionForProject(action, getID());

        //Send email to the owners.
        User disapprovingUser = User.getInstance(conn, dMgr, acl.getUserID());
        String subject = "Project " + getWordMark() + " disapproved.";
        BuildContext ctx = TemplateInterpolator.createContext();
        ctx.put("project", this);
        ctx.put("disapprovingUser", disapprovingUser);
        String body = TemplateInterpolator.interpolate(DISAPPROVE_TMPL, ctx,
                                                       getClass());
        Role role = new Role(conn, dMgr, "Project Owner", false);
        HelmEmailer emailer = new HelmEmailer(conn, dMgr);
        try 
        {
            emailer.messageUsersWithProjectRole(role, this, subject, body);
        }
        catch (JoistException e)
        {
            log.info("Unable to mail project owner about project disapproval.");
        }
        delete(acl);
    }

    /**
     * Updates the project's information.
     */
    public void updateInfo(AccessControlList acl,
                           String license,
                           String shortDescription,
                           String longDescription,
                           String useIndex,
                           String status, 
                           String aliasURL
                           )
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist, UpdateException, ACLException
    {
        acl.assertPermissionForProject("Project - Edit", getID());
        if (isProprietary() != Licenses.isProprietary(license))
        {
            try {
                updateLicense(license);
            } catch (HandlerException e) {
                log.exception(e);
                if (debug) log.info("exception updating mailing list types " +
                        "for new project license: " + e.getMessage());
                throw new UpdateException("unable to update mailing list " +
                        "types for new license: " + e.getMessage());
            } catch (DoesNotExist e) {
                log.exception(e);
                if (debug) log.info("exception updating mailing list types " +
                        "for new project license: " + e.getMessage());
                throw new UpdateException("unable to update mailing list " +
                        "types for new license: " + e.getMessage());
            }
        }
        pMgr.updateProjectInfo(conn, getID(), license, shortDescription,
                               longDescription, DBFlag.flagValueOf(useIndex),
                               status, aliasURL);
    }

    /**
     * Handle switching mailing list types and any other items
     * which need to be flipped when the project goes from open
     * to proprietary or vice versa.
     *
     * @@param license the new license
     */
    private void updateLicense(String license)
        throws HandlerException, DataSetException, SQLException, DoesNotExist
    {
        boolean becomingProprietary = Licenses.isProprietary(license);
        log.exception("updateLicense -- isProprietary: " + becomingProprietary);
        Iterator mailingLists = getMailingLists().iterator();
        while (mailingLists.hasNext()) {
            MailingList list = (MailingList) mailingLists.next();
            String type = list.getType();
            if (becomingProprietary) {
                if (!type.endsWith("-private")) {
                    list.setType(type + "-private");
                    list.update();
                }
            } else {
                if (type.endsWith("-private")) {
                    list.setType(type.substring(0,
                                type.length() - "-private".length()));
                    list.update();
                }
            }
        }
    }

    /**
     * Clear the Issuezilla accounts and rebuild them according to
     * what's in the database.
     */
    public void rebuildIssueTracking(AccessControlList acl)
        throws ACLException, SQLException, DataSetException, 
               JoistDatabaseException, DoesNotExist
    {
        acl.assertPermissionForProject("Project Role - Grant", getID());

        List projects = new ArrayList();
        projects.addAll(expand());

        List users = null;
        if (isHost())
        {
            users = getHost().getAllSiteUsers();
        } else {
            users = getDomain().getUsers();
            users.addAll(getHost().getUsers());
        }

        //First, disable everybody in each project.
        for (Iterator i = projects.iterator(); i.hasNext();)
        {
            Project p = (Project)i.next();
            TigrisUpdate.disableAllAccounts(conn, dMgr, acl.getUser(), p);
        }
        IssueTrackingAccountDescriptor before = 
            new IssueTrackingAccountDescriptor();
        IssueTrackingAccountDescriptor after = 
            new IssueTrackingAccountDescriptor(projects,users);
        before.syncTo(conn, dMgr, after);
    }

    ////////////////////////////////////////////////////////////////////
    // Read-only functions.
    ////////////////////////////////////////////////////////////////////   

    public int compareTo(Object o)
        throws ClassCastException
    {
        Project p = (Project)o;
        int val = -1;
        try 
        {
            val = getName().compareTo(p.getName());
        } catch (DataSetException ignore) {}
        return val;
    }

    public boolean equals(Project p)
    {
        boolean val = false;
        try 
        {
            if (getID().equals(p.getID()))
            {
                val = true;
            }
        } catch (DataSetException ignore) {}
        return val;       
    }

    public ProjectGroup asGroup()
    throws DataSetException
    {
        ProjectGroup g = null;
        if (isGroup())           
        {
            try {
                g = new ProjectGroup(conn, dMgr, this.rec);
            } catch (DoesNotExist ignore) {}
        }
        return g;
    }

    public Category asCategory()
    throws DataSetException
    {
        Category c = null;
        if (isCategory())           
        {
            try {
                c = new Category(conn, dMgr, this.rec);
            } catch (DoesNotExist ignore) {}
        }
        return c;
    }

    /**
     * Returns a list of Projects represending all the projects
     * this project represents. If called on a base project, 
     * returns a list containing only itself.
     */    
    public List expand() 
	throws DataSetException, SQLException
    {
        List projects = null;
	if (isBase())
	{
	    projects = new ArrayList();
	    projects.add(this);
	} else {
	    projects = asGroup().expand();
	}
        return projects;
    }

    public String requiredRoleGrantAction()
        throws SQLException, DataSetException, JoistDatabaseException
    {
        // Determine necessary action, erring on the side of fascism.
        String requiredAction = "Host Role - Grant";
        String type = getType();
        if (type.equals(ProjectManager.HOST_PROJECT_TYPE))
        {
            //Taken care of above.
        } else if (type.equals(ProjectManager.DOMAIN_PROJECT_TYPE)) {
            requiredAction = "Domain Role - Grant";
        } else {
            if (isApproved())
            {
                requiredAction = "Project Role - Grant";
            } else {
                requiredAction = "Unapproved Project Role - Grant";
            }
        }
        return requiredAction;
    }

    /**
     * Returns a list of Categories to which this project belongs.
     */
    public List getCategories()
        throws DataSetException, SQLException, DoesNotExist
    {
        DataSet categorySet = 
            pMgr.getCategoriesForProject(conn, getID());
        ArrayList categories = new ArrayList();
        for (int i = 0; i < categorySet.size(); i++)
        {                    
            Record r = categorySet.getRecord(i);
            Category c = new Category(conn, dMgr, r);
            categories.add(c);
        }        
        return categories;
    }

    /**
     * Returns a list of ProjectGroups to which this project belongs.
     */
    public List getGroups()
        throws DataSetException, SQLException, DoesNotExist
    {
        DataSet groupSet = 
            prjGrpMgr.getGroupsForProject(conn, getID());
        ArrayList groups = new ArrayList();
        for (int i = 0; i < groupSet.size(); i++)
        {                    
            Record r = groupSet.getRecord(i);
            String projectID = r.getValue(ProjectProjectGroupManager.PROJECT_GROUP_ID).asString();
            ProjectGroup p = new ProjectGroup(conn, dMgr, projectID);
            groups.add(p);
        }        
        return groups;
    }

    public PaginatablePrebuiltList getUsers()
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
    {
        return getUsers(new Integer(0));
    }

    public PaginatablePrebuiltList getUsers(Integer itemsPerPage)
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
    {
        DataSet userSet = urpMgr.getUsersForProject(conn, 
                                                    getID(), 
                                                    Boolean.TRUE);
        ArrayList userList = new ArrayList();
        ArrayList userGroupList = new ArrayList();
        for (int i = 0; i < userSet.size(); i++)
        {                    
            Record r = userSet.getRecord(i);
            User u = new User(conn, dMgr, r);
            if (u.isGroup())
            {
                userGroupList.add(u);
            } else {
                userList.add(u);
            }
        }
        
        Collections.sort(userList);
        Collections.sort(userGroupList);
        userGroupList.addAll(userList);

        return new PaginatablePrebuiltList(itemsPerPage, userGroupList);
    }

    public List getRequestedUsers()
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
    {
        DataSet userSet = urpMgr.getUsersForProject(conn, 
                                                    getID(), Boolean.FALSE);
        ArrayList userList = new ArrayList();
        for (int i = 0; i < userSet.size(); i++)
        {                    
            Record r = userSet.getRecord(i);
            String userID = r.getStringValue("userID");
            User u = User.getInstance(conn, dMgr, userID);
            userList.add(u);
        }
        
        return userList;
    }


    public List getRequestedRoles()
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
    {
        DataSet roleSet = urpMgr.getRequestedRolesForProject(conn, 
                                                    getID());
        ArrayList roleList = new ArrayList();
        for (int i = 0; i < roleSet.size(); i++)
        {                    
            Record r = roleSet.getRecord(i);
            String roleID = r.getStringValue("role_id");
            Role role = new Role(conn, dMgr, roleID);
            roleList.add(role);
        }
        
        return roleList;
    }

    public List getOwners()
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
    {
        String roleID = roleMgr.getRoleID(conn, "Project Owner");
        DataSet ownerSet = urpMgr.getUsersForRoleProject(conn, roleID,
                                                         getID());
        ArrayList ownerList = new ArrayList();
        for (int i = 0; i < ownerSet.size(); i++)
        {                    
            String userID  = ownerSet.getRecord(i).
	           getValue(UserRoleProjectManager.USER_ID).toString();
            User user = User.getInstance(conn, dMgr, userID);
            ownerList.add(user);
        }
        
        return ownerList;
    }

    public List getMailingLists()
        throws DataSetException, SQLException, DoesNotExist
    {
	MailingListManager mlMgr = (MailingListManager)
	    dMgr.getManager("org.tigris.helm.database.MailingListManager");
        DataSet mailingListSet = mlMgr.listProjectMailingLists(conn, 
                                                               getID());

        ArrayList mailingLists = new ArrayList();
        for (int i = 0; i < mailingListSet.size(); i++)
        {                    
            Record r = mailingListSet.getRecord(i);
            MailingList m = new MailingList(conn, dMgr, r);
            mailingLists.add(m);
        }
        
        return mailingLists;
    }

    /**
     * Return the Skin for this project. If no Skin is specified for
     * this project, get the Skin for the domain, and if that fails,
     * get the Skin for the host.
     */
    public Skin getSkin()
        throws SQLException, DataSetException, DoesNotExist, 
               JoistDatabaseException
    {
        Skin s = Skin.getSkin(conn, dMgr, getSkinID());
        if (s == null)
        {
            s = Skin.getSkin(conn, dMgr, 
                             getDomain().getSpecialProject().getSkinID());
        }
        if (s == null)
        {
            s = Skin.getSkin(conn, dMgr, 
                             getHost().getSpecialProject().getSkinID());
        }
        return s;
    }

    /**
     * Return the ID corresponding to the skin used by this project.
     */
    public String getSkinID()
        throws DataSetException
    {
        return getField(ProjectManager.SKIN_ID);
    }

    /**
     * Returns the appropriate ProjectProfile subclass for a project
     * of this project's type.
     */
    public ProjectProfile getProfile()
        throws DataSetException
    {
        String name = getField(ProjectManager.PROJECT_PROFILE);
        ProjectProfile p = null;
        if (name.equals("development"))
        {
            p = new DevelopmentProfile();
        } else if (name.equals("discussion")) {
            p = new DiscussionProfile();
        } else if (name.equals("category")) {
            p = new CategoryProfile();
        } else if (name.equals("clone")) {
            p = new CloneProfile();
        }
        return p;
    }

    /**
     * Returns true if the project is that special project representing
     * all projects on the host.
     */
    public boolean isHost()
        throws DataSetException
    {
        String type = getType();
        return type.equals(ProjectManager.HOST_PROJECT_TYPE);
    }

    public boolean isDomain()
        throws DataSetException
    {
        String type = getType();
        return type.equals(ProjectManager.DOMAIN_PROJECT_TYPE);
    }

    public boolean isCategory()
        throws DataSetException
    {
        String type = getType();
        return type.equals(ProjectManager.CATEGORY_PROJECT_TYPE);
    }

    public boolean isGroup()
        throws DataSetException
    {
        String type = getType();
        return !(type.equals(ProjectManager.BASE_PROJECT_TYPE));
    }

    public boolean isBase()
        throws DataSetException
    {
        String type = getType();
        return type.equals(ProjectManager.BASE_PROJECT_TYPE);
    }

    public boolean isProprietary()
        throws DataSetException
    {
        return Licenses.isProprietary(getLicense());
    }

    public boolean isApproved()
        throws JoistDatabaseException, DataSetException, SQLException
    {
        return !getApprovedBy().equals(usrGrpMgr.getNobodyUserID(conn));
    }

    public List getDownloads ()
        throws DataSetException, SQLException, DoesNotExist
    {
        List downloads = new ArrayList();

        // Get all downloads for this project
        DataSet downloadSet = 
            dlMgr.getDownloadsForProject(conn, getID());
        Record r;
        for (int i = 0; i < downloadSet.size(); i++)
        {
            r = downloadSet.getRecord(i);
            downloads.add(new Download(conn, dMgr, r));
        }

        return downloads;
    }

    public List getUnapprovedDownloads()
       throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        List downloads = new ArrayList();
     
        DataSet downloadSet = dlMgr.getUnapprovedDownloadsForProject
                                   (conn, getID());

        Record r;
        for (int i = 0; i < downloadSet.size(); i++)
        {
            r = downloadSet.getRecord(i);
            Download download = new Download(conn, dMgr, r);
	        downloads.add(new Download(conn, dMgr, r));
        }

        return downloads;

    }

    public List getDocuments ()
        throws DataSetException, SQLException, DoesNotExist
    {
        List documents = new ArrayList();

        // Get all downloads for this project
        DataSet documentSet = 
            docMgr.getDocumentsForProject(conn, getID());
        Record r;
        for (int i = 0; i < documentSet.size(); i++)
        {
            r = documentSet.getRecord(i);
            documents.add(new Document(conn, dMgr, r));
        }

        return documents;
    }

    public PaginatableNewsItemList 
        getNews(Integer itemsPerPage, Criterion searchCriterion, AccessControlList acl)
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        String nobodyID = usrGrpMgr.getNobodyUserID(conn);

        PaginatableNewsItemList n = null;
        String query = newsMgr.getNewsForProjectQuery(conn, getID());
        n = new PaginatableNewsItemList(conn, dMgr, itemsPerPage, query, 
                                        searchCriterion, acl);
        return n;
    }

    public PaginatableNewsItemList getNews(AccessControlList acl)
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        return getNews(new Integer(0), null, acl);
    }

    public PaginatableNewsItemList getUnapprovedNews
        (Integer itemsPerPage, Criterion searchCriterion, AccessControlList acl)
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        PaginatableNewsItemList n = null;
        String query = newsMgr.getUnapprovedNewsForProjectQuery(conn, getID());
        n = new PaginatableNewsItemList(conn, dMgr, itemsPerPage, query, 
                                    searchCriterion, acl);
        return n;
    }

    public PaginatableNewsItemList getUnapprovedNews(AccessControlList acl)
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        return getUnapprovedNews(new Integer(0), null, acl);
    }

    ////////////////////////////////////////////////////////////////////
    // Field accessor functions.
    ////////////////////////////////////////////////////////////////////

    public String getID()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_ID).asString();
    }

    public Domain getDomain()
        throws DataSetException, SQLException, JoistDatabaseException, DoesNotExist
    {
        return new Domain(conn, dMgr, getDomainID());
    }

    public Host getHost()
        throws DataSetException, SQLException, JoistDatabaseException, DoesNotExist
    {
        return getDomain().getHost();
    }
    
    public String getDomainID()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_DOMAIN_ID).asString();
    }

    public String getDomainName()
        throws DataSetException, SQLException, JoistDatabaseException
    {
        return domMgr.getDomainName(getDomainID());
    }

    /**
     * For future use.
     */
    public String getBrand()
        throws DataSetException, SQLException
    {
        return null;
    }

    /**
     * Returns the lower case version of the project name.
     */
    public String getName()
        throws DataSetException
    {
        if (name == null)
        {
            name = getName(getWordMark());
        }
        return name;
    }

    /**
     * Returns the stylized version of the name, capitalized as entered by the
     * admin user.
     */
    public String getWordMark()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_NAME).asString();
    }

    public String getLicense()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_LICENSE).asString();
    }

    public String getShortDescription()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_SHORT_DESCRIPTION)
            .asString();
    }

    public Boolean useIndex()
        throws DataSetException
    {
        return DBFlag.boolValueOf
            (rec.getValue(ProjectManager.USE_INDEX).asString());
    }

    /**
     * Returns the project's hypertext document directory (i.e.
     * <code>SANDBOX/data/helm/htdoc/PROJECTNAME/www</code>).
     *
     * @@return The path to the directory.
     */
    protected String getHtdocDir ()
        throws DataSetException
    {
        return JoistProperties.getProperty("SANDBOX") + File.separator + 
            "data" + File.separator + "helm" + File.separator + "htdoc" +
            File.separator + getName() + File.separator + "www";
    }

    /**
     * Gets the full description of the project, or the contents of htdoc 
     * <code>INDEX_FILE</code> if <code>ProjectManager.INDEX_FILE</code> is set.
     *
     * @@return The full description.
     */
    public String getLongDescription()
        throws DataSetException
    {
        // Check for alternate description.
        String useIndex = rec.getValue(ProjectManager.USE_INDEX).asString();
        if (DBFlag.booleanValueOf(useIndex))
        {
            // Dump the contents of the alternate description file.
            try
            {
                FileReader reader =
                    new FileReader(getHtdocDir() + File.separator + INDEX_FILE);
                StringBuffer buf = new StringBuffer();
                if (reader.ready())
                {
                    char[] cbuf = new char[1024];
                    int nbrRead;
                    while ((nbrRead = reader.read(cbuf, 0, cbuf.length)) != -1)
                        buf.append(cbuf, 0, nbrRead);
                    reader.close();
                    return buf.toString();
                }
            }
            catch (IOException ioe)
            {
                // Either the file wasn't found or there was an error reading
                // it.  Punt and use the in memory description.
                if (ioe instanceof FileNotFoundException)
                {
                    // TODO: Report missing index.html to user.
                }
            }
        }

        // No alternate description used.
        return rec.getValue(ProjectManager.PROJECT_LONG_DESCRIPTION)
            .asString();
    }

    public String getProposedBy()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_PROPOSED_BY).asString();
    }

    public String getProposedByLoginID()
        throws DataSetException, JoistDatabaseException, SQLException,
               DoesNotExist
    {
        String userID = getProposedBy();
        Record r = uMgr.getUser(conn, userID);
        User u = new User(conn, dMgr, r);
        return u.getLoginID();
    }

    public String getProposedEmail()
        throws DataSetException, JoistDatabaseException, SQLException,
               DoesNotExist
    {
        String userID = getProposedBy();
        Record r = uMgr.getUser(conn, userID);
        User u = new User(conn, dMgr, r);
        return u.getEmail();
    }

    public String getProposedByName()
        throws DataSetException, JoistDatabaseException, SQLException,
               DoesNotExist
    {
        String userID = getProposedBy();
        Record r = uMgr.getUser(conn, userID);
        User u = new User(conn, dMgr, r);
        return u.getName();
    }

    public String getApprovedBy()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_APPROVED_BY).asString();
    }

    public String getStatus()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_STATUS).asString();
    }

    public String getType()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_TYPE).asString();
    }

    public String getAliasURL()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_ALIAS_URL).asString();
    }

    /**
     * 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, User user)
        throws DataSetException
    {
        // Save to /pub-fileserver/projectID/userID/fileNameAsUploaded.
        StringBuffer dir = new StringBuffer(baseDir);
        dir.append(File.separatorChar).append(getID())
            .append(File.separatorChar).append(user.getID());
        return dir.toString();
    }

    /**
     * Add or suggest a download for this project.
     *
     * @@param acl      The ACL of the user adding the download.
     * @@param files    The <code>File</code> to add.
     * @@param descrip  The descriptions of the file to add.
     * @@param isPublic A flag indicating whether the file is private.
     * @@param url      The authorization and timeout URL.
     */
    public void addDownload (AccessControlList acl, File file, String descrip, 
                             String isPublic, String url)
        throws ACLException, DataSetException, SQLException, UpdateException, 
               JoistDatabaseException, IOException, DoesNotExist
    {
        new Download(conn, dMgr, acl, this, descrip, file, isPublic, url);
    }

    /**
     * Add or suggest a document section for this project.
     *
     * @@param acl       The ACL of the user doing the add.
    */
    public void addSection (AccessControlList acl, String parentID,
                            String name, String descrip)
        throws ACLException, DataSetException, SQLException,
               JoistDatabaseException, IOException, 
               DoesNotExist, UpdateException
    {
        new Section(conn, dMgr, acl, this, parentID, name, descrip);
    }

    /**
     * Get a list of top level document sections for this project
    */
    public List getSections ()
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        List sections = new ArrayList();

        DataSet sectionSet = secMgr.getTopLevelSectionsForProject 
                              (conn, getID());

        for (int i = 0; i < sectionSet.size(); i++)
        {
            Record r = sectionSet.getRecord(i);
	        sections.add(new Section(conn, dMgr, r));
        }

        return sections;

    }

    /**
     * Get a list of top level documents for this project
     * Top-level documents are those not associated with a section.
    */
    public List getTopLevelDocuments ()
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        List documents = new ArrayList();

        DataSet documentSet = docMgr.getDocumentsForProject (conn, getID());

        for (int i = 0; i < documentSet.size(); i++)
        {
            Record r = documentSet.getRecord(i);
            String documentID = r.getStringValue("document_id");
            if (pdsMgr.getSectionIDForDocument(conn, documentID).equals("0"))
	           documents.add(new Document(conn, dMgr, r));
        }

        return documents;

    }

    public List getUnapprovedDocuments()
       throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        List documents = new ArrayList();
     
        DataSet documentSet = docMgr.getUnapprovedDocumentsForProject (conn, getID());

        for (int i = 0; i < documentSet.size(); i++)
        {
            Record r = documentSet.getRecord(i);
            Document document = new Document(conn, dMgr, r);
	        documents.add(document);
        }

        return documents;

    }

    public List getUnapprovedSections()
       throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
    {
        List sections = new ArrayList();
     
        DataSet sectionSet = secMgr.getUnapprovedSectionsForProject (conn, getID());

        for (int i = 0; i < sectionSet.size(); i++)
        {
            Record r = sectionSet.getRecord(i);
            Section section = new Section(conn, dMgr, r);
            if (section.getApprovedBy().getID().equals
                   (usrGrpMgr.getNobodyUserID(conn)))
	           sections.add(section);
        }

        return sections;

    }

    /**
     * Add or suggest a document for this project.
     *
     * @@param acl       The ACL of the user doing the add.
    */
    public void addDocument (AccessControlList acl, String name,
                             String descrip, String type,
                             File f, String url, String text,
                             String sectionID, String htURL)
        throws ACLException, DataSetException, SQLException,
               JoistDatabaseException, IOException, DoesNotExist,
               UpdateException
    {
        new Document(conn, dMgr, acl, this, name, descrip, type, 
                     url, text, sectionID, f, htURL);
    }


    /**
     * Add or suggest a news item for this project.
     *
     * @@param acl       The ACL of the user doing the add.
     */
    public NewsItem addNewsItem (AccessControlList acl, Date eventDate,
                             String headline, String body, 
			                 Date publishDate, Date removeDate,
			                 String priority)
        throws ACLException, DataSetException, SQLException, 
               JoistDatabaseException, IOException, DoesNotExist,
               UpdateException
    {
        NewsItem newsItem = new NewsItem (conn, dMgr, acl, this, eventDate, headline, body, publishDate, removeDate, priority);
            log.info("Project newsId= " + newsItem.getID());
        return newsItem;
    }

    /**
     * Writes the .htaccess file in the right directory for this project.
     *
     * @@param path      The full directory path to where to write a .htaccess
     *                  file.
     * @@param url       The URL for auth and timeout (when <code>null</code>, 
     *                  defaults to <code>http://[JVM host]/</code>).
     */
    protected void writeHtaccessFile (String path, String url)
        throws IOException, DataSetException, SQLException, DoesNotExist
    {
        String fileName = path + File.separatorChar + ".htaccess";
        if (url == null)
        {
            url = URL.DEFAULT_PROTOCOL + "://" +
                InetAddress.getLocalHost().getHostName() + '/';
        }

        // If not in vhosting mode, append projectID as cgi param
        org.joist.util.JoistProperties properties
            = org.joist.util.JoistProperties.getInstance( );
        if( properties == null )
            throw new NullPointerException( "JoistProperties is null" );
        if (!isVhosting(properties))
        {
            url = URL.appendCGIParam(url, "projectID", getID());
        }

        // Get a mutex for the given .htaccess file.
        Object htaccessWriteLock = null;
        synchronized (htaccessLocks)
        {
            if (!htaccessLocks.containsKey(fileName))
            {
                htaccessLocks.put(fileName, new Object());
            }
            htaccessWriteLock = htaccessLocks.get(fileName);
        }

        // Append each entry to the .htaccess file.
        synchronized (htaccessWriteLock)
        {
            List downloads = getDownloads();
            FileWriter out = new FileWriter(fileName);
            out.write("# DO NOT EDIT: Generated by Tigris on " + 
                      new java.util.Date() + "\n\n");
            int nbrDownloads = downloads.size();
            for (int i = 0; i < nbrDownloads; i++)
            {
                Download d = (Download)downloads.get(i);

                out.write("<Files \"");
                out.write(d.getName());
                out.write("\">\n");
                out.write("AuthName MDAAuth\n");
                out.write("AuthType Basic\n");
                out.write("require valid-user\n");
                out.write("MDARealmMask      \"");
                out.write(generateMDARealmMask(d.isPublic().booleanValue()));
                out.write("\"\n");
                out.write("MDAAuthLoginURL   \"");
                out.write(url);
                out.write("\"\n");
                out.write("MDAAuthTimeoutURL \"");
                out.write(URL.appendCGIParam
                          (url, MESSAGE, "Download authorization timed out."));
                out.write("\"\n");
                out.write("MDAAuthTimeoutMin 1\n");
                out.write("</Files>\n");
                if (i < nbrDownloads - 1) out.write('\n');
            }
            List documents = getDocuments();
            int nbrDocuments = documents.size();
            for (int i = 0; i < nbrDocuments; i++)
            {
                Document dc = (Document)documents.get(i);

                out.write("<Files \"");
                out.write(dc.getName());
                out.write("\">\n");
                out.write("AuthName MDAAuth\n");
                out.write("AuthType Basic\n");
                out.write("require valid-user\n");
                out.write("MDARealmMask      \"");
                out.write(generateMDARealmMask(dc.isPublic().booleanValue()));
                out.write("\"\n");
                out.write("MDAAuthLoginURL   \"");
                out.write(url);
                out.write("\"\n");
                out.write("MDAAuthTimeoutURL \"");
                out.write(URL.appendCGIParam
                          (url, MESSAGE, "Document authorization timed out."));
                out.write("\"\n");
                out.write("MDAAuthTimeoutMin 1\n");
                out.write("</Files>\n");
                if (i < nbrDocuments - 1) out.write('\n');
            }
            out.close();
        }
    }

    /**
     * All the .htaccess files within a specific projectID will share that
     * same realm.  The return value will be used in creation of an auth
     * ticket for file downloads.
     *
     * @@param isPublicFile Whether the download requires auth for a
     *                    <i>specific domain</i>.
     * @@return            The hexidecimal representation of the project's 
     *                    unique identifier.
     */
    public String generateMDARealmMask (boolean isPublicFile)
        throws DataSetException
    {
        // If the file requested is private, set the projectID bit.
        BigInteger i = (isPublicFile ?
                        BigInteger.ZERO : 
                        BigInteger.ZERO.setBit(Integer.parseInt(getID())));
        // Return as hex (a la tohex(2 ^ downloadID)).
        return i.toString(16);
    }

    /**
     * Return the ProjectHome url.
     *
     * @@see #getProjectHome( String )
     */
    public String getProjectHome( )
        throws NullPointerException, IllegalArgumentException, DataSetException
    {
        return getProjectHome( ( String )null );
    }
    
    
    /**
     * Return the ProjectHome url.
     *
     * Will return either '/servlets/ProjectHome?projectID=THIS_PROJECT_ID
     * or 'http://THIS_PROJECTNAME.THIS_PROJECT_DOMAIN/servlets/ProjectHome.
     * The switch turns on the <code>env.sh</code> setting IS_VHOSTING.  (The
     * ${SANDOBX}/scripts/configure.pl writes the IS_VHOSTING value to 
     * <code>${SANDBOX}/newhelm/conf/40helm.zone.properties</code>)
     * <p>
     * You would use this method to write out links to this project's
     * ProjectHome page.  For example, say you are browsing 
     * www.DOMAIN and you come upon the ProjectList page that
     * holds a list of all projects.  Calling this method on each of the
     * projects found to write the links for ProjectList will 
     * return the appropriate ProjectHome link. 
     *
     * @@param inProtocol Pass 'http' or 'https'.  If null, we assume 'http'.
     *
     * @@return Either 'PROJECTHOME_SERVLETPATH?projectID=THIS_PROJECT_ID' or
     * 'http://THIS_PROJECTNAME.THIS_PROJECT_DOMAIN/SERVLET_PATH'
     *
     * @@exception NullPointerException If i can't get JoistProperties instance.
     * @@exception IllegalArgumentException Thrown if you pass anything but 
     * 'http' or 'http' in the inProtocol param.
     * @@exception DataSetException Thrown by getName( ).
     */
    public String getProjectHome( String inProtocol )
        throws NullPointerException, IllegalArgumentException, DataSetException
    {
        return buildProjectPageURL("ProjectHome", null, inProtocol, false, true);
    }

    public String projectMembersURL()
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL
            ("ProjectMembers", null, "http", false, true);
    }

    private boolean isVhosting(org.joist.util.JoistProperties properties) {
        String IS_VHOSTING_KEY = "IS_VHOSTING"; // Key for VHOSTING.
        // Test if vhosting is turned on.
        String isVhosting = properties.getProperty( IS_VHOSTING_KEY );
        if( isVhosting != null &&
                (new Boolean(isVhosting).booleanValue()) )
            return true;
        return false;
    }

    /**
     * This provides an URL (or UIR) to use for a given page in a project.
     * This version can be used with a template.
     */
    public String getProjectPageURL(String page)
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL(page, null, null, false, true);
    }

    /**
     * This provides an URL (or URI) to use for a given page in a project.
     * This version can be used within a template.
     */
    public String getProjectPageURL(String page, String queryArgs)
        throws NullPointerException, DataSetException
    {
        if (queryArgs != null && queryArgs.equals(""))
            queryArgs = null;

        return buildProjectPageURL(page, queryArgs, null, false, true);
    }

    /**
     * This provides an URL to use for a given page in a project.  This
     * verion is typically used within e-mail and in other contexts
     * where an absolute link is required.
     */
    public String getProjectPageFullURL(String page, String queryArgs,
            String inProtocol)
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL(page, queryArgs, inProtocol, true, true);
    }

    /**
     * This provides an URL (or URI) to use for a given page in a project.
     */
    public String getProjectPageURL(String page, String queryArgs,
            String inProtocol)
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL(page, queryArgs, inProtocol, false, true);
    }


    /**
     * This provides an URL (or URI) to use for a given (non-servlet) file
     *  in a project.
     */
    public String getProjectFileURL(String page)
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL(page, null, null, false, false);
    }

    /**
     * This provides an URL (or URI) to use for a given (non-servlet) file
     *  in a project.
     */
    public String getProjectFileURL(String page, String queryArgs)
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL(page, queryArgs, null, false, false);
    }

    /**
     * This provides an URL (or URI) to use for a given (non-servlet) file
     *  in a project.
     */
    public String getProjectFileURL(String page, String queryArgs,
                                    String inProtocol)
        throws NullPointerException, DataSetException
    {
        return buildProjectPageURL(page, queryArgs, inProtocol, false, false);
    }


    /**
     * This provides a URL to use for a given page in a project.  It uses
     * a configuration flag -- which is part of env.sh -- to determine
     * whether projects should be represented as http://$project.domain/...
     * or http://domain/...?projectID=$project.getID()
     *
     * The logic is: if forceFullyQualifiedDomain is true or if vhosting
     * (the former form) is being used, then start with
     * http://[{project}].domain.  Next, add /servlets/$page.  Finally,
     * if a queryArgs are provided or if the latter form is being used,
     * generate an appropriate query string.
     *
     * Look at the JavaDocs for getProjectHome for more an explanation
     * of one use of this function.
     *
     * @@param page The servlet to which to point
     * @@param queryArgs Any query arguments which are needed
     * @@param inProtocol The protocol being used, so far as we know
     * @@param forceFullyQualifiedDomain Whether to insist on including
     * the protocol, domain, and port number.  This is useful eg. for
     * e-mail messages, where relative URIs will not work.
     * @@return a URI/URL to send to the client
     */
    private String buildProjectPageURL
        (String page, String queryArgs, String inProtocol, 
         boolean forceFullyQualifiedDomain, boolean isServlet)
        throws NullPointerException, DataSetException
    {
        // JoistProperties is a singleton of system properties.
        org.joist.util.JoistProperties properties
            = org.joist.util.JoistProperties.getInstance( );
        if( properties == null )
            throw new NullPointerException( "JoistProperties is null" );
                    
        boolean isVhosting = isVhosting(properties);
        StringBuffer buff = new StringBuffer();

        String DOMAIN_KEY = "DOMAIN";
        String SERVLET_PREFIX = "/servlets/"; 

        org.joist.util.URL urlUtil = new org.joist.util.URL( );
        String protocol = urlUtil.getProtocol( inProtocol );
        String port = urlUtil.getPort( protocol );
        String domain = properties.getProperty( DOMAIN_KEY );
        if( domain == null || domain.length( ) <= 0 )
            throw new NullPointerException( DOMAIN_KEY + " is null" );

        if (isVhosting || forceFullyQualifiedDomain) {
            buff.append( protocol );
            buff.append( "://" ); 
            if (isVhosting) {
                buff.append( getName() ); // Add this project's name as host.
                buff.append( '.' ); // Dot between project name and domain
            }
            buff.append( domain );  
            if( port != null)
            {
                buff.append( ":" );
                buff.append( port );
            }
        }
        if (isServlet)
            buff.append(SERVLET_PREFIX);
        buff.append(page);
        String projectArgs = null;
        if (!isVhosting)
            projectArgs = "projectID=" + getID();

        if (projectArgs != null && queryArgs != null) {
            buff.append("?").append(projectArgs).append("&").append(queryArgs);
        } else if (projectArgs != null) {
            buff.append("?").append(projectArgs);
        } else if (queryArgs != null) {
            buff.append("?").append(queryArgs);
        }
        return buff.toString();
    }
}
@


1.140
log
@removed specific domain name reference
@
text
@@


1.139
log
@cleanup
@
text
@d1684 1
a1684 1
     * www.wireopen.com and you come upon the ProjectList page that
@


1.138
log
@removed unneccessary check from getUnapprovedDocuments
@
text
@d1085 21
@


1.137
log
@now adding new news item using NewsItem constructor
@
text
@d1454 1
a1454 3
            if (document.getApprovedBy().getID().equals
                   (usrGrpMgr.getNobodyUserID(conn)))
	           documents.add(document);
@


1.136
log
@checking if vhosted before appending cgi param to url in .htaccess file
@
text
@d1507 1
a1507 1
    public String addNewsItem (AccessControlList acl, Date eventDate,
d1511 3
a1513 2
        throws ACLException, DataSetException, SQLException,
               JoistDatabaseException, IOException, DoesNotExist
d1515 3
a1517 15
        String message;
        String projectID = getID();
        String action = "Project News - Suggest";
        acl.assertPermissionForProject(action, projectID);
        action = "Project News - Approve";
        String approvedBy = (acl.hasPermissionForProject(action, projectID) ?
                             acl.getUserID() : 
                             usrGrpMgr.getNobodyUserID(conn));
        newsMgr.updateNews(conn, null, projectID, eventDate, headline, body,
	            approvedBy, publishDate, removeDate, priority, acl.getUserID());
        if (!approvedBy.equals(acl.getUserID()))
            message = "Thank you for adding your news item. When the administrator approves it, it will appear in the list of news items for this project."; 
        else
            message="Thank you for adding your news item.";
        return message;
@


1.135
log
@changed to return 0  instead of null if top level document
@
text
@d1548 10
a1557 2
        // TODO: Only append when not vhosted
        url = URL.appendCGIParam(url, "projectID", getID());
@


1.134
log
@Projects are the same if their IDs are the same, not their names.
@
text
@d1434 1
a1434 1
            if (pdsMgr.getSectionIDForDocument(conn, documentID) == null)
@


1.133
log
@added documents uploads to the writeHtaccess method
@
text
@d740 1
a740 1
            if (getName().equals(p.getName()))
@


1.133.2.1
log
@Porting to the Turbine Peer system.  -dlr and leonardr
@
text
@@


1.132
log
@readding all the files as part of the process of returning to the way
things were as of tuesday
@
text
@d1594 26
@


1.131
log
@revert this stuff to its state as of 2001/01/24 12:42:00 GMT -- with
the following exceptions, which have some different modifications so
they'll work with changes which have happened in joist:

ProjectNewsEdit.java
SkinManager.java
SkinStyleElementValueManager.java
StyleElementManager.java
StyleManager.java

it compiles.  i dunno if it works, though.
@
text
@d32 1
a32 1
 * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
d69 1
a69 4

import org.joist.database.Criterion;
import org.joist.database.DataManager;
import org.joist.database.JoistDatabaseException;
d160 1
d167 3
a169 3
    public static void assertNonexistance(DataManager dMgr, String domainID,
                                          String name)
        throws DBException, AlreadyExists
d173 1
a173 1
            new Project(dMgr, domainID, name);
d225 1
a225 1
    public Project (DataManager dMgr)
d227 1
a227 1
        super(dMgr);
d230 2
a231 2
    public Project (DataManager dMgr, Record rec)
        throws DoesNotExist, DBException
d233 1
a233 1
        super(dMgr, rec);
d240 2
a241 2
    public Project (DataManager dMgr, String projectID)
        throws DoesNotExist, DBException
d243 2
a244 1
        super(dMgr, pMgr.getProjectForID(projectID));
d251 3
a253 2
     public Project (DataManager dMgr, String domainID, String name)
         throws DoesNotExist, DBException
d255 2
a256 1
        super(dMgr, pMgr.getProjectForName(c, domainID, name));
d263 4
a266 3
    public Project (DataManager dMgr, String domainID, String aliasURL, 
                    boolean ignore)
        throws DoesNotExist, DBException
d268 2
a269 1
        super(dMgr, pMgr.getProjectForAliasURL(c, domainID, aliasURL));
d277 2
a278 2
    public Project(DataManager dMgr, AccessControlList acl,
                   ProjectProfile profile,  String domainID, String wordMark, 
d283 3
a285 2
        throws ACLException, AlreadyExists, DoesNotExist, UpdateException,
               DBException
d287 1
a287 1
        super(dMgr);
d296 1
d299 1
a299 1
            Project.assertNonexistance(dMgr, domainID, wordMark);
d302 7
a308 5
            String approvedBy = uMgr.getNobodyUserID();
            setRecord(pMgr.addProject(profile, domainID, wordMark, license, 
                                      shortDescription, longDescription,
                                      useIndex, "", aliasURL, proposedBy,
                                      approvedBy));
d328 1
a328 1
            newOwner   = User.getInstance(dMgr, newOwnerID);
d332 1
a332 1
            newOwner   = new User(dMgr, domainID, projectOwner);
d336 16
a351 1
        try
d353 15
a367 17
            // HELP: special user for system-approved roles?
            String rootUserID = uMgr.getUserForLoginID(domainID, "root")
                .getValue(UserManager.USER_ID).asString();
            urpMgr.grantNamedRole(newOwnerID, "Project Owner", 
                                  getID(), rootUserID);

            String name = getName(wordMark);
            AnzuTigrisTask.addProject(dMgr, newOwnerID, domainID, name);
            AnzuTigrisTask.setOwnerAlias(dMgr, newOwnerID, getID(),
                                         false);

            //Add the project to the appropriate groups.
            ProjectGroup.addToHostGroup(dMgr, this);
            ProjectGroup.addToDomainGroup(dMgr, this, getDomainID());

            //Approve the project, if user has the right permission.
            if (acl.hasPermissionForDomain("Project - Approve", domainID))
d369 2
a370 1
                approve(acl);
d372 1
a372 1
            else
d374 1
a374 22
                //Send a message to the domain admin(s) informing them of
                //the newly requested project.
                User createdUser = User.getInstance(dMgr, acl.getUserID());
                Role role = new Role(dMgr, "Domain Admin", false);
                Domain domain = new Domain(dMgr, domainID);
                String subject = "New unapproved project: " + wordMark;
                BuildContext ctx = TemplateInterpolator.createContext();
                ctx.put("project", this);
                ctx.put("createdUser", createdUser);
                String body = TemplateInterpolator.interpolate(CREATED_TMPL,
                                                               ctx,
                                                               getClass());
                HelmEmailer emailer = new HelmEmailer(dMgr);
                try 
                {
                    emailer.messageUsersWithDomainRole(role, domain, subject, 
                                                       body);
                }
                catch (JoistException e)
                {
                    log.info("Unable to mail domain admins about new project.");
                }
d376 1
d378 1
a378 19
            try
            {
                profile.addDefaultMailingLists
                    (dMgr, getID(), newOwner, Licenses.isProprietary(license));
            }
            catch (HandlerException e)
            {
                log.exception(e);
                if (debug) log.info("HandlerException adding default MLs: " +
                                    e.getMessage());
                throw new UpdateException
                    ("HandlerException adding default MLs: " + e.getMessage());
            }
        }
        catch (JoistDatabaseException e)
        {
            throw new DBException(e);
        }
        catch (DataSetException e)
d380 2
a381 1
            throw new DBException(e);
d383 1
a383 1
        catch (SQLException e)
d385 5
a389 1
            throw new DBException(e);
d399 2
a400 1
        throws DoesNotExist, DBException
d405 1
a405 1
            TigrisUpdate.addProject(dMgr, initiatingUser, p);
d408 1
a408 1
                TigrisUpdate.addModule(dMgr, null, p, "www",
d418 1
a418 1
            ("org.tigris.helm.database.UserManager");        
d434 1
a434 1
            ("org.tigris.helm.database.RoleManager");
d452 2
a453 1
        throws DoesNotExist, DBException
d462 2
a463 1
        throws DoesNotExist, DBException
d469 2
a470 1
        throws ACLException, DoesNotExist, DBException
d476 2
a477 1
        throws ACLException, DoesNotExist, DBException
d487 2
a488 1
        throws DoesNotExist, UpdateException, DBException
d502 2
a503 1
        throws ACLException, DoesNotExist, DBException
d528 1
a528 1
        urpMgr.deleteRolesForProject(getID());
d545 2
a546 2
        AnzuTigrisTask.deleteProject(dMgr, acl.getUserID(),
                                     getDomainID(), getName());
d554 2
a555 2
        pMgr.deleteProject(getID());
        TigrisUpdate.deleteProject (dMgr, acl.getUserID(), this);
d562 2
a563 1
        throws ACLException, DoesNotExist, DBException
d571 1
a571 1
        pMgr.approveProject(getID(), acl.getUserID());
d576 1
a576 1
            ProjectGroup.addToPublicGroup(dMgr, this, getDomainID());
d584 2
a585 1
        throws ACLException, JoistException, DoesNotExist, DBException
d595 1
a595 1
        User disapprovingUser = User.getInstance(dMgr, acl.getUserID());
d602 2
a603 2
        Role role = new Role(dMgr, "Project Owner", false);
        HelmEmailer emailer = new HelmEmailer(dMgr);
d626 2
a627 1
        throws DBException, DoesNotExist, UpdateException, ACLException
d648 1
a648 1
        pMgr.updateProjectInfo(getID(), license, shortDescription,
d661 1
a661 1
        throws HandlerException, DBException, DoesNotExist
d710 1
a710 1
            TigrisUpdate.disableAllAccounts(dMgr, acl.getUser(), p);
d716 1
a716 1
        before.syncTo(dMgr, after);
d749 1
a749 1
        throws DBException
d755 1
a755 1
                g = new ProjectGroup(dMgr, this.rec);
d768 1
a768 1
                c = new Category(dMgr, this.rec);
d780 1
a780 1
	throws DBException
d794 1
a794 1
        throws DBException
d819 1
a819 1
        throws DBException, DoesNotExist
d821 2
a822 1
        DataSet categorySet = pMgr.getCategoriesForProject(getID());
d827 1
a827 1
            Category c = new Category(dMgr, r);
d837 1
a837 1
        throws DBException, DoesNotExist
d840 1
a840 1
            prjGrpMgr.getGroupsForProject(getID());
d846 1
a846 1
            ProjectGroup p = new ProjectGroup(dMgr, projectID);
d853 1
a853 1
        throws DBException, JoistDatabaseException,
d860 2
a861 1
        throws DoesNotExist, DBException
d863 3
a865 1
        DataSet userSet = urpMgr.getUsersForProject(getID(), Boolean.TRUE);
d871 1
a871 1
            User u = new User(dMgr, r);
d888 1
a888 1
        throws DBException, JoistDatabaseException,
d891 2
a892 1
        DataSet userSet = urpMgr.getUsersForProject(getID(), Boolean.FALSE);
d898 1
a898 1
            User u = User.getInstance(dMgr, userID);
d907 1
a907 1
        throws DBException, JoistDatabaseException,
d910 2
a911 1
        DataSet roleSet = urpMgr.getRequestedRolesForProject(getID());
d917 1
a917 1
            Role role = new Role(dMgr, roleID);
d925 1
a925 1
        throws DBException, JoistDatabaseException,
d928 3
a930 2
        String roleID = roleMgr.getRoleID("Project Owner");
        DataSet ownerSet = urpMgr.getUsersForRoleProject(roleID, getID());
d936 1
a936 1
            User user = User.getInstance(dMgr, userID);
d944 1
a944 1
        throws DoesNotExist, DBException
d948 2
a949 1
        DataSet mailingListSet = mlMgr.listProjectMailingLists(getID());
d955 1
a955 1
            MailingList m = new MailingList(dMgr, r);
d968 2
a969 1
        throws DoesNotExist, DBException
d971 1
a971 1
        Skin s = Skin.getSkin(dMgr, getSkinID());
d974 1
a974 1
            s = Skin.getSkin(dMgr, 
d979 1
a979 1
            s = Skin.getSkin(dMgr, 
d989 1
a989 1
        throws DBException
d999 1
a999 1
        throws DBException
d1021 1
a1021 1
        throws DBException
d1028 1
a1028 1
        throws DBException
d1035 1
a1035 1
        throws DBException
d1042 1
a1042 1
        throws DBException
d1049 1
a1049 1
        throws DBException
d1056 1
a1056 1
        throws DBException
d1062 1
a1062 1
        throws DBException
d1064 1
a1064 1
        return !getApprovedBy().equals(uMgr.getNobodyUserID());
d1068 1
a1068 1
        throws DBException, DoesNotExist
d1073 2
a1074 1
        DataSet downloadSet = dlMgr.getDownloadsForProject(getID());
d1079 1
a1079 1
            downloads.add(new Download(dMgr, r));
d1086 1
a1086 1
        throws DBException, DoesNotExist
d1092 1
a1092 1
            docMgr.getDocumentsForProject(getID());
d1097 1
a1097 1
            documents.add(new Document(dMgr, r));
d1105 1
a1105 1
        throws DBException, DoesNotExist, ParseException,
d1108 1
a1108 1
        String nobodyID = uMgr.getNobodyUserID();
d1111 2
a1112 2
        String query = newsMgr.getNewsForProjectQuery(getID());
        n = new PaginatableNewsItemList(dMgr, itemsPerPage, query, 
d1118 1
a1118 1
        throws DBException, DoesNotExist, ParseException,
d1126 1
a1126 1
        throws DBException, DoesNotExist, ParseException,
d1130 3
a1132 3
        String query = newsMgr.getUnapprovedNewsForProjectQuery(getID());
        n = new PaginatableNewsItemList(dMgr, itemsPerPage, query, 
                                        searchCriterion, acl);
d1137 1
a1137 1
        throws DBException, DoesNotExist, ParseException,
d1148 1
a1148 1
        throws DBException
d1154 1
a1154 1
        throws DoesNotExist, DBException
d1156 1
a1156 1
        return new Domain(dMgr, getDomainID());
d1160 1
a1160 1
        throws DoesNotExist, DBException
d1166 1
a1166 1
        throws DBException
d1168 1
a1168 8
        try
        {
            return rec.getValue(ProjectManager.PROJECT_DOMAIN_ID).asString();
        }
        catch (DataSetException e)
        {
            throw new DBException(e);
        }
d1172 1
a1172 1
        throws DBException
d1181 1
a1181 1
        throws DBException
d1190 1
a1190 1
        throws DBException
d1204 1
a1204 1
        throws DBException
d1206 1
a1206 8
        try
        {
            return rec.getValue(ProjectManager.PROJECT_NAME).asString();
        }
        catch (DataSetException e)
        {
            throw new DBException(e);
        }
d1210 1
a1210 1
        throws DBException
d1212 1
a1212 8
        try
        {
            return rec.getValue(ProjectManager.PROJECT_LICENSE).asString();
        }
        catch (DataSetException e)
        {
            throw new DBException(e);
        }
d1216 1
a1216 1
        throws DBException
d1218 2
a1219 9
        try
        {
            return rec.getValue(ProjectManager.PROJECT_SHORT_DESCRIPTION)
                .asString();
        }
        catch (DataSetException e)
        {
            throw new DBException(e);
        }
d1223 1
a1223 1
        throws DBException
d1225 2
a1226 9
        try
        {
            return DBFlag.boolValueOf
                (rec.getValue(ProjectManager.USE_INDEX).asString());
        }
        catch (DataSetException e)
        {
            throw new DBException(e);
        }
d1236 1
a1236 1
        throws DBException
d1250 1
a1250 1
        throws DBException
d1289 1
a1289 1
        throws DBException
d1295 1
a1295 1
        throws DBException, JoistDatabaseException, SQLException,
d1299 2
a1300 2
        Record r = uMgr.getUser(userID);
        User u = new User(dMgr, r);
d1305 1
a1305 1
        throws DBException, JoistDatabaseException, SQLException,
d1309 2
a1310 2
        Record r = uMgr.getUser(userID);
        User u = new User(dMgr, r);
d1315 1
a1315 1
        throws DBException, JoistDatabaseException, SQLException,
d1319 2
a1320 2
        Record r = uMgr.getUser(userID);
        User u = new User(dMgr, r);
d1325 1
a1325 1
        throws DBException
d1331 1
a1331 1
        throws DBException
d1337 1
a1337 1
        throws DBException
d1339 1
a1339 8
        try
        {
            return rec.getValue(ProjectManager.PROJECT_TYPE).asString();
        }
        catch (DataSetException e)
        {
            throw new DBException(e);
        }
d1343 1
a1343 1
        throws DBException
d1356 1
a1356 1
        throws DBException
d1376 2
a1377 2
        throws ACLException, DBException, UpdateException, 
               IOException, DoesNotExist
d1379 1
a1379 1
        new Download(dMgr, acl, this, descrip, file, isPublic, url);
d1389 3
a1391 2
        throws ACLException, DBException, IOException, DoesNotExist,
               UpdateException
d1393 1
a1393 1
        new Section(dMgr, acl, this, parentID, name, descrip);
d1400 2
a1401 1
        throws DBException, DoesNotExist, ParseException
d1405 3
a1407 1
        DataSet sectionSet = secMgr.getTopLevelSectionsForProject(getID());
d1411 1
a1411 1
            sections.add(new Section(dMgr, r));
d1423 1
a1423 1
        throws DBException, DoesNotExist, ParseException,
d1428 2
a1429 1
        DataSet documentSet = docMgr.getDocumentsForProject(getID());
d1434 2
a1435 2
            if (pdsMgr.getSectionIDForDocument(documentID) == null)
                documents.add(new Document(dMgr, r));
d1443 2
a1444 1
       throws DBException, DoesNotExist, ParseException
d1448 1
a1448 2
        DataSet documentSet =
            docMgr.getUnapprovedDocumentsForProject(getID());
d1453 1
a1453 1
            Document document = new Document(dMgr, r);
d1455 2
a1456 2
                (uMgr.getNobodyUserID()))
                documents.add(document);
d1464 2
a1465 1
       throws DBException, DoesNotExist, ParseException
d1469 1
a1469 2
        DataSet sectionSet =
            secMgr.getUnapprovedSectionsForProject (getID());
d1474 1
a1474 1
            Section section = new Section(dMgr, r);
d1476 1
a1476 1
                   (uMgr.getNobodyUserID()))
d1493 2
a1494 1
        throws ACLException, DBException, IOException, DoesNotExist,
d1497 2
a1498 2
        new Document(dMgr, acl, this, name, descrip, type, url, text,
                     sectionID, f, htURL);
d1511 2
a1512 1
        throws ACLException, DBException, IOException, DoesNotExist
d1521 3
a1523 4
                             uMgr.getNobodyUserID());
        newsMgr.updateNews(null, projectID, eventDate, headline, body,
                           approvedBy, publishDate, removeDate, priority,
                           acl.getUserID());
d1540 1
a1540 1
        throws IOException, DBException, DoesNotExist
d1609 1
a1609 1
        throws DBException
d1625 1
a1625 1
        throws NullPointerException, IllegalArgumentException, DBException
d1655 1
a1655 1
     * @@exception DBException Thrown by getName( ).
d1658 1
a1658 1
        throws NullPointerException, IllegalArgumentException, DBException
d1660 1
a1660 2
        return buildProjectPageURL("ProjectHome", null, inProtocol, false,
                                   true);
d1664 1
a1664 1
        throws NullPointerException, DBException
d1685 1
a1685 1
        throws NullPointerException, DBException
d1695 1
a1695 1
        throws NullPointerException, DBException
d1710 1
a1710 1
        throws NullPointerException, DBException
d1720 1
a1720 1
        throws NullPointerException, DBException
d1731 1
a1731 1
        throws NullPointerException, DBException
d1741 1
a1741 1
        throws NullPointerException, DBException
d1752 1
a1752 1
        throws NullPointerException, DBException
d1784 1
a1784 1
        throws NullPointerException, DBException
@


1.130
log
@fixed constructor
@
text
@@


1.129
log
@Removed all references to JDBC connections.  Connections are now pulled
directly from the connection pool.
@
text
@d275 1
a275 1
                   ProjectProfile String domainID, String wordMark, 
@


1.128
log
@Ported UserManager and RoleManager to Helm. Started moving other TableManagers toward a grab-connection-on-demand model. Massive breakage ensues. dlr and I are working on it.
@
text
@a162 1
     * @@param c        The JDBC connection to use.
d169 2
a170 2
    public static void assertNonexistance(Connection conn, DataManager dMgr, 
                                          String domainID, String name)
d175 1
a175 1
            new Project(conn, dMgr, domainID, name);
d227 1
a227 1
    public Project (Connection conn, DataManager dMgr)
d229 1
a229 1
        super(conn, dMgr);
d232 1
a232 1
    public Project (Connection conn, DataManager dMgr, Record rec)
d235 1
a235 1
        super(conn, dMgr, rec);
d242 1
a242 1
    public Project (Connection conn, DataManager dMgr, String projectID)
d245 1
a245 2
        super(conn, dMgr);
        setRecord(pMgr.getProjectForID(conn, projectID));
d252 1
a252 2
     public Project (Connection c, DataManager dMgr, String domainID,
                     String name)
d255 1
a255 2
        super(c, dMgr);
        setRecord(pMgr.getProjectForName(c, domainID, name));
d262 2
a263 2
    public Project (Connection c, DataManager dMgr, String domainID, 
                    String aliasURL, boolean ignore)
d266 1
a266 2
        super(c, dMgr);
        setRecord(pMgr.getProjectForAliasURL(c, domainID, aliasURL));
d274 2
a275 2
    public Project(Connection c, DataManager dMgr, AccessControlList acl,
                   ProjectProfile profile, String domainID, String wordMark, 
d283 1
a283 1
        super(c, dMgr);
a291 1
        String domainName;
d294 1
a294 1
            Project.assertNonexistance(conn, dMgr, domainID, wordMark);
d297 5
a301 7
            String approvedBy = usrGrpMgr.getNobodyUserID(c);
            setRecord(pMgr.addProject(conn, profile, domainID, wordMark, 
                                      license, shortDescription, 
                                      longDescription, useIndex, "", aliasURL,
                                      proposedBy, approvedBy));

            domainName = domMgr.getDomainName(domainID);
d321 1
a321 1
            newOwner   = User.getInstance(conn, dMgr, newOwnerID);
d325 1
a325 1
            newOwner   = new User(conn, dMgr, domainID, projectOwner);
d332 1
a332 1
            String rootUserID = uMgr.getUserForLoginID(conn, "root")
d334 1
a334 1
            urpMgr.grantNamedRole(conn, newOwnerID, "Project Owner", 
d338 2
a339 2
            AnzuTigrisTask.addProject(conn, dMgr, newOwnerID, domainID, name);
            AnzuTigrisTask.setOwnerAlias(conn, dMgr, newOwnerID, getID(),
d343 2
a344 2
            ProjectGroup.addToHostGroup(conn, dMgr, this);
            ProjectGroup.addToDomainGroup(conn, dMgr, this, getDomainID());
d355 3
a357 4
                User createdUser = User.getInstance(conn, dMgr,
                                                    acl.getUserID());
                Role role = new Role(conn, dMgr, "Domain Admin", false);
                Domain domain = new Domain(conn, dMgr, domainID);
d365 1
a365 1
                HelmEmailer emailer = new HelmEmailer(conn, dMgr);
d380 1
a380 2
                    (conn, dMgr, getID(), newOwner,
                     Licenses.isProprietary(license));
d416 1
a416 1
            TigrisUpdate.addProject(conn, dMgr, initiatingUser, p);
d419 1
a419 1
                TigrisUpdate.addModule(conn, dMgr, null, p, "www",
d533 1
a533 1
        urpMgr.deleteRolesForProject(conn, getID());
d550 1
a550 1
        AnzuTigrisTask.deleteProject(conn, dMgr, acl.getUserID(),
d559 2
a560 2
        pMgr.deleteProject(conn, getID());
        TigrisUpdate.deleteProject (conn, dMgr, acl.getUserID(), this);
d575 1
a575 1
        pMgr.approveProject(conn, getID(), acl.getUserID());
d580 1
a580 1
            ProjectGroup.addToPublicGroup(conn, dMgr, this, getDomainID());
d598 1
a598 1
        User disapprovingUser = User.getInstance(conn, dMgr, acl.getUserID());
d605 2
a606 2
        Role role = new Role(conn, dMgr, "Project Owner", false);
        HelmEmailer emailer = new HelmEmailer(conn, dMgr);
d650 1
a650 1
        pMgr.updateProjectInfo(conn, getID(), license, shortDescription,
d712 1
a712 1
            TigrisUpdate.disableAllAccounts(conn, dMgr, acl.getUser(connection), p);
d718 1
a718 1
        before.syncTo(conn, dMgr, after);
d757 1
a757 1
                g = new ProjectGroup(conn, dMgr, this.rec);
d770 1
a770 1
                c = new Category(conn, dMgr, this.rec);
d823 1
a823 2
        DataSet categorySet = 
            pMgr.getCategoriesForProject(conn, getID());
d828 1
a828 1
            Category c = new Category(conn, dMgr, r);
d841 1
a841 1
            prjGrpMgr.getGroupsForProject(conn, getID());
d847 1
a847 1
            ProjectGroup p = new ProjectGroup(conn, dMgr, projectID);
d863 1
a863 3
        DataSet userSet = urpMgr.getUsersForProject(conn, 
                                                    getID(), 
                                                    Boolean.TRUE);
d869 1
a869 1
            User u = new User(conn, dMgr, r);
d889 1
a889 2
        DataSet userSet = urpMgr.getUsersForProject(conn, getID(), 
                                                    Boolean.FALSE);
d895 1
a895 1
            User u = User.getInstance(conn, dMgr, userID);
d907 1
a907 1
        DataSet roleSet = urpMgr.getRequestedRolesForProject(conn, getID());
d913 1
a913 1
            Role role = new Role(conn, dMgr, roleID);
d924 2
a925 3
        String roleID = roleMgr.getRoleID(conn, "Project Owner");
        DataSet ownerSet = urpMgr.getUsersForRoleProject(conn, roleID,
                                                         getID());
d931 1
a931 1
            User user = User.getInstance(conn, dMgr, userID);
d943 1
a943 1
        DataSet mailingListSet = mlMgr.listProjectMailingLists(conn, getID());
d949 1
a949 1
            MailingList m = new MailingList(conn, dMgr, r);
d964 1
a964 1
        Skin s = Skin.getSkin(conn, dMgr, getSkinID());
d967 1
a967 1
            s = Skin.getSkin(conn, dMgr, 
d972 1
a972 1
            s = Skin.getSkin(conn, dMgr, 
d1057 1
a1057 1
        return !getApprovedBy().equals(usrGrpMgr.getNobodyUserID(conn));
d1066 1
a1066 2
        DataSet downloadSet = 
            dlMgr.getDownloadsForProject(conn, getID());
d1071 1
a1071 1
            downloads.add(new Download(conn, dMgr, r));
d1084 1
a1084 1
            docMgr.getDocumentsForProject(conn, getID());
d1089 1
a1089 1
            documents.add(new Document(conn, dMgr, r));
d1100 1
a1100 1
        String nobodyID = usrGrpMgr.getNobodyUserID(conn);
d1103 2
a1104 2
        String query = newsMgr.getNewsForProjectQuery(conn, getID());
        n = new PaginatableNewsItemList(conn, dMgr, itemsPerPage, query, 
d1122 3
a1124 3
        String query = newsMgr.getUnapprovedNewsForProjectQuery(conn, getID());
        n = new PaginatableNewsItemList(conn, dMgr, itemsPerPage, query, 
                                    searchCriterion, acl);
d1148 1
a1148 1
        return new Domain(conn, dMgr, getDomainID());
d1326 2
a1327 2
        Record r = uMgr.getUser(conn, userID);
        User u = new User(conn, dMgr, r);
d1336 2
a1337 2
        Record r = uMgr.getUser(conn, userID);
        User u = new User(conn, dMgr, r);
d1346 2
a1347 2
        Record r = uMgr.getUser(conn, userID);
        User u = new User(conn, dMgr, r);
d1413 1
a1413 1
        new Download(conn, dMgr, acl, this, descrip, file, isPublic, url);
d1426 1
a1426 1
        new Section(conn, dMgr, acl, this, parentID, name, descrip);
d1437 1
a1437 3
        DataSet sectionSet = secMgr.getTopLevelSectionsForProject 
                              (conn, getID());

d1441 1
a1441 1
	        sections.add(new Section(conn, dMgr, r));
d1458 1
a1458 2
        DataSet documentSet = docMgr.getDocumentsForProject (conn, getID());

d1463 2
a1464 2
            if (pdsMgr.getSectionIDForDocument(conn, documentID) == null)
	           documents.add(new Document(conn, dMgr, r));
d1477 1
a1477 1
            docMgr.getUnapprovedDocumentsForProject (conn, getID());
d1482 1
a1482 1
            Document document = new Document(conn, dMgr, r);
d1484 2
a1485 2
                   (usrGrpMgr.getNobodyUserID(conn)))
	           documents.add(document);
d1498 1
a1498 1
            secMgr.getUnapprovedSectionsForProject (conn, getID());
d1503 1
a1503 1
            Section section = new Section(conn, dMgr, r);
d1505 1
a1505 1
                   (usrGrpMgr.getNobodyUserID(conn)))
d1525 2
a1526 2
        new Document(conn, dMgr, acl, this, name, descrip, type, 
                     url, text, sectionID, f, htURL);
d1548 2
a1549 2
                             usrGrpMgr.getNobodyUserID(conn));
        newsMgr.updateNews(conn, null, projectID, eventDate, headline, body,
@


1.127
log
@Making use of DBException.
@
text
@d32 1
a32 1
 * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
d69 4
a72 1
import org.joist.database.*;
d439 1
a439 1
            ("org.joist.database.UserManager");        
d455 1
a455 1
            ("org.joist.database.RoleManager");
d722 1
a722 1
            TigrisUpdate.disableAllAccounts(conn, dMgr, acl.getUser(), p);
@


1.126
log
@added getDocuments method

added url for the .htaccess file to argument lists for Document methods
@
text
@d169 1
a169 1
        throws DataSetException, SQLException, AlreadyExists
d231 1
a231 1
        throws DoesNotExist, DataSetException
d241 1
a241 1
        throws SQLException, DataSetException, DoesNotExist
d253 1
a253 1
         throws SQLException, DataSetException, DoesNotExist
d265 1
a265 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
d282 2
a283 3
        throws SQLException, DataSetException, JoistDatabaseException,
               AlreadyExists, UpdateException, ACLException, DoesNotExist,
               JoistException
d334 48
a381 13
        // HELP: special user for system-approved roles?
        String rootUserID = uMgr.getUserForLoginID(conn, "root")
            .getValue(UserManager.USER_ID).asString();
        urpMgr.grantNamedRole(conn, newOwnerID, "Project Owner", 
                              getID(), rootUserID);

        String name = getName(wordMark);
        AnzuTigrisTask.addProject(conn, dMgr, newOwnerID, domainID, name);
        AnzuTigrisTask.setOwnerAlias(conn, dMgr, newOwnerID, getID(), false);

        //Add the project to the appropriate groups.
        ProjectGroup.addToHostGroup(conn, dMgr, this);
        ProjectGroup.addToDomainGroup(conn, dMgr, this, getDomainID());
d383 1
a383 18
        //Approve the project, if user has the right permission.
        if (acl.hasPermissionForDomain("Project - Approve", domainID))
        {
            approve(acl);
        } else {
            //Send a message to the domain admin(s) informing them of
            //the newly requested project.
            User createdUser = User.getInstance(conn, dMgr, acl.getUserID());
            Role role = new Role(conn, dMgr, "Domain Admin", false);
            Domain domain = new Domain(conn, dMgr, domainID);
            String subject = "New unapproved project: " + wordMark;            
            BuildContext ctx = TemplateInterpolator.createContext();
            ctx.put("project", this);
            ctx.put("createdUser", createdUser);
            String body = TemplateInterpolator.interpolate(CREATED_TMPL, ctx, 
                                                           getClass());
            HelmEmailer emailer = new HelmEmailer(conn, dMgr);
            try 
d385 3
a387 2
                emailer.messageUsersWithDomainRole(role, domain, subject, 
                                                   body);
d389 1
a389 1
            catch (JoistException e)
d391 5
a395 1
                log.info("Unable to mail domain admins about new project.");
d398 5
a402 2

        try
d404 1
a404 2
            profile.addDefaultMailingLists(conn, dMgr, getID(), newOwner,
                                           Licenses.isProprietary(license));
d406 1
a406 1
        catch (HandlerException e)
d408 1
a408 5
            log.exception(e);
            if (debug) log.info("HandlerException adding default MLs: " +
                    e.getMessage());
            throw new UpdateException("HandlerException adding default MLs: " +
                    e.getMessage());
d418 1
a418 2
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
d470 1
a470 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
d479 1
a479 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
d485 1
a485 2
        throws SQLException, DataSetException, JoistDatabaseException,
               ACLException, DoesNotExist
d491 1
a491 2
        throws SQLException, DataSetException, JoistDatabaseException,
               ACLException, DoesNotExist
d501 1
a501 2
        throws DataSetException, SQLException, JoistDatabaseException,
               UpdateException, DoesNotExist
d515 1
a515 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist, ACLException
d558 1
a558 1
                getDomainID(), getName());
d574 1
a574 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist, ACLException
d595 1
a595 2
        throws SQLException, DataSetException, JoistDatabaseException,
               JoistException, DoesNotExist, ACLException
d636 1
a636 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist, UpdateException, ACLException
d670 1
a670 1
        throws HandlerException, DataSetException, SQLException, DoesNotExist
d758 1
a758 1
    throws DataSetException
d789 1
a789 1
	throws DataSetException, SQLException
d803 1
a803 1
        throws SQLException, DataSetException, JoistDatabaseException
d828 1
a828 1
        throws DataSetException, SQLException, DoesNotExist
d846 1
a846 1
        throws DataSetException, SQLException, DoesNotExist
d862 1
a862 1
        throws DataSetException, SQLException, JoistDatabaseException,
d869 1
a869 2
        throws DataSetException, SQLException, JoistDatabaseException,
               DoesNotExist
d896 1
a896 1
        throws DataSetException, SQLException, JoistDatabaseException,
d899 2
a900 2
        DataSet userSet = urpMgr.getUsersForProject(conn, 
                                                    getID(), Boolean.FALSE);
d915 1
a915 1
        throws DataSetException, SQLException, JoistDatabaseException,
d918 1
a918 2
        DataSet roleSet = urpMgr.getRequestedRolesForProject(conn, 
                                                    getID());
d932 1
a932 1
        throws DataSetException, SQLException, JoistDatabaseException,
d951 1
a951 1
        throws DataSetException, SQLException, DoesNotExist
d955 1
a955 2
        DataSet mailingListSet = mlMgr.listProjectMailingLists(conn, 
                                                               getID());
d974 1
a974 2
        throws SQLException, DataSetException, DoesNotExist, 
               JoistDatabaseException
d994 1
a994 1
        throws DataSetException
d1004 1
a1004 1
        throws DataSetException
d1026 1
a1026 1
        throws DataSetException
d1033 1
a1033 1
        throws DataSetException
d1040 1
a1040 1
        throws DataSetException
d1047 1
a1047 1
        throws DataSetException
d1054 1
a1054 1
        throws DataSetException
d1061 1
a1061 1
        throws DataSetException
d1067 1
a1067 1
        throws JoistDatabaseException, DataSetException, SQLException
d1073 1
a1073 1
        throws DataSetException, SQLException, DoesNotExist
d1091 1
a1091 1
        throws DataSetException, SQLException, DoesNotExist
d1110 1
a1110 1
        throws DataSetException, SQLException, DoesNotExist, ParseException,
d1123 1
a1123 1
        throws DataSetException, SQLException, DoesNotExist, ParseException,
d1131 1
a1131 1
        throws DataSetException, SQLException, DoesNotExist, ParseException,
d1142 1
a1142 1
        throws DataSetException, SQLException, DoesNotExist, ParseException,
d1153 1
a1153 1
        throws DataSetException
d1159 1
a1159 1
        throws DataSetException, SQLException, JoistDatabaseException, DoesNotExist
d1165 1
a1165 1
        throws DataSetException, SQLException, JoistDatabaseException, DoesNotExist
d1171 1
a1171 1
        throws DataSetException
d1173 8
a1180 1
        return rec.getValue(ProjectManager.PROJECT_DOMAIN_ID).asString();
d1184 1
a1184 1
        throws DataSetException, SQLException, JoistDatabaseException
d1193 1
a1193 1
        throws DataSetException, SQLException
d1202 1
a1202 1
        throws DataSetException
d1216 1
a1216 1
        throws DataSetException
d1218 8
a1225 1
        return rec.getValue(ProjectManager.PROJECT_NAME).asString();
d1229 1
a1229 1
        throws DataSetException
d1231 8
a1238 1
        return rec.getValue(ProjectManager.PROJECT_LICENSE).asString();
d1242 1
a1242 1
        throws DataSetException
d1244 9
a1252 2
        return rec.getValue(ProjectManager.PROJECT_SHORT_DESCRIPTION)
            .asString();
d1256 1
a1256 1
        throws DataSetException
d1258 9
a1266 2
        return DBFlag.boolValueOf
            (rec.getValue(ProjectManager.USE_INDEX).asString());
d1276 1
a1276 1
        throws DataSetException
d1290 1
a1290 1
        throws DataSetException
d1329 1
a1329 1
        throws DataSetException
d1335 1
a1335 1
        throws DataSetException, JoistDatabaseException, SQLException,
d1345 1
a1345 1
        throws DataSetException, JoistDatabaseException, SQLException,
d1355 1
a1355 1
        throws DataSetException, JoistDatabaseException, SQLException,
d1365 1
a1365 1
        throws DataSetException
d1371 1
a1371 1
        throws DataSetException
d1377 1
a1377 1
        throws DataSetException
d1379 8
a1386 1
        return rec.getValue(ProjectManager.PROJECT_TYPE).asString();
d1390 1
a1390 1
        throws DataSetException
d1403 1
a1403 1
        throws DataSetException
d1423 2
a1424 2
        throws ACLException, DataSetException, SQLException, UpdateException, 
               JoistDatabaseException, IOException, DoesNotExist
d1436 2
a1437 3
        throws ACLException, DataSetException, SQLException,
               JoistDatabaseException, IOException, 
               DoesNotExist, UpdateException
d1446 1
a1446 2
        throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
d1468 1
a1468 1
        throws DataSetException, SQLException, DoesNotExist, ParseException,
d1488 1
a1488 2
       throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
d1492 2
a1493 1
        DataSet documentSet = docMgr.getUnapprovedDocumentsForProject (conn, getID());
d1509 1
a1509 2
       throws DataSetException, SQLException, DoesNotExist, ParseException,
               JoistDatabaseException
d1513 2
a1514 1
        DataSet sectionSet = secMgr.getUnapprovedSectionsForProject (conn, getID());
d1538 1
a1538 2
        throws ACLException, DataSetException, SQLException,
               JoistDatabaseException, IOException, DoesNotExist,
d1555 1
a1555 2
        throws ACLException, DataSetException, SQLException,
               JoistDatabaseException, IOException, DoesNotExist
d1566 2
a1567 1
	            approvedBy, publishDate, removeDate, priority, acl.getUserID());
d1584 1
a1584 1
        throws IOException, DataSetException, SQLException, DoesNotExist
d1653 1
a1653 1
        throws DataSetException
d1669 1
a1669 1
        throws NullPointerException, IllegalArgumentException, DataSetException
d1699 1
a1699 1
     * @@exception DataSetException Thrown by getName( ).
d1702 1
a1702 1
        throws NullPointerException, IllegalArgumentException, DataSetException
d1704 2
a1705 1
        return buildProjectPageURL("ProjectHome", null, inProtocol, false, true);
d1709 1
a1709 1
        throws NullPointerException, DataSetException
d1730 1
a1730 1
        throws NullPointerException, DataSetException
d1740 1
a1740 1
        throws NullPointerException, DataSetException
d1755 1
a1755 1
        throws NullPointerException, DataSetException
d1765 1
a1765 1
        throws NullPointerException, DataSetException
d1776 1
a1776 1
        throws NullPointerException, DataSetException
d1786 1
a1786 1
        throws NullPointerException, DataSetException
d1797 1
a1797 1
        throws NullPointerException, DataSetException
d1829 1
a1829 1
        throws NullPointerException, DataSetException
@


1.125
log
@Put user groups first and sort results.
@
text
@d1085 18
d1490 3
a1492 3
                             String descrip, String location,
                             String url, String text,
                             String sectionID)
d1497 2
a1498 2
        new Document(conn, dMgr, acl, this, name, descrip, location, 
                     url, text, sectionID);
d1611 1
a1611 1
        // If the file requested is private, set the prjoectID bit.
@


1.124
log
@Expand project before running creation scripts.
@
text
@d867 1
d872 6
a877 1
            userList.add(u);
d880 5
a884 1
        return new PaginatablePrebuiltList(itemsPerPage, userList);
@


1.123
log
@* Renamed isPublicDownload parameter to isPublicFile.
* Clarified JavaDoc for isPublicFile.
@
text
@d402 1
a402 2
        TigrisUpdate.addProject(conn, dMgr, initiatingUser, this);
        if (getProfile().isAutoPublishedToWeb())
d404 7
a410 2
            TigrisUpdate.addModule(conn, dMgr, null, this, "www",
                                   "Web publishing module", "1");
@


1.123.2.1
log
@Moving revision 1.124 into 092 to fix IZ 2156, 'IZ generating 'internal server errors'
@
text
@d402 2
a403 1
        for (Iterator i = expand().iterator(); i.hasNext();)
d405 2
a406 7
            Project p = (Project)i.next();
            TigrisUpdate.addProject(conn, dMgr, initiatingUser, p);
            if (p.getProfile().isAutoPublishedToWeb())
            {
                TigrisUpdate.addModule(conn, dMgr, null, p, "www",
                                       "Web publishing module", "1");
            }
@


1.123.2.2
log
@Porting changes from HEAD into branch.
@
text
@d740 1
a740 1
            if (getID().equals(p.getID()))
@


1.123.2.3
log
@moved changed from HEAD for ProjectDocuments and ProjectDownloads
@
text
@a866 1
        ArrayList userGroupList = new ArrayList();
d871 1
a871 6
            if (u.isGroup())
            {
                userGroupList.add(u);
            } else {
                userList.add(u);
            }
d874 1
a874 5
        Collections.sort(userList);
        Collections.sort(userGroupList);
        userGroupList.addAll(userList);

        return new PaginatablePrebuiltList(itemsPerPage, userGroupList);
a1074 18
    public List getDocuments ()
        throws DataSetException, SQLException, DoesNotExist
    {
        List documents = new ArrayList();

        // Get all downloads for this project
        DataSet documentSet = 
            docMgr.getDocumentsForProject(conn, getID());
        Record r;
        for (int i = 0; i < documentSet.size(); i++)
        {
            r = documentSet.getRecord(i);
            documents.add(new Document(conn, dMgr, r));
        }

        return documents;
    }

d1406 1
a1406 1
            if (pdsMgr.getSectionIDForDocument(conn, documentID).equals("0"))
d1462 3
a1464 3
                             String descrip, String type,
                             File f, String url, String text,
                             String sectionID, String htURL)
d1469 2
a1470 2
        new Document(conn, dMgr, acl, this, name, descrip, type, 
                     url, text, sectionID, f, htURL);
d1520 2
a1521 10

        // If not in vhosting mode, append projectID as cgi param
        org.joist.util.JoistProperties properties
            = org.joist.util.JoistProperties.getInstance( );
        if( properties == null )
            throw new NullPointerException( "JoistProperties is null" );
        if (!isVhosting(properties))
        {
            url = URL.appendCGIParam(url, "projectID", getID());
        }
a1565 26
            List documents = getDocuments();
            int nbrDocuments = documents.size();
            for (int i = 0; i < nbrDocuments; i++)
            {
                Document dc = (Document)documents.get(i);

                out.write("<Files \"");
                out.write(dc.getName());
                out.write("\">\n");
                out.write("AuthName MDAAuth\n");
                out.write("AuthType Basic\n");
                out.write("require valid-user\n");
                out.write("MDARealmMask      \"");
                out.write(generateMDARealmMask(dc.isPublic().booleanValue()));
                out.write("\"\n");
                out.write("MDAAuthLoginURL   \"");
                out.write(url);
                out.write("\"\n");
                out.write("MDAAuthTimeoutURL \"");
                out.write(URL.appendCGIParam
                          (url, MESSAGE, "Document authorization timed out."));
                out.write("\"\n");
                out.write("MDAAuthTimeoutMin 1\n");
                out.write("</Files>\n");
                if (i < nbrDocuments - 1) out.write('\n');
            }
d1583 1
a1583 1
        // If the file requested is private, set the projectID bit.
@


1.122
log
@How about making sure a new business object initializes properly before committing code that puts it into HelmServlet.
@
text
@d1571 4
a1574 3
     * @@param isPublicDownload Whether the download requires auth.
     * @@return                 The hexidecimal representation of the project's 
     *                         unique identifier.
d1576 1
a1576 1
    public String generateMDARealmMask (boolean isPublicDownload)
d1580 1
a1580 1
        BigInteger i = (isPublicDownload ?
@


1.121
log
@Allow a special Helm task to initialize  project resources.
@
text
@d957 1
a957 1
        Skin s = Skin.getSkin(conn, dMgr, getID());
d961 1
a961 1
                             getDomain().getSpecialProject().getID());
d966 1
a966 1
                             getHost().getSpecialProject().getID());
d969 9
@


1.120
log
@added getUnapprovedSections method
@
text
@d312 1
a312 6
        TigrisUpdate.addProject(conn, dMgr, acl.getUserID(), this);
        if (profile.isAutoPublishedToWeb())
        {
            TigrisUpdate.addModule(conn, dMgr, null, this, "www",
                                   "Web publishing module", "1");
        }
d393 17
a705 1
            TigrisUpdate.addProject(conn, dMgr, acl.getUser().getID(), p);
d811 3
d829 3
d969 22
@


1.119
log
@Use templates to generate the email message bodies for project
creation and disapproval.
@
text
@d1383 20
d1411 2
a1412 1
                             String url, String text, String sectionID)
@


1.118
log
@Another big batch of skin changes.
@
text
@d62 1
d113 12
d366 5
a370 6
            StringBuffer body = new StringBuffer();
            body.append(createdUser.getName()).append(" has started the ")
                .append(wordMark).append(" project.\n");
            body.append("Please approve or disapprove this project at ")
                .append("your convenience.\n\n");
            body.append("Project description:\n").append(longDescription);
d375 4
a378 2
                                                   body.toString());
            } catch (JoistException e) {
d383 2
a384 1
        try {
d387 3
a389 1
        } catch (HandlerException e) {
d581 5
a585 8
        StringBuffer body = new StringBuffer();
        body.append("Sorry, your request for hosting of the ")
            .append(getWordMark()).append(" project has been disapproved.\n")
            .append("You can no longer access any resources for the ")
            .append(getWordMark()).append(" project on the site.\n\n")
            .append("For more information, please contact ")
            .append(disapprovingUser.getName()).append(" (")
            .append(disapprovingUser.getEmail()).append(')');
d590 4
a593 3
            emailer.messageUsersWithProjectRole(role, this, subject, 
                                                body.toString());
        } catch (JoistException e) {
@


1.117
log
@added getUnapprovedDocuments method

added arguments for new fields
@
text
@d939 4
@


1.116
log
@Fall back to domain or host skin if project doesn't have one.
@
text
@d1343 22
d1371 2
a1372 2
                             String location, String descrip, 
                             String sectionID)
d1377 2
a1378 1
        new Document(conn, dMgr, acl, this, name, location, descrip, sectionID);
@


1.115
log
@Allow project to get its skin.
@
text
@d917 3
a919 1
     * Return the Skin for this project.
d922 2
a923 1
        throws SQLException, DataSetException, DoesNotExist
d925 12
a936 1
        return Skin.getSkin(conn, dMgr, getID());
@


1.114
log
@fixed null pointer error in getTopLevelDocuments method
@
text
@d916 9
@


1.113
log
@added getSectionIDForDocument method
@
text
@d1312 1
a1312 1
            if (pdsMgr.getSectionIDForDocument(conn, documentID).equals("0"))
@


1.112
log
@Get affected users for issue tracking sync properly.
@
text
@d1312 1
a1312 1
            if (pdsMgr.isTopLevelDocument(conn, documentID))
@


1.111
log
@Fixes related to IssueTrackingRebuild.
@
text
@d666 2
a667 6
        List users = getDomain().getUsers();
        users.addAll(getHost().getUsers());
        
        //If a project group (not a domain or host project), 
        //add this project to the list of projects to be considered.
        if (this.isGroup() && !this.isDomain() && !this.isHost())
d669 4
a672 1
            projects.add(this);
d678 3
a680 1
            TigrisUpdate.disableAllAccounts(conn, dMgr, acl.getUser(), (Project)i.next());
a681 1

@


1.110
log
@New servlet and support for same: IssueTrackingRebuild
@
text
@a661 2
        //First, disable everybody.
        TigrisUpdate.disableAllAccounts(conn, dMgr, acl.getUser(), this);
d671 1
a671 1
        if (this.isGroup())
d674 6
@


1.109
log
@Big patch bringing the smart script runner online.
@
text
@d71 1
d73 1
a73 7
import org.tigris.helm.domain.BusinessObject;
import org.tigris.helm.domain.Category;
import org.tigris.helm.domain.User;
import org.tigris.helm.domain.NewsItem;
import org.tigris.helm.domain.ProjectGroup;
import org.tigris.helm.domain.Role;
import org.tigris.helm.domain.Domain;
d653 32
d1031 6
@


1.108
log
@Big patch implementing a pilot test of the smart 'determine which scripts to run' system.
@
text
@d1000 6
@


1.107
log
@Get the index.html file from the right location.
@
text
@d713 19
@


1.106
log
@First use of PaginatablePrebuiltList
@
text
@d67 1
d1045 20
d1069 2
a1070 2
        String flag = rec.getValue(ProjectManager.USE_INDEX).asString();
        if (DBFlag.booleanValueOf(flag))
d1075 2
a1076 1
                FileReader reader = new FileReader(INDEX_FILE);
@


1.105
log
@added methods for adding and getting documents and sections
@
text
@d765 8
a772 1
    public List getUsers()
d787 1
a787 1
        return userList;
@


1.104
log
@Support both word mark and unstylized names.
@
text
@d134 3
d406 6
d1168 76
@


1.103
log
@minor reformatting
@
text
@d107 2
a108 1
    private static final String PROJECT_NAME_RE = "^[a-z0-9][-a-z0-9]{0,63}$";
d136 5
d199 9
d262 2
d266 1
a266 1
                   ProjectProfile profile, String domainID, String name, 
d287 1
a287 1
            Project.assertNonexistance(conn, dMgr, domainID, name);
d291 1
a291 1
            setRecord(pMgr.addProject(conn, profile, domainID, name, 
d335 1
d353 1
a353 1
            String subject = "New unapproved project: " + name;            
d356 1
a356 1
                .append(name).append(" project.\n");
d484 2
a485 2
            if (debug) log.info("Removing project " + getName() +
                                " from group " + p.getName());
d500 3
a502 2
                if (debug) log.info("unable to delete ml " + ml.getName() +
                        " in project " + getName() + " : " + e);
d558 1
a558 1
        String subject = "Project " + getName() + " disapproved.";
d561 1
a561 1
            .append(getName()).append(" project has been disapproved.\n")
d563 1
a563 1
            .append(getName()).append(" project on the site.\n\n")
d985 3
d989 14
@


1.102
log
@Many, many pagination changes.
@
text
@d541 5
a545 5
        body.append("Sorry, your request for hosting of the ").
            append(getName()).append(" project has been disapproved.\n");
        body.append("You can no longer access any resources for the ")
            .append(getName()).append(" project on the site.\n\n");
        body.append("For more information, please contact ")
d547 1
a547 1
            .append(disapprovingUser.getEmail()).append(")");
@


1.101
log
@Updated to support new HELM_PROJECT.USE_INDEX field (may make use of new DBFlag class to do so).
@
text
@d79 1
d81 1
a81 1
import org.tigris.helm.tool.mail.MailingList;
d895 2
a896 1
    public List getNews ()
d900 1
a900 1
        List newsItems = new ArrayList();
d902 6
a907 3
        // Get all news items 
        DataSet newsItemSet = newsMgr.getNewsForProject 
                              (conn, getID());
d909 6
a914 7
        for (int i = 0; i < newsItemSet.size(); i++)
        {
            Record r = newsItemSet.getRecord(i);
	        newsItems.add(new NewsItem(conn, dMgr, r));
        }

        return newsItems;
d916 10
d928 1
a928 1
    public List getUnapprovedNews ()
d932 2
a933 6
        List newsItems = new ArrayList();
        String nobodyID = usrGrpMgr.getNobodyUserID(conn);

        // Get all news items 
        DataSet newsItemSet = newsMgr.getNewsForProject 
                              (conn, getID(), nobodyID);
a934 9
        for (int i = 0; i < newsItemSet.size(); i++)
        {
            Record r = newsItemSet.getRecord(i);
	        newsItems.add(new NewsItem(conn, dMgr, r));
        }

        return newsItems;

    }
@


1.100
log
@printing a different confirmation message for adding a news item, depending on if user has permissions to approve item
@
text
@d79 1
a80 1
import org.tigris.helm.tool.*;
d248 4
a251 4
                   ProjectProfile profile,
                   String domainID, String name, String license,
                   String shortDescription, String longDescription,
                   String status, String aliasURL,  
d275 1
a275 1
                                      longDescription, "", aliasURL,
d305 2
d566 1
d593 2
a594 1
                               longDescription, status, aliasURL);
d984 7
d995 2
a996 3
        String flag =
            rec.getValue(ProjectManager.USE_INDEX).asString();
        if (booleanValueOf(flag).booleanValue())
@


1.99
log
@If desired and available, use index.html.
@
text
@d1118 1
a1118 1
    public void addNewsItem (AccessControlList acl, Date eventDate,
d1125 1
d1135 5
@


1.98
log
@Removed unnecessary getCache() implementations in BusinessObject subclasses and migrated to a factory method for User's primary database key ctor.
@
text
@d983 32
a1014 10
        // TODO: Check for alternate description.
        //String flag =
        //    rec.getValue(ProjectManager.USE_INDEX).asString();
        //if (flag)
        //{
        //    // Dump the contents of the alternate description file.
        //    FileReader reader = new FileReader(INDEX_FILE);
        //}
        //else
        //{
a1016 1
        //}
@


1.97
log
@- Initial work for USE_INDEX field.
- Propogated object cache interface.
@
text
@a102 5
    protected Dictionary getCache ()
    {
        return null;
    }

d303 1
a303 1
            newOwner   = new User(conn, dMgr, newOwnerID);
d329 1
a329 1
            User createdUser = new User(conn, dMgr, acl.getUserID());
d535 1
a535 1
        User disapprovingUser = new User(conn, dMgr, acl.getUserID());
d761 1
a761 1
            User u = new User(conn, dMgr, userID);
d799 1
a799 1
            User user = new User(conn, dMgr, userID);
@


1.96
log
@added getUnapprovedNews method
@
text
@d98 9
a106 1
    protected final String getTableName() { return ProjectManager.TABLE_NAME; }
d114 5
d988 10
d1000 1
@


1.95
log
@Run ProjectCreate before MemberAdd.
@
text
@d883 2
a884 1
        throws DataSetException, SQLException, DoesNotExist, ParseException
d890 1
a890 1
                    (conn, getID());
d895 22
a916 1
	    newsItems.add(new NewsItem(conn, dMgr, r));
d1080 2
a1081 2
			     Date publishDate, Date removeDate,
			     String priority)
d1086 1
a1086 2
	// TODO: create Project News - Suggest and Add actions
        String action = "Project News - View";
d1088 1
a1088 2
        log.info("Project ID for add news item: "+ projectID);
        action = "Project News - Add";
d1093 1
a1093 1
	                   approvedBy, publishDate, removeDate, priority);
@


1.94
log
@Create mailing lists last so that an Anzu crash won't leave the project in an inconsistent state.
@
text
@d272 8
a308 8

        // Add the project to CVS, Issuezilla, etc.
        TigrisUpdate.addProject(conn, dMgr, acl.getUserID(), this);
        if (profile.isAutoPublishedToWeb())
        {
            TigrisUpdate.addModule(conn, dMgr, null, this, "www",
                                   "Web publishing module", "1");
        }
@


1.93
log
@accessing object via ID's rather than records, in getRequestedRoles() and getRequestedUsers()
@
text
@a301 11
        try {
            profile.addDefaultMailingLists(conn, dMgr, getID(), newOwner,
                                           Licenses.isProprietary(license));
        } catch (HandlerException e) {
            log.exception(e);
            if (debug) log.info("HandlerException adding default MLs: " +
                    e.getMessage());
            throw new UpdateException("HandlerException adding default MLs: " +
                    e.getMessage());
        }

d339 11
@


1.92
log
@- corrected comment
- ifdef'd trace
@
text
@d752 2
a753 1
            User u = new User(conn, dMgr, r);
d771 2
a772 1
            Role role = new Role(conn, dMgr, r);
@


1.91
log
@Removed use of deprecated class.
@
text
@d449 1
a449 1
        // TODO;Delete this project's version control.
d455 2
a456 1
            log.info("Removing project " + getName() + " from group " + p.getName());
@


1.90
log
@An appropriate project object can now be turned into a Category or ProjectGroup object.
@
text
@a444 2
        ModuleManager modMgr = (ModuleManager)
            dMgr.getManager("org.tigris.helm.database.ModuleManager");
d449 2
a450 3
        //Delete this project's modules.
        modMgr.deleteModulesForProject(conn, getID());
        
@


1.89
log
@* handle deleting EB lists when it's time (unfortunately, this doesn't yet
  delete the archives themselves)
* minor argument changes (User to String userID)
@
text
@d647 26
a723 9
    }

    public List getCategoryProjects(AccessControlList acl)
        throws DataSetException, SQLException, DoesNotExist
    {
        DataSet projectSet = 
            pMgr.getProjectsForCategory(conn, getID());
        return AccessControlledDatabaseFilter.getViewableProjects
            (conn, dMgr, acl, projectSet);
@


1.88
log
@* adjust for corrections to Role constructor
* correct another Role constructor which listed the DataManager before
  the Connection
@
text
@d465 14
a478 1
        // This takes care of deleting all the mailing lists, alias, etc.:
@


1.87
log
@* handle project deletion w/ anzu
* switch some method signatures in AnzuTigrisTask and add deleteProject
* switch from remove to delete where appropriate (when removing an
  object entirely, rather than just removing it from a container)
@
text
@d333 1
a333 1
            Role role = new Role(dMgr, conn, "Domain Admin", false);
d526 1
a526 1
        Role role = new Role(dMgr, conn, "Project Owner", false);
@


1.86
log
@Death to project modules!
@
text
@d299 2
a300 1
        AnzuTigrisTask.setOwnerAlias(conn, dMgr, newOwner, getID(), false);
a301 4
        // Add the mailing lists and modules for the project.
        // Please note that addDefaultMailingLists also takes care of
        // adding the project itself to anzu.  Perhaps the name should
        // change to addProjectMailSetup or somesuch.
d464 4
a469 2
        
        //TODO: Delete this project's mailing lists.           
@


1.85
log
@Corrected bugs in and wrote first usage of audit logging.
@
text
@d317 6
a322 6
        TigrisUpdate.addProject
            (conn, dMgr, acl.getUserID(), this);

        profile.addDefaultModules(conn, dMgr,
                                  domainName, name, getID(), 
                                  null);  
@


1.84
log
@Merged duplicate download addition code into a Download ctor.  Made Download.edit() regenerate the .htaccess file.
@
text
@a353 1
        
@


1.83
log
@Changed IS_PRIVATE to IS_PUBLIC--propogating all the way through to the UI.
@
text
@d1009 5
a1013 5
     * @@param acl       The ACL of the user doing the add.
     * @@param files     The <code>File</code> to add.
     * @@param descrip   The descriptions of the file to add.
     * @@param isPrivate A flag indicating whether the file is private.
     * @@param url       The authorization and timeout URL.
d1016 2
a1017 2
                             String isPrivate, String url)
        throws ACLException, DataSetException, SQLException,
d1020 1
a1020 18
        //To add a download you need either Suggest or Approve permission.
        String projectID = getID();
        String suggest = "Project Download - Suggest";
        String approve = "Project Download - Approve";
        if (!acl.hasPermissionForProject(suggest, projectID) 
            && !acl.hasPermissionForProject(approve, projectID))
        {
            //Assert a permission we know they don't have to cause an
            //exception.
            acl.assertPermissionForProject(suggest, projectID);
        }
        log.info("Project ID for adddownload: "+ projectID);
        String approvedBy = (acl.hasPermissionForProject(approve, projectID) ?
                             acl.getUserID() : 
                             usrGrpMgr.getNobodyUserID(conn));
        dlMgr.addDownload(conn, projectID, file, descrip, acl.getUserID(), 
                          approvedBy, isPrivate);
        writeHtaccessFile(file.getParentFile().getAbsolutePath(), url);
d1056 1
a1056 1
    private void writeHtaccessFile (String path, String url)
@


1.82
log
@support for owner aliases -- basically, owner@@{project}.{domain}
is an alias which sends e-mail to each of the people who's listed
as project owner for {project}.
@
text
@d1115 1
a1115 1
                out.write(generateMDARealmMask(d.isPrivate().booleanValue()));
d1137 3
a1139 3
     * @@param isPrivateDownload Whether the download requires auth.
     * @@return                  The hexidecimal representation of the 
     *                          project's unique identifier.
d1141 1
a1141 1
    public String generateMDARealmMask (boolean isPrivateDownload)
d1145 3
a1147 3
        BigInteger i = (isPrivateDownload ?
                        BigInteger.ZERO.setBit(Integer.parseInt(getID())) :
                        BigInteger.ZERO);
@


1.81
log
@
Overloaded getProjectFileURL()
@
text
@d298 3
a300 1
        
@


1.80
log
@New method to allow you to get the appropriate project URL without '/servlets/' in there
@
text
@d1256 21
d1287 1
@


1.79
log
@Added a default project name constant.
@
text
@d1191 1
a1191 1
        return buildProjectPageURL("ProjectHome", null, inProtocol, false);
d1198 1
a1198 1
            ("ProjectMembers", null, "http", false);
d1218 1
a1218 1
        return buildProjectPageURL(page, null, null, false);
d1231 1
a1231 1
        return buildProjectPageURL(page, queryArgs, null, false);
d1243 1
a1243 1
        return buildProjectPageURL(page, queryArgs, inProtocol, true);
d1253 12
a1264 1
        return buildProjectPageURL(page, queryArgs, inProtocol, false);
d1290 3
a1292 2
    private String buildProjectPageURL(String page, String queryArgs,
            String inProtocol, boolean forceFullyQualifiedDomain)
d1328 3
a1330 1
        buff.append(SERVLET_PREFIX).append(page);
@


1.78
log
@Fix inability of root to create approved projects.
@
text
@d85 5
d204 1
a204 1
    public Project(Connection conn, DataManager dMgr, String projectID)
d215 2
a216 2
     public Project(Connection c, DataManager dMgr, 
                   String domainID, String name)
d227 2
a228 2
    public Project(Connection c, DataManager dMgr, String domainID, 
                   String aliasURL, boolean ignore)
a784 10
    }

    public boolean exists()
    {
        try {
            String test = getID();
        } catch (Exception e) { // assume it's bad
            return false;
        }
        return true;
@


1.77
log
@Enabled security check of records passed into business objects.
@
text
@a266 27

        //Approve the project, if user has the right permission.
        if (acl.hasPermissionForDomain("Project - Approve", domainID))
        {
            approve(acl);
        } else {
            //Send a message to the domain admin(s) informing them of
            //the newly requested project.
            User createdUser = new User(conn, dMgr, acl.getUserID());
            Role role = new Role(dMgr, conn, "Domain Admin", false);
            Domain domain = new Domain(conn, dMgr, domainID);
            String subject = "New unapproved project: " + name;            
            StringBuffer body = new StringBuffer();
            body.append(createdUser.getName()).append(" has started the ")
                .append(name).append(" project.\n");
            body.append("Please approve or disapprove this project at ")
                .append("your convenience.\n\n");
            body.append("Project description:\n").append(longDescription);
            HelmEmailer emailer = new HelmEmailer(conn, dMgr);
            try 
            {
                emailer.messageUsersWithDomainRole(role, domain, subject, 
                                                   body.toString());
            } catch (JoistException e) {
                log.info("Unable to mail domain admins about new project.");
            }
        }
d287 6
d320 27
a347 5
        // HELP: special user for system-approved roles?
        String rootUserID = uMgr.getUserForLoginID(conn, "root")
            .getValue(UserManager.USER_ID).asString();
        urpMgr.grantNamedRole(conn, newOwnerID, "Project Owner", 
                              getID(), rootUserID);
@


1.76
log
@Added a check so that business objects cannot be created with records from the wrong table. Also added some new business objects.
@
text
@d93 2
@


1.75
log
@Added support for resigning your own roles.
@
text
@d188 1
a188 1
        throws DoesNotExist
@


1.74
log
@Straightened out permissions a bit.
@
text
@d789 14
@


1.73
log
@Made use of URL.DEFAULT_PROTOCOL and added TODO item.
@
text
@d1006 1
d1008 9
a1016 2
        String action = "Project Download - Suggest";
        acl.assertPermissionForProject(action, projectID);
d1018 1
a1018 2
        action = "Project Download - Approve";
        String approvedBy = (acl.hasPermissionForProject(action, projectID) ?
@


1.72
log
@ProjectGroupDelete should work now (as should project deletion in general)
@
text
@d17 1
a17 1
 * software developed by CollabNet (http://www.Collab.Net/)."
d1058 2
a1059 1
            url = "http://" + InetAddress.getLocalHost().getHostName() + '/';
d1061 1
@


1.71
log
@add a new version of this method
@
text
@d432 5
a436 2
        acl.assertPermissionForProject("Project - Delete", getID());
        
a673 1
            log.info("I belong to group " + p.getName());
d794 7
@


1.71.2.1
log
@merged in changes from HEAD
@
text
@d17 1
a17 1
 * software developed by CollabNet (http://www.collab.net/)."
d432 2
a433 5
        if (isGroup())
            acl.assertPermissionForDomain("ProjectGroup - Delete", 
                                          getDomainID());
        else
            acl.assertPermissionForProject("Project - Delete", getID());
d671 1
a793 7
    public boolean isGroup()
        throws DataSetException
    {
        String type = getType();
        return !(type.equals(ProjectManager.BASE_PROJECT_TYPE));
    }

d1049 1
a1049 2
            url = URL.DEFAULT_PROTOCOL + "://" +
                InetAddress.getLocalHost().getHostName() + '/';
a1050 1
        // TODO: Only append when not vhosted
@


1.71.2.2
log
@changes to support owner email aliases.  tested in head, tested in
branch, and ok'ed by jr.
@
text
@a311 1
        AnzuTigrisTask.setOwnerAlias(conn, dMgr, newOwner, getID(), false);
@


1.70
log
@Changes to fix horrible mistakes in removing projects from project groups, among other things.
@
text
@d1182 10
@


1.69
log
@correct the order of these operations -- doing them wrong means that
the scripts try to add IZ members to projects before the IZ project
database has been created yet ... ops.
@
text
@d284 7
a290 2
            emailer.messageUsersWithDomainRole(role, domain, subject, 
                                                    body.toString());
d448 3
a450 1
            ((ProjectGroup)i.next()).removeProjectNoPerms(this);
a463 1
        String domainName = domMgr.getDomainName(getDomainID());
d465 1
a465 2
        TigrisUpdate.deleteProject
            (conn, dMgr, acl.getUserID(), this);
d517 7
a523 2
        emailer.messageUsersWithProjectRole(role, this, subject, 
                                            body.toString());
d664 1
a664 1
            prjGrpMgr.getBasesForComposite(conn, getID());
d669 1
a669 1
            String projectID = r.getValue(ProjectManager.PROJECT_ID).asString();
d671 1
@


1.68
log
@this bug was hidden by the fact that there always happened to be a
project with the same id as the domain -- 2.  an add'l exception
has been added to the throws.
@
text
@a265 4
        //Add the project to the appropriate groups.
        ProjectGroup.addToHostGroup(conn, dMgr, this);
        ProjectGroup.addToDomainGroup(conn, dMgr, this, getDomainID());

d330 4
@


1.67
log
@use TigrisUpdate after creating the mailing lists, so as to avoid
the possibility of cvs commit messages being sent before the cvs
mailing list is created
@
text
@d855 1
a855 1
        throws DataSetException, SQLException
d857 1
a857 1
        return pMgr.getProjectDomain(conn, getDomainID());
@


1.66
log
@Mega patch which makes script data persistent and which provides a general framework for tasks to be run (which will be used by anzu eventually)
@
text
@a262 1
            // Add the project to CVS, Issuezilla, etc.
a263 2
            TigrisUpdate.addProject
                (conn, dMgr, acl.getUserID(), this);
d326 5
@


1.65
log
@rudimentary docs, and a new method which could be used within templates
to avoid the ugliness of adding projectID=$currentProject.getID()
to every link.
@
text
@d265 2
a266 2
            TigrisUpdate.addProject(domainName, name, getID(), null, 
                                    shortDescription);
d457 2
a458 1
        TigrisUpdate.deleteProject(domainName, getName(), getID(), null);
@


1.64
log
@remove debugging breadcrumb trail which was accidentally commited
@
text
@d1167 18
d1192 3
@


1.63
log
@Fixed a bug--project group deletion still needs work.
@
text
@a318 3
        System.err.println("adding mailing lists; isProprietary? " +
                Licenses.isProprietary(license) + " from license " +
                license);
@


1.62
log
@added getOwners() method
@
text
@d659 2
a660 1
            ProjectGroup p = new ProjectGroup(conn, dMgr, r);
@


1.61
log
@handle setting the type correctly when creating mailing lists.  this
involves changing the throws slightly ... hence the changes in
project/*Profile and project/Project  ... try to avoid unnecessary
additional exceptions when possible.
@
text
@d117 1
d362 2
d725 19
@


1.60
log
@All project group activity now goes through the ProjectGroup object.
@
text
@d321 10
a330 2
        profile.addDefaultMailingLists(conn, dMgr, getID(), newOwner,
                                       Licenses.isProprietary(license));
@


1.59
log
@added getRequestedRoles method
@
text
@d269 2
a270 3
        prjGrpMgr.addProjectToGroup(conn, getID(), pMgr.getHostProjectID());
        prjGrpMgr.addProjectToGroup(conn, getID(), 
                                    pMgr.getDomainProjectID(domainID));
d364 1
a364 1
        throws DataSetException, SQLException, JoistDatabaseException,
d367 1
a367 1
        prjGrpMgr.addProjectToGroup(conn, getID(), cat.getID());
d374 1
a374 1
        throws DataSetException, SQLException, JoistDatabaseException,
d377 15
a391 1
        prjGrpMgr.removeProjectFromGroup(conn, getID(), cat.getID());
d430 5
a434 2
        //Remove it from its groups.
        prjGrpMgr.removeProjectFromGroups(conn, getID());
d470 1
a470 6
            ProjectProjectGroupManager prjGrpMgr = (ProjectProjectGroupManager)
                dMgr.getManager
                ("org.tigris.helm.database.ProjectProjectGroupManager");
            prjGrpMgr.addProjectToGroup(conn, getID(), 
                                        pMgr.getPublicDomainProjectID 
                                        (getDomainID()));
d637 15
@


1.58
log
@Made message more helpful.
@
text
@d673 17
@


1.57
log
@Added messaging of project owners on disapproval.
@
text
@d476 1
a476 1
        
d478 1
d480 8
a487 1
        String body = "The " + getName() + " project has been disapproved by the administrators.\nYou can no longer access any project resources on the site.";
d490 2
a491 1
        emailer.messageUsersWithProjectRole(role, this, subject, body);
@


1.56
log
@Modifications to make project addition more wizard-like...small breakage on this commit, will fix immediatly.
@
text
@d464 23
@


1.55
log
@New projects must be added synchronously, and should not be duplicates
of existing projects.
@
text
@d253 1
a253 1
            Project.assertNonexistance(conn, dMgr, domainID,name);
@


1.54
log
@Do not allow project names starting with a dash (IZ #1252).
@
text
@d99 5
d249 18
a266 12
        
        // Add the project to the database.
        String approvedBy = usrGrpMgr.getNobodyUserID(c);
        setRecord(pMgr.addProject(conn, profile, domainID, name, 
                                  license, shortDescription, longDescription,
                                  "", aliasURL,
                                  proposedBy, approvedBy));

        // Add the project to CVS, Issuezilla, etc.
        String domainName = domMgr.getDomainName(domainID);
        TigrisUpdate.addProject(domainName, name, getID(), null, 
                                shortDescription);
@


1.53
log
@- Renamed isValidProjectName() to isValidName().
- Moved the rest of the isValidName() implementation over.
@
text
@d96 1
a96 1
    private static final String PROJECT_NAME_RE = "^[-a-z0-9]{1,64}$";
@


1.52
log
@Moved in functionality from ProjectManager.
@
text
@d58 2
d94 5
d150 1
a150 1
    public static boolean isValidProjectName (String name)
@


1.51
log
@added radio buttons to default to "never" for a date to remove news items, and "immeidately" for a date to publish news items

cleanup.
@
text
@d135 29
d337 1
@


1.50
log
@
PR:
Obtained from:
Submitted by:
Reviewed by:

Slightly corrected some spacing.
@
text
@a669 4
	
        //String dateToday = FormatDate.format("EEE MMM dd kk:mm:ss z yyyy",
         //                "MM-dd-yy", new Date().toString());
        Date dateToday = new Date();	
@


1.49
log
@The app should now respect the Unapproved Project Role - Grant action properly.
@
text
@d239 2
a240 2
                .append(name).append("project.\n");
            body.append("Please approve or disapprove this project at")
@


1.48
log
@Moved CGI key from ProjectDownload into here...couldn't figure out a
good way to handle proper encapsulation in this situation.
@
text
@d525 2
a527 2
            } else {
                requiredAction = "Project Role - Grant";
@


1.47
log
@Use ProjectDownload's CGI param.
@
text
@d82 5
a927 1
                // CGI param name is specific to ProjectDownload.
d929 1
a929 1
                          (url, "msg", "Download authorization timed out."));
@


1.46
log
@now getting all news items in getNews(); filtering out removed items in the template
@
text
@d923 1
d925 1
a925 2
                          (url, "Message",
                           "Download authorization timed out."));
@


1.45
log
@changed getNews() method so that it would get news items that have yet to be posted -- will filter in template for non-admins
@
text
@d665 4
a668 2
        String dateToday = FormatDate.format("EEE MMM dd kk:mm:ss z yyyy",
                         "MM-dd-yy", new Date().toString());
d670 1
a670 1
        // Get news items that have not been removed
d677 1
a677 5
	    NewsItem newsItem = new NewsItem(conn, dMgr, r);
	    if (newsItem.getRemoveOn().compareTo(dateToday) >= 0)
	    {
	       newsItems.add(newsItem);
	    }
@


1.44
log
@added getNews method
@
text
@d668 1
a668 1
        // Get news items for this project that should be posted
d676 1
a676 2
	    if ( (newsItem.getPublishOn().compareTo(dateToday) <= 0)
	       && (newsItem.getRemoveOn().compareTo(dateToday) >= 0))
@


1.43
log
@added addNewsItem method
@
text
@d52 1
d72 1
d661 25
@


1.42
log
@Sort projects by name whenever possible.
@
text
@d52 1
d97 1
d298 2
d818 25
@


1.41
log
@A slightly heavy-handed way of noting which project a download came
from.  May want to factor out and use some vhost determination
routines.  Bleh!
@
text
@d77 1
a77 1
public class Project extends BusinessObject
d474 25
@


1.40
log
@Restructed to send MDA auth via cookies instead of query string.
@
text
@d807 1
d827 2
a828 1
            for (int i = 0; i < downloads.size(); i++)
d851 1
@


1.39
log
@Renamed MD5 class to MDA--it just more than just compute a digest
(it's very mod_auth_mda-specific).
@
text
@d56 3
a59 2
import org.webmacro.util.*;
import org.webmacro.servlet.*;
a96 7
    /**
     * The shared secret with the mod_auth_mda Apache module running on the
     * file server.
     */
    private static final String MDA_CRYPT_KEY = 
        "w b@@5b15#664038f.f9d8U19b7e25 664eY9ad2%4393e,a2ef";

a761 29
    }

    /**
     * Returns a digitally signed HTTP download URL to be interpretted by the 
     * Apache module mod_auth_mda.
     *
     * @@param server The server to create the URL for.
     * @@param user   The user whose email address to sign the URL.
     * @@param dl     The download to create a URL for.
     */
    public String getDownloadURL (String server, User user, Download dl)
        throws DataSetException, UnknownHostException, Exception
    {
        // Create and append digital signature.
        String realm = generateMDARealmMask(dl.isPrivate().booleanValue());
        InetAddress inetAddr = (server != null ? 
                                InetAddress.getByName(server) : 
                                InetAddress.getLocalHost());
        String email = user.getEmail();
        String cargo = "";
        long time = new java.util.Date().getTime() / 1000;
        MDA mda = new MDA();
        String digest = mda.compute(inetAddr.getHostAddress(), MDA_CRYPT_KEY, 
                                    email, realm, cargo, time);
        if (debug) log.info("digest=" + digest);
        digest += mda.getTimestamp() + email + '!' + realm + '!' + cargo;
        String serverURL = "http://" + server + '/' + getID() + '/' +
            user.getID() + '/' + dl.getName();
        return URL.appendCGIParam(serverURL, digest);
@


1.38
log
@Use the IP address of the InetAddress.  According to the JavaDoc, we
were already doing that (but not according to reality).
@
text
@d100 1
a100 1
    private static final String MD5_CRYPT_KEY = 
d789 2
a790 2
        MD5 md5 = new MD5();
        String digest = md5.compute(inetAddr.getHostAddress(), MD5_CRYPT_KEY, 
d793 1
a793 1
        digest += md5.getTimestamp() + email + '!' + realm + '!' + cargo;
@


1.37
log
@Initial run at ProjectGroup business object.
@
text
@d787 1
a787 1
        String cargo = ""; // HELP: WTF is this?
d790 2
a791 2
        String digest = md5.compute(inetAddr.toString(), MD5_CRYPT_KEY, email, 
                                    realm, "", time);
@


1.36
log
@- Added JavaDoc.
- Passing "" for the value of cargo, just like the Frogdot code does.
@
text
@d69 1
d137 5
d219 4
a222 10
        ArrayList groups = new ArrayList();
        groups.add(pMgr.getHostProjectID());
        groups.add(pMgr.getDomainProjectID(domainID));
        for (ListIterator i = groups.listIterator(); i.hasNext();)
        {
            String projectGroup = (String)i.next();
            prjGrpMgr.addProjectToGroup(conn, 
                                        getID(),
                                        projectGroup);
        }
d787 1
a787 1
        String cargo = null; // HELP: WTF is this?
d816 1
a816 1

@


1.35
log
@Narrowed the writeHtaccessFile() interface by one parameter (now
handled internally to the method).
@
text
@d771 1
a771 1
     * Returns a digitally signed download URL to be interpretted by the 
d774 3
a776 2
     * @@param user      The user whose email address to sign the URL.
     * @@param isPrivate Whether the download is private.
d791 1
a791 1
                                    realm, cargo, time);
@


1.34
log
@First stab at integration of Frogdot's digest class MD5-based digital signature algorithm.
@
text
@d822 1
a822 2
        writeHtaccessFile(file.getParentFile().getAbsolutePath(), url, 
                          getDownloads());
a831 1
     * @@param downloads A list of <code>Download</code> objects.
d833 2
a834 2
    private void writeHtaccessFile (String path, String url, List downloads)
        throws IOException, DataSetException
d856 1
@


1.33
log
@Application level file locking for generation of .htaccess files.
@
text
@d778 1
a778 1
        throws DataSetException, UnknownHostException
d788 2
a789 1
        String digest = MD5.compute(inetAddr.toString(), MD5_CRYPT_KEY, email,
d792 1
a792 1
        digest += time + email + '!' + realm + '!' + cargo;
@


1.32
log
@Use the host name (rather than IP that the implicit toString()
would've returned).
@
text
@d77 1
a77 1
    public static final boolean debug = true;
d81 6
d843 11
d855 30
a884 25
        FileWriter out = new FileWriter(fileName);
        out.write("# DO NOT EDIT: Generated by Tigris on " + 
                  new java.util.Date() + "\n\n");
        for (int i = 0; i < downloads.size(); i++)
        {
            Download d = (Download)downloads.get(i);

            out.write("<Files \"");
            out.write(d.getName());
            out.write("\">\n");
            out.write("AuthName MDAAuth\n");
            out.write("AuthType Basic\n");
            out.write("require valid-user\n");
            out.write("MDARealmMask      \"");
            out.write(generateMDARealmMask(d.isPrivate().booleanValue()));
            out.write("\"\n");
            out.write("MDAAuthLoginURL   \"");
            out.write(url);
            out.write("\"\n");
            out.write("MDAAuthTimeoutURL \"");
            out.write(URL.appendCGIParam(url, "Message",
                                         "Download authorization timed out."));
            out.write("\"\n");
            out.write("MDAAuthTimeoutMin 1\n");
            out.write("</Files>\n");
a885 1
        out.close();
@


1.31
log
@Corrected documentation.
@
text
@d832 4
a835 1
        if (url == null) url = "http://" + InetAddress.getLocalHost() + '/';
@


1.30
log
@Default URL should included the host name of the generating JVM.
@
text
@d825 1
a825 1
     *                  defaults to <code>/</code>).
@


1.29
log
@- Added imports for two java.net classes for use in digital signature
  generation.
- Moved a couple member fields.
- Added MD5_CRYPT_KEY constant, the shared secret used in auth.
- Added getUploadDirectory() and getDownloadURL() methods.
- Corrected and added documentation.
- Modified generateMDARealmMask() to handle public downloads as well.
@
text
@d832 1
a832 1
        if (url == null) url = "/";
@


1.28
log
@- Added URL param to addDownload() writeHtaccessFile() interfaces.
- Added default for writeHtaccessFile() url param.
- Added some JavaDoc.
@
text
@d52 2
d77 4
d89 6
a94 2
    private static Log log = new Log("proj", "Project");
    public static final boolean debug = true;
d747 43
d792 1
a792 1
     * Add a download for this project.
d849 1
a849 1
            out.write(generateMDARealmMask());
d859 1
a859 1
            out.write("</Files>\n\n");
d869 5
a873 4
     * @@return The hexidecimal representation of the project's unique
     *         identifier.
     */
    private String generateMDARealmMask ()
d876 6
a881 2
        // Set the prjoectID bit and return as hex a la tohex(2 ^ downloadID).
        return BigInteger.ZERO.setBit(Integer.parseInt(getID())).toString(16);
@


1.27
log
@- Used new static method in Joist's URL class.
- Changed addDownloads() to addDownload() -- now handles one file at a
  time.  Old implementation was a tad flawed for current necessity.
- Modified the writeHtaccessFile() implementation--moving towards what
  is needed.
@
text
@d741 5
a745 4
     * @@param acl          The ACL of the user doing the add.
     * @@param files        The <code>File</code> to add.
     * @@param descrip      The descriptions of the file to add.
     * @@param isPrivate    A flag indicating whether the file is private.
d748 1
a748 1
                             String isPrivate)
d762 1
a762 1
        writeHtaccessFile(file.getParentFile().getAbsolutePath(),
d771 2
d775 1
a775 1
    private void writeHtaccessFile (String path, List downloads)
a777 2
        // TODO: Pass the value of MDARealmMask that value as "realm" when 
        // creating a cookie.
d779 1
a797 2
            // TODO: The download URL from which the request came.
            String url = "/";
d813 2
a814 1
     * same realm.
@


1.26
log
@Moved comment to the right place and elaborated.
@
text
@d59 1
d61 1
d739 1
a739 1
     * Adds downloads for this project.
d741 4
a744 1
     * @@param files A list of <code>File</code> objects.
d746 2
a747 2
    public void addDownloads (AccessControlList acl, List files,
                              List descriptions, String path)
d759 4
a762 8
        int nbrFiles = files.size();
        for (int i = 0; i < nbrFiles; i++)
        {
            dlMgr.addDownload(conn, projectID, (String)descriptions.get(i), 
                              (File)files.get(i), acl.getUserID(), approvedBy);
        }

        writeHtaccessFile(path, getDownloads());
d766 1
a766 1
     * Writes the .htaccess file in the right directory for the
d780 3
a782 1
        FileWriter writer = new FileWriter(fileName, true);
d787 9
a795 9
            writer.write("<Files \"");
            writer.write(d.getName());
            writer.write("\">\n");
            writer.write("AuthName MDAAuth\n");
            writer.write("AuthType Basic\n");
            writer.write("require valid-user\n");
            writer.write("MDARealmMask      \"");
            writer.write(generateMDARealmMask());
            writer.write("\"\n");
d797 10
a806 6
            writer.write("MDAAuthLoginURL   \"/login/login.html\"\n");
            // TODO: Point back to the main web server, using Joist's
            // message in red.
            writer.write("MDAAuthTimeoutURL \"/login/timeout.html\"\n");
            writer.write("MDAAuthTimeoutMin 1\n");
            writer.write("</Files>\n\n");
d808 1
a808 1
        writer.close();
@


1.25
log
@- Added imports of some core Java classes.
- Added a static assertNonexistance() method.
- Added a TODO item to the project deletion method to remove download
  directories during a delete.
- Added ACL checking and call to new writeHtaccessFile() to addDownloads().
- Initial implementations of writeHtaccessFile() and generateMDARealmMask().
@
text
@a789 1
            // tohex(2 ^ downloadID)
d814 1
@


1.24
log
@Send mail to domain admins on creation of unapproved project.
@
text
@d49 2
a50 1
import java.io.File;
d85 30
d356 2
d742 3
a744 2
                              List descriptions)
        throws DataSetException, SQLException
d747 7
a753 3
        // TODO: Check permissions and whether approval is had.
        //assertHasPermissionForProject("", projectID);
        String approvedBy = (false ? null : acl.getUserID());
d759 1
d761 40
a800 1
            // TODO: Write the .htaccess files.
d802 14
@


1.23
log
@Can't proprietarize approved open source projects.
@
text
@d57 1
d64 2
d139 2
a140 1
               AlreadyExists, UpdateException, ACLException, DoesNotExist
d175 20
a194 1
        approve(acl);
@


1.22
log
@set the owner for all the mailing lists created to the owner of this
project.  we might need to worry about this if there's any again
if there's any way to change the owner of a project via the sourcecast
ui
@
text
@d325 1
a325 1
        if (!Licenses.isProprietary(getLicense()))
d350 2
a351 2
        if (Licenses.isProprietary(getLicense()) != 
                Licenses.isProprietary(license)) {
d530 6
@


1.21
log
@Don't run MemberAdd on non-base projects.
@
text
@a172 13
        // Add the mailing lists and modules for the project.
        // Please note that addDefaultMailingLists also takes care of
        // adding the project itself to anzu.  Perhaps the name should
        // change to addProjectMailSetup or somesuch.
        System.err.println("adding mailing lists; isProprietary? " +
                Licenses.isProprietary(license) + " from license " +
                license);
        profile.addDefaultMailingLists(conn, dMgr, getID(),
                                       Licenses.isProprietary(license));
        profile.addDefaultModules(conn, dMgr,
                                  domainName, name, getID(), 
                                  null);  
        
d179 3
d187 1
d189 2
a190 1
            newOwnerID = new User(conn, dMgr, domainID, projectOwner).getID();
d192 13
@


1.20
log
@Made the TigrisUpdate stuff saner with the use of business objects.
@
text
@d517 8
a524 2
        //TODO: Don't hard-code this.
        return type.equals("category");
@


1.19
log
@Corrected URL. Spice weasels rule OK
@
text
@d236 1
a236 1
               UpdateException
d246 1
a246 1
               UpdateException
d272 1
a272 1
               UpdateException, ACLException
d309 1
a309 1
               UpdateException, ACLException
d342 1
a342 1
               UpdateException, ACLException
d565 9
@


1.18
log
@More specific message to project owners on role request.
@
text
@d725 1
a725 1
            ("/servlets/ProjectMembers", null, "http", false);
@


1.17
log
@Fixed security bug. Also display buttons for role manipulation in UserEdit only if you can use those roles.
@
text
@d721 7
@


1.16
log
@set the list type to a "private" version when the license is set to a
proprietary license; set it to a non-private version when the license is
set to an open source version.
@
text
@d402 22
@


1.15
log
@avoid excessive object creation: there's no point in constructing Integers
if all we're going to do is construct Strings from them via toString().
@
text
@d78 1
d177 5
a181 1
        profile.addDefaultMailingLists(conn, dMgr, getID());
d345 18
d366 32
a397 1
    
@


1.14
log
@corrected javadoc comment formatting
@
text
@d176 1
a176 1
        profile.addDefaultMailingLists(conn, dMgr, new Integer(getID()));
d178 1
a178 1
                                  domainName, name, new Integer(getID()), 
@


1.13
log
@Sync'd with table manager.
@
text
@d601 2
a602 1
    /** Return the ProjectHome url.
@


1.12
log
@removed Member Policy field
@
text
@d49 2
a51 1
import java.util.*;
d583 2
a584 1
    public void addDownloads (List files)
d587 4
d594 2
a595 2
            // TODO: Inform the db.
            dlMgr.addDownload(conn, null);
@


1.11
log
@Use new narrower interface for call to getPort
@
text
@d131 1
a131 1
                   String status, String aliasURL, String memberPolicy, 
d149 1
a149 1
                                  "", aliasURL, memberPolicy,
d333 1
a333 2
                           String aliasURL,
                           String memberPolicy
d340 1
a340 1
                               longDescription, status, aliasURL, memberPolicy);
a575 5
    public String getMemberPolicy()
        throws DataSetException
    {
        return rec.getValue(ProjectManager.PROJECT_MEMBER_POLICY).asString();
    }
@


1.10
log
@Added stub for addition of downloads to a project.
@
text
@d709 1
a709 1
        String port = urlUtil.getPort( properties, protocol );
@


1.9
log
@Moved utility methods to org.joist.util.URL.  Reuse
@
text
@d427 2
a428 1
    public boolean exists(){
d582 19
a600 3
    
    
    
@


1.8
log
@Corrected bad name for TableManager.
@
text
@d690 3
a692 2
        String protocol = getProtocol( inProtocol );
        String port = getPort( properties, protocol );
a723 66
    }
    
    /**
     * Get port to use.
     * 
     * @@param inProperties Instance of JoistProperties.  Used to pull http
     * ports from.
     * @@param inProtocol Either 'http' or 'https'.
     *
     * @@return Port to use as string.  Null if port is 
     *
     * @@exception NullPointerException If i can't get a JoistProperties
     */
     private String getPort( org.joist.util.JoistProperties inProperties,
                                String inProtocol )
        throws NullPointerException
     {
        String port = null; // Port to return
        
        final String HTTP_PROTOCOL = "http";
        final Integer DEFAULT_HTTP_PORT = new Integer( 80 );
        final Integer DEFAULT_HTTPS_PORT = new Integer( 443 );
        final String HTTP_PORT_KEY = "http_port";   // Key to pull http_port
        final String HTTPS_PORT_KEY = "https_port"; // Key to pull https_port.
        
        boolean isHttp = inProtocol.equalsIgnoreCase( HTTP_PROTOCOL );
        Integer defaultPort = ( isHttp )? DEFAULT_HTTP_PORT: DEFAULT_HTTPS_PORT;
        String portKey = ( isHttp )? HTTP_PORT_KEY: HTTPS_PORT_KEY;
        port = inProperties.getProperty( portKey );
        if( port == null )
            throw new NullPointerException( portKey + " is null" );
        if( port.equals( defaultPort.toString( ) ) )
            port = null; // Return null if port is default for the protocol.
            
        return port;
     }
    
    
    /** Figure the protocol to use -- http or https.
     * 
     * @@param inProtocol Pass 'http' or 'https'.  If null, we assume 'http'.
     *
     * @@return Return 'http' or 'https'
     *
     * @@exception IllegalArgumentException Thrown if you pass anything but 
     * 'http' or 'http' in the inProtocol param.
     */
    private String getProtocol( String inProtocol )
        throws NullPointerException, IllegalArgumentException
    {
        final String HTTP_PROTOCOL = "http";
        final String HTTPS_PROTOCOL = "https";
        final String DEFAULT_PROTOCOL = HTTP_PROTOCOL; // Default protocol    
         
        String protocol = DEFAULT_PROTOCOL; // Protocol to return.

        if( inProtocol != null )
            protocol = inProtocol;
        if( !protocol.equalsIgnoreCase( HTTP_PROTOCOL )
            && !protocol.equalsIgnoreCase( HTTPS_PROTOCOL ) )
        {
            throw new IllegalArgumentException( "Unsupported protocol: "
                + inProtocol );
        }
            
        return protocol;
@


1.7
log
@- Added a ProjectDownloadManager member.
- Added a getDownloads() method to retreive downloads for the project.
@
text
@d218 1
a218 1
            ("org.tigris.helm.ProjectDownloadManager");
@


1.6
log
@removed getNumberOfRequestedUsers() method -- unnecessary since the template can call size() on getRequestedUsers()
@
text
@d74 1
d217 2
d445 1
a445 1
        throws SQLException, DataSetException, JoistDatabaseException
d448 18
@


1.5
log
@Permission checking bugfixes; one more big one on the way.
@
text
@a403 16
    public String getNumberOfRequestedUsers()
        throws DataSetException, SQLException, JoistDatabaseException, 
               DoesNotExist
    {
        DataSet userSet = urpMgr.getUsersForProject(conn, 
                                                    getID(), Boolean.FALSE);
        ArrayList userList = new ArrayList();
        for (int i = 0; i < userSet.size(); i++)
        {
            Record r = userSet.getRecord(i);
            User u = new User(conn, dMgr, r);
            userList.add(u);
        }
        
        return Integer.toString(userList.size());
    }
@


1.4
log
@provide more general methods : we need this for e-mail messages
(invitations), and we need it for more than just the home page.
@
text
@d151 5
a166 1

a168 5

        // Add the project to CVS, Issuezilla, etc.
        String domainName = domMgr.getDomainName(domainID);
        TigrisUpdate.addProject(domainName, name, getID(), null, 
                                shortDescription);
@


1.3
log
@Fixed project deletion and ProjectMembershipRequest
@
text
@d585 1
a585 3
        throws NullPointerException, 
                IllegalArgumentException,
                DataSetException
d591 2
a592 1
    /** Return the ProjectHome url.
d602 1
a602 1
     * www.DOMAIN.com and you come upon the ProjectList page that
d618 1
a618 3
        throws NullPointerException, 
                IllegalArgumentException,
                DataSetException
d620 12
a631 1
        StringBuffer url2Return = new StringBuffer( ); // Build url in here.
d633 41
a673 5
        final String DOMAIN_KEY = "DOMAIN";  // Key to pull site domain.
        final String IS_VHOSTING_KEY = "IS_VHOSTING"; // Key for VHOSTING.
        final String SERVLET_PATH = "/servlets/ProjectHome"; 
        final String QUERY_STRING = "?projectID=" + getID( );
        
a674 1
        //
d680 20
a699 17
        // Test that vhosting is turned on.
        //
        String isVhosting = properties.getProperty( IS_VHOSTING_KEY );
        if( isVhosting != null
            && ( new Boolean( isVhosting ).booleanValue( ) ) )
        {   
            String protocol = getProtocol( inProtocol );
            String port = getPort( properties, protocol );
            String domain = properties.getProperty( DOMAIN_KEY );
            if( domain == null || domain.length( ) <= 0 )
                throw new NullPointerException( DOMAIN_KEY + " is null" );
           
            url2Return.append( protocol );
            url2Return.append( "://" );         
            url2Return.append( getName( ) ); // Add this project's name as host.
            url2Return.append( '.' ); // Dot between project name and domain
            url2Return.append( domain );  
d702 2
a703 2
                url2Return.append( ":" );
                url2Return.append( port );
a704 1
            url2Return.append( SERVLET_PATH );
d706 11
a716 4
        else // IS_VHOSING is false.  VHOSTING is not turned on.
        {
            url2Return.append( SERVLET_PATH );
            url2Return.append( QUERY_STRING );
d718 1
a718 2
        
        return url2Return.toString( );
d721 2
a722 2
    
    /** Get port to use.
d730 1
a730 1
     * @@exception NullPointerException If i can't get a JoistProperties instance.
d767 1
a767 2
        throws NullPointerException, 
                IllegalArgumentException
@


1.2
log
@Made project deletion more consistent.
@
text
@d282 2
a283 1
        //TODO: Remove all roles in the project.
d316 1
a316 1
                ("org.tigris.helm.database.ProjectProjectGroupManager");        
@


1.1
log
@Initial revision
@
text
@d280 1
a280 1
        prjGrpMgr.removeBaseFromComposites(conn, getID());
d282 1
a282 1
        //Remove all roles in the project.
d288 3
a290 1
        //Delete the project itself.
a291 3

        //Delete its CVS repository etc.
        String domainName = domMgr.getDomainName(getDomainID());
@


1.1.1.1
log
@Merging newhelm tree into helm, as per IZ issue #557.  Previous major version of helm is tagged TIGRIS_NOV_11_2000.
@
text
@@
