AdminstrationGuide

ProjectForge® 2011

Version: 3.6.1
Date: 2011-05-27
Project: ProjectForge® 2011
URL: www.projectforge.org
Author: Kai Reinhard
mailtok.reinhard@me.com

downloadPrint-friendly version: AdministrationGuide.pdf

Contents

1Introduction
2Setting up the application working directory
3Setting up the database
3.1 Desktop database Hypersonic
3.2 Initialization, first login and set-up dialogue
3.3 PostgreSQL
3.3.1 Mac OS X
3.3.2 Configuration
3.3.3 Setting up the database
3.4 Create database indices
4Configuration
4.1 Base directory (application's home)
4.2 Configuration file config.xml
4.3 Configuration settings (web interface)
4.4 Using ttf fonts for PDF render engine
4.5 HTML formatted E-Mail templates
4.6 Configuration of Mobile Enterprise Blogging (MEB)
4.6.1 E-Mail
4.6.2 Servlet-Call
4.6.3 Easy creation of JIRA-Issues
4.7 Asterisk connection: phone calls and texting with ProjectForge
4.7.1 Phone calls
4.7.2 Texting
5Maintenance
5.1 Updating by simple clicks
5.2 Re-indexing the database
5.3 Restart/Shutdown
5.4 Analysing tools
5.5 XML-backup and restore and data-base migration
5.5.1 Export
5.5.2 Import
5.5.3 Limitations
5.6 Backup
5.7 Restoring a backup
5.8 Automatical backup
5.8.1 Backup script
5.8.2 Adding crontab
5.8.3 Remote backup
5.8.4 Polling remote backup
5.9 Scheduler
5.9.1 Data base search index
5.10 Spaces
5.10.1 Store
5.10.2 Deletion or historization of spaces
5.11 Uninstalling ProjectForge
6Webserver Tomcat
6.1 server.xml
6.2 context.xml
6.3 Increase memory and environment for Tomcat
6.4 Generating SSL key
6.5 Webapp Lambda-Probe
7FAQ
7.1 Reset passwords
7.2 Hypersonic: Could not insert entries to the data base.

List of figures

1Initiating phone calls
2Texting with ProjectForge
3ProjectForge provides a convenient method for system updates. The data base scheme will be updated and the data base will be migrated automatically by scripts.

1 Introduction

This documents describes the administration of ProjectForge®.

2 Setting up the application working directory

  1. mkdir -p ${HOME}/ProjectForge/hibernate-search
    mkdir ${HOME}/ProjectForge/tmp mkdir ${HOME}/ProjectForge/work
  2. cp -r resources ${HOME}/ProjectForge/

3 Setting up the database

3.1 Desktop database Hypersonic

  1. cp hsqldb-1.8.0.7.jar apache-tomcat/common/lib/ (for tomcat 6: apache-tomcat/lib )
  2. mkdir ${user.home}/ProjectForge
  3. Start ProjectForge® (via Tomcat or Eclipse WTP-Plugin)
The database will be written at default to ${user.home}/ProjectForge.

3.2 Initialization, first login and set-up dialogue

After the first start of ProjectForge® you will see ProjectForge®'s set-up dialogue. Please configure at minimum the adminstrator's password and the target (empty data-base for a productive system or pre-filled with test data). You can configure or change all other settings such as time zone, e-mail addresses etc. any time later.

3.3 PostgreSQL

3.3.1 Mac OS X

Install PostgreSQL e.g. via fink install postgresql . Shared memory regions are set during the system's startup. Unfortunately, once the shared memory regions have been configured on Mac OS X, it appears they can't be changed. Here's how to increase them on your system. Edit /etc/sysctl.conf and set higher numbers there (from wiki.finkproject.org/index.php/Shared_Memory_Regions_on_Darwin ):
 File: /etc/sysctl.conf
1
2
3
4
5
kern.sysv.shmmax=16777216
kern.sysv.shmmin=1
kern.sysv.shmmni=64
kern.sysv.shmseg=8
kern.sysv.shmall=32768
Remember to set all of the 5 values above, otherwise your settings will be overridden by /etc/rc.

Hint

For more convinient start and stop of the PostgreSQL as normal user, try this:
1
2
3
Archon:~ admin$ sudo visudo
kai   ALL = NOPASSWD: /sw/bin/pgsql.sh start
kai   ALL = NOPASSWD: /sw/bin/pgsql.sh stop
Afterwards you can start without su as normal user the database with /sw/bin/pgsql.sh start and stop with /sw/bin/pgsql.sh stop without entering any password. (Currently I've problems with: "could not identify current directory: Permission denied" . The hotfix is to change the directory to any which is readable for the super user: cd /tmp; sudo /sw/bin/pgsql.sh start; cd - .

3.3.2 Configuration

 File: pg_hba.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
# Database administrative login by UNIX sockets
local   projectforge projectforge                     ident sameuser

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               md5
local   all         all                               ident sameuser
# IPv4 local connections:
host    all         all         192.168.12.34/32      md5
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5

3.3.3 Setting up the database

  1. Edit postgresql.conf:
     File: postgresql.conf
    1
    2
    3
    ...
    max_connections = 200                   # (change requires restart)
    ...
  2. createuser -U postgres -P projectforge as e.g. admin user.
  3. createdb -U postgres -E UTF-8 -O projectforge projectforge as e.g. admin user.
  4. You can drop any existing user and database with: dropdb projectforge and dropuser projectforge
  5. Re-use of existing database (use a dump)
    psql -q -f projectforge_2008-04-02_02-00.sql -U postgres projectforge 2>&1 > log.txt
  6. cp postgresql-8.0-318.jdbc3.jar apache-tomcat/common/lib/ (for tomcat 6: apache-tomcat/lib )
  7. Creation of the new database scheme
    1. Create ProjectForge.xml in conf/Catalina/localhost/ ($CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml). and modify
      schemaUpdate=true
    2. Start ProjectForge® for automatically creation of the new database scheme (see log files for detail).
    3. Stop ProjectForge®
    4. Restore setting in $CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml
      schemaUpdate=false

3.4 Create database indices

The creation script of all proposed indices can be downloaded via the admin web. The most indices for the foreign keys are build out of the metadata of the PostgreSQL database.

4 Configuration

4.1 Base directory (application's home)

ProjectForge® needs a base directory which is set in $CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml of the web server. By default it is ${user.home}/ProjectForge . You should prepare this directory for use-age of ProjectForge®. The following directories must exist:
ProjectForge/hibernate-search Here the lucene indices are stored. If corrupted, delete all files and directories in this directory and re-build data base indices via the web admin console.
ProjectForge/resources/fonts For additional fonts used e. g. by the pdf renderers.
ProjectForge/resources/images For images e. g. by the pdf renderers.
ProjectForge/work For uploaded files etc.

4.2 Configuration file config.xml

The format of the file is:
 File: <app-home>/config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?xml version="1.0" encoding="UTF-8" ?>
<config>
  <!-- Uncomment this, if ProjectForge runs in root context: -->
  <!--servletContextPath></servletContextPath-->
  <!-- Uncomment this, if ProjectForge does not regognize your host
       correctly for e. g. ImageCropper: -->

  <!--domain>https://projectforge.acme.com:8443</domain-->
  <!--pluginMainClasses>
    org.projectforge.plugins.todo.ToDoPlugin
  </pluginMainClasses-->

  <!-- Customized logo file relative to <app-home>/resources/images: -->
  <!-- logoFile>Micromata.png</logoFile-->
  <telephoneSystemUrl>http://asterisk.acme.com/originatecall.php\
  ?source=#source&amp;target=#target</telephoneSystemUrl>
  <telephoneSystemNumber>0561316793</telephoneSystemNumber>
  <telephoneSystemOperatorPanelUrl><![CDATA[
    <a onclick=
"var w = window.open('http://192.168.76.25/', 'asterisk',\
                'scrollbars=no,resizable=yes,width=800,height=800');\
                w.focus();"
 href="#">
      <img src="../images/asteriskOperatorPanel.png"
           title="Asterisk operator panel - available over the intranet." />
    </a>]]></telephoneSystemOperatorPanelUrl>
  <smsUrl>http://asterisk.acme.com/sms.php?number=#number&amp;message=#message</smsUrl>
  <defaultLocale>DE</defaultLocale>
  <defaultTimeNotation>h24</defaultTimeNotation>
  <sendMail>
    <protocol>smtp</protocol>
    <host>localhost</host>
    <port>25</port>
    <debug>false</debug>
  </sendMail>
  <jiraBrowseBaseUrl>https://jira.acme.com/jira/browse/</jiraBrowseBaseUrl>
  <holidays>
    <holiday label="ACME 10th anniversary" year="2010" month="5" dayOfMonth="18"
             workingDay="false" />
    <!-- New holiday: -->
    <holiday label="Erster Mai" month="4" dayOfMonth="1" workingDay="false" />
    <holiday label="Dritter Oktober" month="9" dayOfMonth="3" workingDay="false" />
    <!-- Xmas Eve as half working day: -->
    <holiday id="XMAS_EVE" workingDay="true" workFraction="0.5" />
    <!-- New year eve as half working day: -->
    <holiday id="SYLVESTER" workingDay="true" workFraction="0.5" />
    <!-- Ignore shrove tuesday: -->
    <holiday id="SHROVE_TUESDAY" ignore="true" />
  </holidays>
  <contractTypes>
    <contractType value="COF" label="Contract of employment" />
    <contractType value="FC" label="Frame contract" />
    <contractType value="PC" label="Project contract" />
    <contractType value="SC" label="Service contract" />
  </contractTypes>
  <menuConfig>
    <sub-menu>
      <!-- Change the following menu's visibility: -->
      <menu-entry id="IMAGE_CROPPER" visible="true" />
      <menu-entry id="DOCUMENTATION" visible="false" />
    </sub-menu>
  </menuConfig>
</config>
Parameter Description
logoFile If you want to place your own compony logo file at the top of the navigation panel, you can specify the logo file. The path is relative to the <app-dir>resources/images directory.
telephoneSystemUrl (#source and #target will be replaced by ProjectForge®):
http://asterisk.acme.com/originatecall.php ?source=#source&target=#target
telephoneSystemNumber For internal direct calls, the telephone system number will be removed if a number starts with it, e.g. 0123: 012345 -> 45.
telephoneSystemOperatorPanelUrl Here you can define any existing operating panel (see example config.xml above).
smsUrl ProjectForge® supports the sending of SMS if a servlet is available (#number and #message will be replaced by ProjectForge®):
http://asterisk.acme.com/sms.php ?number=#number&message=#message"
defaultLocale Default locale is used for formatting the week of year (which depends on the locale). All user's of ProjectForge® therefore will have the same definition of the weeks of year by using this locale application wide and not the user's locale.
defaultTimeNotation Default time notation used for user's without a personal time notation setting. The default time notation is 24-hours for German user languages (starting with "de") or 12-hours for all other languages. Supported values: "H12" and "H24".
excelDefaultPaperSize Default paper size for excel exports (default is DINA4). Supported values: "Letter"
jiraBrowseBaseUrl Base url for linking JIRA issues: https://jira.acme.com/jira/browse/PROJECTFORGE-222. The issue name UPPERCASE_LETTERS-### will be appended to this url. ProjectForge® parses the user's text input for [A-Z][A-Z0-9*]-[0-9]* and displays a list of detected JIRA-issues with a link beside the text area containing such issues. Example: https://jira.acme.com/jira/browse/ (don't forget closing '/').
If null, the no text input will be parsed and no JIRA link will be displayed.
holidays ProjectForges pre-defined holidays can be extended or declared as to be ignored (see example above in config.xml).
Pre-defined holidays (referenced by id) are:
NEW_YEAR, XMAS_EVE, FIRST_XMAS_DAY, SECOND_XMAS_DAY, SYLVESTER, SHROVE_MONDAY, SHROVE_TUESDAY, ASH_WEDNESDAY, PALM_SUNDAY, MAUNDY_THURSDAY, GOOD_FRIDAY, EASTER_SUNDAY, EASTER_MONDAY, ASCENSION, WHIT_SUNDAY, WHIT_MONDAY, CORPUS_CHRISTI.
If not given, only the pre-defined holidays will be used.
portletMode If configured (as true) then only the content html layer is shown (no menu, no logos, no headbar). This is use-ful for iFrame integration or integration in e. g. Liferay.
contractTypes If you're organizing contracts with ProjectForge you should configure your required contract types (s. examples in the config file above). If you delete or rename contract types (values) in your configuration any existing data base entry should be changed by you manually in the data base!
menuConfig You can configure menu entries as invisible by adding them here (s. above in the example). To add new menu entries, please use the plugin technology.
You can find a list of all id's of the ProjectForge menu entries here: MenuItemDef.html
The ImageCropper is de-activated at default because it's SSL (https) required for correct functioning (required by the Adobe Flash player).
Please note: a re-start of ProjectForge is required after any changes of menuConfig.
pluginMainClasses Here you can define further third party plug-ins or own plugins. The classes defined here must be derived from AbstractPlugin. Multiple entries should be separated by white chars and/or commas.
Please note: a re-start of ProjectForge is required after any changes of menuConfig.
cronExpressionNightlyJob Cron expression for starting the nightly job. The nightly job re-indexes the data base (full re-index) and starts the MEB polling job (imports all mails from mail account, if not already imported and MEB mail account is configured). Default value is (every night at 2 am UTC, s. CronSetup.java):
0 0 2 * * ?
See the documentation of the Quartz scheduling framework for further information.
cronExpressionMebPollingJob Cron expression for starting the meb polling job for getting unseen mails from the mail server (only if MEB mail account is configured). Default value is (every 10 minutes: 5, 15, 25, ..., s. CronSetup.java):
0 5/10 * * * ?
See the documentation of the Quartz scheduling framework for further information.

4.3 Configuration settings (web interface)

Please go to this page for setting different parameters of ProjectForge® such as default time zone etc. You'll find the documentation there.

4.4 Using ttf fonts for PDF render engine

FOP is used as internal render engine. For enabling True Type Fonts please refer the FOP documentation.
1
2
java -cp build/fop.jar:lib/avalon-framework-4.2.0.jar:lib/commons-logging-1.0.4.jar:lib/commons-io-1.3.1.jar \
          org.apache.fop.fonts.apps.PFMReader <path>/<font>.pfm ttf<font>.xml

4.5 HTML formatted E-Mail templates

ProjectForge works with Groovy templates for generating e-mails (as notifications). You'll find the templates inside your web archive of the ProjectForge installation: WEB-INF/classes/mail/. You can modify any template of this directory if needed by simply copiing the file(s) you want to modify into your ProjectForge application dir, which is also the destination of config.xml:
 cp {PROJECTFORGE_WEB_DIR}/WEB-INF/classes/mail/templatefile {PROJECTFORGE_APP_DIR}/mail/
Afterwards you can edit this file. ProjectForge looks first in this ProjectForge app directory for loading templates and if not found it uses the resources path.
The templates are internationalized with the locale of the receiving user.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<html>
<html>
#INCLUDE{mail/mailHead.html}
<body>
#INCLUDE{mail/mailOpening.html}
<br />
Here you can place content (don't forget to use i18n keys for supporting internationalized e-mails).
...
<br />
<%= pf.getString("link") %><a href="${requestUrl}">${requestUrl}</a>
<br />
This is an example of using dynamic data (here a list of positions will be printed):
<table>
  <% for (position in order.positions) { %>
    <tr>
      <th><%= pf.getString("title") %></th>
      <td>${position.title}</td>
      ...
    </tr>
  <% } %>
</table>

#INCLUDE{mail/mailHistoryTable.html}

#INCLUDE{mail/mailClosing.html}
#INCLUDE{mail/mailFooter.html}
</body>
</html>
If you don't like html-formatted e-mails, you can simply remove all html tags (ignore the html suffix then).

4.6 Configuration of Mobile Enterprise Blogging (MEB)

ProjectForge supports two ways of receiving SMS: e-mail and/or servlet-call. You can use both or at least one of the two ways:
 File: config.xml
1
2
3
4
5
6
7
8
9
...
  <receiveSmsKey>kds8uijkqw6idg</receiveSmsKey>
  <mebMailAccount>
    <hostname>mail.acme.com</hostname>
    <username>pf-sms</username>
    <password>h7ishd6d</password>
    <protocol>imaps</protocol>
  </mebMailAccount>
  ...
ProjectForges ensures that messages will be imported only once.

4.6.1 E-Mail

ProjectForge can receive messages from a mail server (e. g. IMAP mail account). The e-mails will be parsed as key-value:
 File: Mail
1
2
3
date=xxx
sender=0123456789
msg=JIRA issue: fix the encoding bug
The date can have one of the two formats: either seconds since 01/01/70 or 201006121738 (yyyymmddhhMMss).
There are two cron jobs which are responsible for getting new messages:
  1. The first runs every 10 minutes (configurable in confix.xml) and get unseen (recent) mails from the mail server. If not already imported then a new entry is created.
  2. The second runs nightly and read all mails from the inbox and creates new entries for not yet imported messages. This job ensures that no mail is lost e. g. if another mail client has read the mails from this inbox. The first job ignores already seen mails.

4.6.2 Servlet-Call

You can implement a servlet call whenever your system receives an SMS:
https://pf.acme.com/secure/SMSReceiver?key=kds8uijkqw6idg&date=20101105171233&sender=01234567&msg=Hello...
The format of the values are the same as described above. The encoding should be UTF-8. The key is a communication key and should be configured in your config.xml (see above).
Please deploy the following php script on your Asterisk web server:
 File: sms_receive.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/php
<?
SMS2ProjectForge

$SMS_DIR="/var/spool/asterisk/sms/mtrx/";
$PF_EMAIL="projectforge@change-to-your-domain.de";
$FROM="smsgateway@change-to-your-domain.de";
$PF_URL="https://change-to-your-domain.de/secure/SMSReceiver?key=<change-to-your-key>&date=%s&sender=%s&msg=%s";

function parseFile($file, $recipient) {

  if(!$file)
    return;
  if(is_file($file)) {
    $content = file($file);
  } else {
    print("$file is missing\n");
    return;
  }
  foreach($content as $line) {
    if(preg_match("/oa=(\d+)/", $line, $match)) {
#print("Absender " . $match[1] . "\n");
      $oa = $match[1];
    }
    if(preg_match("/ud=(.*)/", $line, $match)) {
#print("Text " . $match[1] . "\n");
      $text = $match[1];
    }
  }
  if($recipient == "pf") {
    $time = time();
#$mailtext = sprintf("date=%s\nsender=%s\nmsg=%s\n", time(), $oa, utf8_encode($text));
    $mailtext = sprintf("date=%s\nsender=%s\nmsg=%s\n", time(), $oa, $text);
    mail($PF_EMAIL"SMS", $mailtext, "From: smsgateway <$FROM>");
    $url = sprintf($PF_URL),
        $time,
        $oa,
        urlencode($text));
    $pig = fopen($url, "r");
    # XXX check answer!
    #$ret = stream_get_contents($pig);
  }
  return(1);
}

function getRecipient($file) {
  if(!$file)
    return;
  # pf.2010-05-04T16:46:01-11 
  if(preg_match("/(\w+)\.\d\d\d\d-\d\d-\d\d.\d\d:\d\d:\d\d-\d+/", $file, $match)) {
    return($match[1]);
  }
  return;
}

##
Main
#
$content = array();
if(is_dir($SMS_DIR)) {
  if($dh = opendir($SMS_DIR)) {
    while(($file = readdir($dh)) !== false) {
      if($file != "." && $file != "..") {
        if(parseFile($SMS_DIR . $file, getRecipient($file))) {
          unlink($SMS_DIR . $file);
        }
      }
    }
  }
}
?>

4.6.3 Easy creation of JIRA-Issues

 File: config.xml
1
2
3
4
5
6
7
8
9
10
11
12
...        
  <jiraConfig>
    <createIssueUrl>https://jira.acme.com/jira/secure/CreateIssueDetails!init.jspa</createIssueUrl>
    <issueTypes>
      <issueType label="Bug" value="1" />
      <issueType label="New functionality" value="2" />
      <issueType label="Task" value="3" />
      <issueType label="Improvement" value="4" />
      <issueType label="Claim" value="5" />
      <issueType label="Open Requirement" value="6" />
    </issueTypes>
  </jiraConfig>
First you have to define your URL for creating JIRA issues. Afterwards you should define your issue types. Every user has to define his favorite projects. This is necessary because JIRA does not provide a creation URL where you can choose your project and issue type and a pre-filled summary of the issue!

4.7 Asterisk connection: phone calls and texting with ProjectForge

4.7.1 Phone calls

If configured the users are able to initiate phone calls directly by clicking on a phone number of an address or by entering a name or a phone number in the direct phone call page.
Figure 1: You can initiate a phone call by simply clicking on a phone number of an address or by entering a name or number into the number field.
Please deploy the following php script on your Asterisk web server:
 File: originatecall.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?
# originates call from ProjectForge
# 03/09 by t.koch@micromata.de

$USERNAME = "admin";
$PASSWORD = "secret";

function doCall($source, $target) {
  global $USERNAME, $PASSWORD;
  $socket = fsockopen("127.0.0.1","5038", $errno, $errstr, $timeout); 
  if(!$socket) {
    return(1);
  }
  fputs($socket, "Action: Login\r\n");                   
  fputs($socket, "UserName: $USERNAME\r\n");            
  fputs($socket, "Secret: $PASSWORD\r\n\r\n");         
  fputs($socket, sprintf("Action: Originate\r\nChannel: Local/%s@intern\r\nContext: intern\r\nExten: %s\r\nPriority: 1\r\nCallerid: %s\r\nTimeout: 8000\r\nVariable: var1=23|var2=24|var3=25\r\nActionID: ABC45678901234567890\r\n\r\nAction: Logoff\r\n\r\n", $source, $target, $source));
  return(0);

  if($debug) {
    while (!feof($socket)) {
      print(fread($socket, 8192));              
    }
    fclose($socket);                               
  }
}

$SOURCE = $_GET{source};
$TARGET = $_GET{target};

if(!is_numeric($SOURCE)) {
  print(2);
  exit(2);
}
if(!is_numeric($TARGET)) {
  print(3);
  exit(3);
}
if(doCall($SOURCE, $TARGET)) 
  print(1);
else
  print(0);
?>
Please check this servlet manually. It has to be available from your ProjectForge server. Then configure your servlet:
 File: config.xml
1
2
3
4
5
6
7
8
<config>
  ...
  <telephoneSystemUrl>http://asterisk.acme.priv/originatecall.php?source=#source&amp;target=#target</telephoneSystemUrl>
  <!-- If the system number is given, ProjectForge will shorten your phone numbers starting with -->
  <!-- this number automatically. This enables internal calls. -->
  <telephoneSystemNumber>0561316793</telephoneSystemNumber>
  ...
</config>
To use the full functionality of ProjectForge please configure the address book feature. Don't forget to configure your default country phone prefix in the configuration web page.

4.7.2 Texting

If configured the users are able to text by clicking on the SMS symbol of an address or by entering a name or a cell phone number.
Figure 2: You can send text messages by simply clicking on the SMS symbol of an address or by entering a name or cell phone number.
Please deploy the following php script on your Asterisk web server:
 File: sms.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?
/*
   Texting with ProjectForge and Asterisk
   07.09.2009 by t.koch@micromata.de v1
*/


$NUMBER = $_REQUEST{number};
$MESSAGE = $_REQUEST{message};

if(!is_numeric($NUMBER)) {
  print("2\nwrong destination number");
  return(2);
}
if(!$MESSAGE) {
  print("1\nmissing message");
  return(1);
}
if(strlen($MESSAGE) > 160) {
  print("3\nmessage > 160");
  return(3);
}
$rand = rand(100000, 4000000);
usleep($rand);

XXX concurrent == maximum number of b channels
system(sprintf("/usr/sbin/smsq '--concurrent=8' '--spool-dir=/var/spool/asterisk/' '--motx-channel=DIALOGICDIVA/contr1/0193010' '--da=%s' '--motx-callerid=<callerid>' '--ud=%s' >/tmp/sms.$rand 2>/tmp/sms.$rand", $NUMBER, $MESSAGE));
print("0\nok");
?>
Please check this servlet manually. It has to be available from your ProjectForge server. Then configure your servlet:
 File: config.xml
1
2
3
4
5
<config>
  ...
  <smsUrl>http://asterisk.acme.priv/sms.php?number=#number&amp;message=#message</smsUrl>
  ...
</config>
To use the full functionality of ProjectForge please configure the address book feature. Don't forget to configure your default country phone prefix in the configuration web page.

5 Maintenance

5.1 Updating by simple clicks

ProjectForge provides a very convenient method for updating to new versions (improved again since version 3.5.2). Please call the menu "Update system".
Figure 3: ProjectForge provides a convenient method for system updates. The data base scheme will be updated and the data base will be migrated automatically by scripts.
This dialog is called automatically on start-up if a new ProjectForge-Release detects something to up-date. Please select the check-box "Show old updates" to see, that your ProjectForge is completely up-to-date. You can update from any older version.

Hint

If your ProjectForge installation is running with the schema-update option true then most of the updates below are done by the data-base layer (Hibernate). So you'll find no update entries in the table t_database_update. It's highly recommended to set schema-update option to false in production mode (please use this option only for the first start-up).

Hint

ProjectForge checks only the newest update entries (sorted by date) of every plugin and the ProjectForge's core for update. Any older update entries aren't tested. If you want tho check older update entries, please check them via SystemUpdatePage.

5.2 Re-indexing the database

Should be done after setup: Use the adminstration menu.

5.3 Restart/Shutdown

Please use the containers shutdown mechanism (e.g. catalina.sh stop ). During the undeployment of the ProjectForge®-War for example the user preferences cache will be flushed to the database, otherwise user preferences will may be lost.

5.4 Analysing tools

Useful commandes are
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
projectforge@vprojectforge:~$ jps
19533 Bootstrap
2261 Jps
projectforge@vprojectforge:~$ jstack 19533
2008-02-14 09:58:28
Full thread dump Java HotSpot(TM) 64-Bit Server VM (1.6.0_03-b05 mixed mode):

"Attach Listener" daemon prio=10 tid=0x00002aaaf4a6e800 nid=0x8fa waiting on condition [0x0000000000000000..0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"http-8443-10" daemon prio=10 tid=0x00002aaaf4a94800 nid=0x716c in Object.wait() [0x0000000041f47000..0x0000000041f47e40]
   java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x00002aaaee262530> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
  at java.lang.Object.wait(Object.java:485)
  at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:416)
  ...

5.5 XML-backup and restore and data-base migration

ProjectForge supports the import and export of its whole data-base as XML. It's independent from the data-base (Hypersonic, PostgreSQL, MySQL, Oracle etc.). You can choose this method to migrate your data-base from one data-base to any other data-base supported by ProjectForge.

5.5.1 Export

It's possible to export an XML-Dump from your data-base using the system administration dialogue (web). This backup contains all data of ProjectForge in one zipped xml file.

5.5.2 Import

  1. First you need a fresh data-base (without any tables and data).
  2. Afterwards start ProjectForge with the connection data to your new data-base.
  3. Upload the XML or zipped XML file inside the setup-page (which is shown automatically in your web-browser for empty data-bases). Leave any other input fields such as password etc. untouched.
  4. Press the upload button.
  5. Watch the results in the log messages. ProjectForge will verify each single entry by comparing each object of the XML file with the imported data-base objects (each single field of every object is compared.) Any inconsistency or difference is shown in the log file.
  6. Now you can login into ProjectForge.

5.5.3 Limitations

The limitation is the web servers memory. It's planned to support very large ProjectForge data-bases using different xml files. Please request this feature e. g. inside the help forum if needed. For migration without changing the data-base vendor the data-base specific dump and restore mechanism are recommended for large data-bases.

Hint

Please note: After an import of a dump file into a new ProjectForge installation all primary keys are changed! ProjectForge ensures the integrity of all data including the history entries.

5.6 Backup

All datasets of ProjectForge® will be stored in the underlaying database (e. g. PostgreSQL).
You should install an Unix cron script making frequently a backup of the database. A dump of containing table entries as SQL statements for PostgreSQL is possible by using:
 pg_dump -D -U projectforge -f pf_dump_`date '+%Y-%m-%d_%H-%M'`.sql

5.7 Restoring a backup

 psql -q -f projectforge_2008-05-12_02-00.sql -U postgres projectforge 2>&1 > log.txt
For further details concerning dropping and creating a new data base, see 3.3.3 .
Don't forget to create indices (see 3.4 )!

Hint

If you want to use productive data in your develepment system for testing, it's recommended to set all e-mail addresses of the users to your developers e-mail. Also all passwords can be easily set to test123 if you user folliwing sql statement in your test database (not productive!):
 update t_pf_user SET password='SHA{BC871652288E56E306CFA093BEFC3FFCD0ED8872}', email='m.developer@acme.com';

5.8 Automatical backup

5.8.1 Backup script

Install crontab entry as user projectforge on your ProjectForge® server starting the following script:
 File: pforgebackup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

PGSQL_DIR=/usr/bin
BACKUPDIR=/home/projectforge/backup
BASENAME=projectforge PASSWD=...

echo Starting backup of ProjectForge ...
BACKUPFILE=$BACKUPDIR/${BASENAME}_`date '+%Y-%m-%d_%H-%M'`.sql

echo Using filename $BACKUPFILE ...
echo Exporting ...
$PGSQL_DIR/pg_dump -D -U projectforge -W $PASSWD -f $BACKUPFILE

echo Zipping backupfile ...
gzip $BACKUPFILE

# For using scp for remote backup:
#scp $BACKUPFILE <user>@backup.mydomain:backup/

echo Deleting backups older than 14 days
find $BACKUPDIR -mtime +14 | xargs rm 

echo Backup of ProjectForge finished.
For allowing pg_dump without prompting password (if set), you can add the following line to:
 File: pg_hba.conf
 local projectforge projectforge ident sameuser

5.8.2 Adding crontab

Adding following entry to the Unix crontab:
1
2
# run every day at 2:00 am
0 2 * * * /home/projectforge/bin/pforgebackup.sh

5.8.3 Remote backup

For remote backup via scp you need to use key authorization:
  1. Generate keys (using empty password) ssh-keygen
  2. Copy your public key, e. g. identity.pub to your backup server.
  3. Add this key on the backup server to the authorized keys.

5.8.4 Polling remote backup

For security reasons it's also possible to get the backup files from the ProjectForge® server with a cronjob starting e. g. one hour later:
 File: pforgePollBackup.sh
1
2
3
4
5
6
7
#!/bin/bash

SERVER=projectforge.mydomain
DIR=/home/projectforge/backup
REMOTE_DIR=backup REMOTE_USER=projectforge

rsync -avz -e "ssh -P" -C $REMOTE_USER@$SERVER:$REMOTE_DIR $DIR
In that case you have to generate ssh key on your backup server and to add it to the authorized keys on your ProjectForge® server.
Add the following entry to your crontab on the backup server: # run every day at 3:00 am 0 3 * * * /home/projectforge/bin/pforgePollBackup.sh

5.9 Scheduler

5.9.1 Data base search index

The re-index job starts every night at 4 AM (UTC). If an error occurs an e-mail is sent to the admin e-mail addresses configured via web administration. If not configured, no e-mail is sent.

5.10 Spaces

5.10.1 Store

All spaces are stored in the gwiki folder of your ProjectForge home directory. For example: ~/ProjectForge/gwiki/<SPACENAME>/
Spaces are named by their ID representing the database spaces object.

5.10.2 Deletion or historization of spaces

If a spaces is marked for deletion, the corresponding wiki files, stored on filesystem, will not been deleted. You are required to handle the history- and backup management by your own, for example by renaming or moving corresponding spaces. If a deleted space will be recovered by it's history, the space needs his physical wiki files.

5.11 Uninstalling ProjectForge

You only need to delete the Exe-File (or war-file if deployed as war) and the working directory you've chosen / configured. If you're not sure, where ProjectForge's working directory is located, please restart ProjectForge and see for the directory in the log output or configuration tab of the standalone version.

Hint

Please note: If you delete the working directory, all your data base entries are deleted as well!

6 Webserver Tomcat

6.1 server.xml

 File: doc/resources/tomcat/server.xml
1
2
3
4
5
6
7
8
9
10
11
<Server port="8005" shutdown="SHUTDOWN">    
  <Service name="Catalina">
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="/home/projectforge/apache-tomcat-6.0.14/tomcat-localhost.keystore"
               compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata"
               compressableMimeType="text/css,text/html,text/javascript,text/plain,text/xml"
               URIEncoding="UTF-8" />
  </Service>
</Server>

6.2 context.xml

 File: $CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<Context path="" reloadable="false" debug="0" docBase="webapps" cookies="false">
  <Resource name="ProjectForgeDS" type="javax.sql.DataSource" auth="Container" driverClassName="org.postgresql.Driver"
    url="jdbc:postgresql://localhost:5432/projectforge" maxActive="100" maxIdle="30" maxWait="10000" username="projectforge" password="" />
  <Parameter name="base.dir" value="${user.home}/ProjectForge" override="false" />
  <Parameter name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" override="false" />
  <Parameter name="hibernate.schemaUpdate" value="false" override="false" />
  <Parameter name="development" value="true" override="false" />
</Context>

6.3 Increase memory and environment for Tomcat

 File: apache-tomcat/bin/setenv.sh
 export JAVA_OPTS="-Duser.timezone=UTC -Xmx512m -XX:PermSize=96m -XX:MaxPermSize=192m -Djava.awt.headless=true"

6.4 Generating SSL key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
keytool -genkey -keystore tomcat-localhost.keystore -alias tomcat -keyalg RSA -keysize 1024 -keypass changeit -storepass changeit
Wie lautet Ihr Vor- und Nachname?
 [Unknown]:  localhost
Wie lautet der Name Ihrer organisatorischen Einheit?
 [Unknown]:
Wie lautet der Name Ihrer Organisation?
 [Unknown]:
Wie lautet der Name Ihrer Stadt oder Gemeinde?
 [Unknown]:
Wie lautet der Name Ihres Bundeslandes oder Ihrer Provinz?
 [Unknown]:
Wie lautet der Landescode (zwei Buchstaben) für diese Einheit?
 [Unknown]:
Ist CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown richtig?
 [Nein]:  Ja

6.5 Webapp Lambda-Probe

Sehr nützliches Tool zur Überwachung von Speicher, Connections, Use-age etc. ist www.lambdaprobe.org .
 File: conf/tomcat-users.xml
1
2
3
4
5
6
7
8
9
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="manager"/>
  <role rolename="tomcat"/>
  <role rolename="poweruser"/>
  <role rolename="poweruserplus"/>
  <role rolename="probeuser"/> <!-- Read-only access -->
  <user username="probeuser" password="<password>" roles="probeuser"/>
</tomcat-users>
 File: bin/setenv.sh
1
2
# Needed by probe: -Dcom.sun.management.jmxremote
export JAVA_OPTS="-Duser.timezone=UTC -XX:PermSize=96m -XX:MaxPermSize=192m -Djava.awt.headless=true -Dcom.sun.management.jmxremote"
 File: conf/server.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Server port="8005" shutdown="SHUTDOWN">    
  <GlobalNamingResources>
    <!-- Used by Manager webapp -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
       description="User database that can be updated and saved"
           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  ...
        <Engine name="Catalina" defaultHost="www.projectforge.org">
           <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
             resourceName="UserDatabase" />
             ...
        </Engine>
    </Service>
</Server>

7 FAQ

7.1 Reset passwords

As an administration user you can reset the user's passwords. If you've lost the administrator's password you can reset the password by updating the database entry like
 update t_pf_user SET password='SHA{2F1E969683DE272AC96D5AA6033E93A8CB2F283F}' where username='admin';
This encrypted passwords represents 'manage'. See the log file for encrypted passwords after login failures, if you want to set another password via sql. For HypersonicSQL shutdown the server and edit the ProjectForgeDB.script file like this:
 INSERT INTO T_PF_USER VALUES(1, ..., 'SHA{2F1E969683DE272AC96D5AA6033E93A8CB2F283F}',...,'admin')

7.2 Hypersonic: Could not insert entries to the data base.

If the user can't add new entries (contracts, Gantt charts, MEB entries etc.) to the data-base Hypersonic, please have a look in your ProjectForgeDB.script file. All create-table-statements should have the following entry for the primary key (pk):
CREATE MEMORY TABLE T_...(PK INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY, ...
If the script doesn't contain GENERATED BY DEFAULT ... , please stop your ProjectForge system and edit the script file and restart ProjectForge.