www.pudn.com > ejbca_3_5_3(1).zip > DEVELOP



Using the Issue Tracker
=======================
All checkins to CVS must be followed by an issue in the issue tracker at
http://jira.primekey.se/. This is needed to keep a good changelog, which is
vital for a succesfull release.
The only exceptions to this rule are trivial internal fixes like typos, or
removal of unused imports, constans and the like. Also documentation fixes
does not need to be tracked in jira.
If submitting patches to ejbca comitters, they should be able to create jira
issues if none exist.

Sending patches
===============
If you are not a comitter in CVS we are glad to accept patches. You can send us patches either
in diff format (cvs diff) or created with Eclipse.
You can also send us you complete files that you changed, we can see the diffs in Eclipse.

Please follow these simple guidelines when submitting patches:
- Keep the patch limited, only change the parts related to your patch.
- Do not change other lines, such as whitespace, adding line breaks to java doc etc.
It will make it very very hard for us to review the patch.

Checking in to CVS
==================
When checking in to CVS, make sure the following conditions are met:
- The checkin can be tracked to a Jira issue.
- There is JUnit test coverage for the code.
- There is sufficient documentation for the feature.

When checking in to CVS you must use a checkin comment starting with jira
issue (if linked to a jira issue). For example:
ECA-113: my comment here
In this way jira can make a reference from an issue to specified CVS
checkins, something that is very very useful.

Eclipse
=======
To build succesfully using Eclipse, there are .classpath and .project files in the package and in cvs.
Simply check out EJBCA as a project and you're almost set.
You must define the variable JBOSS_HOME in Window->Preferences->Java->Build Path->Classpath Variables.
Many classes are generated by XDoclet, so you must also do an 'ant' for Eclipse to find all classes needed
to build the project. After checking out the project, defining JBOSS_HOME and running 'ant', you should simply
refresh the project in Eclipse and voila!

You may have to issue the command 'ant genejbcaws' as well to generate web service classes.

You can build javadoc on all APIs used with 'ant javadoc'.

Debugging
=========
You might notice that there is a j2ee:debug target, it will start JBoss in debug mode.
Just fire up your debugger to the default transport and address display on your console and
you're set. You can now debug your application.

Persistance
===========
It is important to use consistent standardized persistance mechanism, so it is the same everywhere. This
makes is easier to maintain if developers know where to find things. In EJBCA the persistance mechanism is:
1. EJB entity beans. Use find-statements declared with EJB-QL in the entity beans to find various things in
different ways.
2. If the above does not work (really really doesn'y work) for performance or some other reason, you can use
JDBC directly from session beans using preparedStatements. When using JDBC directly is is crucial that
you follow the guidelines below about Database connections.

NEVER NEVER use JDBC directly from other paces than session beans (such as servlets etc).

Database connections and statements
===================================
It is very important to close connections and prepared statments when doing direct
JDBC queries. There is a utility class se.anatom.ejbca.util.JDBCUtil that helps minimize
code for this. All direct JDBC queries must be encapsulated in in a try/finally clause
as shown below:

Connection con = null;
PreparedStatement ps = null;
try {
// Do stuff,,,
} catch (Exception e) {
// handle error
} finally {
JDBCUtil.close(con);
JDBCUtil.close(ps);
}

BouncyCastle provider
=====================
EJBCA uses the BouncyCastle (BC) jce provider.
To handle redeploy you must use the static method:

CertTools.installBCProvier()

to install the provider if needed.

Subject and Issuer DNs
======================
Handling of subject and issuer DNs must be done in an extremely predictable way,
and in the same way everywhere. Issue are ordering of DN elements, handling of
localized strings (UTF8) etc. Because of this, there are a few methods in
se.anatom.ejbca.util.CertTools that MUST be used when handling DNs:

stringToBCDNString() - when handling user input of a DN string to store od
match.
getSubjectDN(cert) - extracts subject DN from a certificate
getIssuerDN(cert) - extracts issuer DN from a certificate
getIssuerDN(crl) - - extracts issuer DN from a CRL

Logging
=======

Straight console output (System.out) MUST not be used in EJBCA except in
cases of console admin utilities.

There are two types of logging in EJBCA:

1. CA logs, defining important events. These logs end up in the database and can
be searched through the administration Web-GUI.

2. Error and debug logs. These logs use Log4j and end up in a log file defined
in JBoss.

Use the Utils
=============
For the most mundane repetitive tasks there are usually util classes in either org.ejbca.util or in the apache
commons classes that will help avoid the same code beeing copied everywhere.

Check them out and learn to use the utils!

CA logs
-------

There are three important classes:
Admin : Defines the administrator that performed the action.
LogEntry : Represents a line in the log database. Only the contants defined
here are used.
ILogSessionRemote/Local : The log functionality itself.

To perform logging, one must first aquire the remote interface to the log
session:
ILogSessionLocalHome logsessionhome = (ILogSessionLocalHome) getLocator().getLocalHome(ILogSessionLocalHome.COMP_NAME);
logsession = logsessionhome.create();

Next step is to log trough the function 'log', it's as easy as can be.

Parameters to the log function are:
admin : is of the class Admin and is created according to the following
criteria:
1. In case a client certificate exists, new Admin(certificate)
2. In other cases one of the types defined in Admin.TYPE_...
ex: new Admin(Admin.TYPE_RACOMMANDLINE_USER, ip-adress).
If possible, the ip-adress should be passed.
module : is one of the LogEntry.MODULE_ constants and defines in which module
the event occured.
ex : LogEntry.MODULE_CA.
time : the time of the event.
username : describes which user (endentity) that is involved in the event.
null in case no user can be considered to be involved.
certificate : defines which certificate is involved in the event. null in case
no certificate can be considered to be involved.
event : is one of the LogEntry.EVENT_ constants and defines which type of event
occured.
comment : a comment to the event.

If there are events that are not defined it is easy to add new ones, just follow
these steps:
1. Add an EVENT_INFO/ERROR constant to LogEntry
2. Add corresponting text in the constant LogEntry.EVENTNAMES_INFO/ERROR
3. Open the file src/ra/web/raadmin/languages/languagefile.en.properies i a text
editor.
Go through the contants until you come to the EVENT_INFO/ERROR... constants and
add the english translation. Try to keep the list sorted in alphabetical order.

If the three steps are followed the Web-GUI will be automagicaly updated and no
changes need to be done to it.

Error and debug logs
--------------------

EJBCA uses the Apache Log4J package for debug-logging. This means that any class
that wants to do logging or console output MUST define:

/** Log4j instance */
private static Logger log = Logger.getLogger(<class>.class);

Logging is then done with:

log.error("message");
log.info("message");
log.debug("message");

There is also a version of the command that takes an additional Exception as
argument, were the exception stack will be printed to the log.

Where the log ends up is defined in 'log4j.properties'.

Some classes have special pre-prepared logging constructs. They are:

BaseSessionBean.java
BaseAdminCommand.java

This means that classes inheriting from one of these classes does not have to
define their own logger, but can simply use:

error("message");
info("message");
debug("message");

Debugging output for entrance and exit in methods can be added in the following
way:

public int myMethod(int arg) {
log.debug(">myMethod("+arg+")");

int ret = 0;
...

log.debug("<meMethod: return "+ret);
return ret;
}

Making session beans
====================

All session beans should extend the class se.anatom.ejbca.BaseSessionBean.

Making entity beans
===================

All entity beans should extend the class se.anatom.ejbca.BaseEntityBean.
When doing this, the standard methods like setting the context are already in
there. They can however always be overriden.


CVS
===

All files should have the below part in the initial class comment:

@version $Id: DEVELOP,v 1.9 2006/09/18 14:19:32 anatom Exp $

Example:

/**
* The main bean for the web interface, it contains all basic functions.
*
* @version $Id: DEVELOP,v 1.9 2006/09/18 14:19:32 anatom Exp $
*/

All java files should include the following header as the first lines in the file:
/*************************************************************************
* *
* EJBCA: The OpenSource Certificate Authority *
* *
* This software is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or any later version. *
* *
* See terms of license at gnu.org. *
* *
*************************************************************************/


CA KeyStore architecture/creating a custom CA Keystore
======================================================

The CA Keystore, where the CAs private key is stored and used is
defined by the interface se.anatom.ejbca.ca.sign.ISigningDevice.

By creating a new custom class and simply editing the property
'signingDeviceFactory' to point at the custom factory class that creates an
instance of the custom SigningDevice class in a thread-safe way.
It is recommended, but not required, that the Signing device implements a
Singleton.

The SigningDeviceFactory class MUST contain the method:

/** Creates (if needed) the signing device and returns the object.
* @prop Arguments needed fo?r the eventual creation of the object
* @return An instance of the Signing device.
*/
public synchronized ISigningDevice makeInstance(Properties prop) throws
Exception {
return PKCS12SigningDevice.instance(prop);
}

Clear or hashed passwords
=========================

Passwords for users are normally stored SHA1-hashed in the database.

You can retrieve and use the password IF it is stored in clear text.

Use something like this to get the password (snip from BatchMakeP12.java):

IUserAdminSessionRemote admin = adminhome.create();
UserAdminData data = admin.findUser(administrator, username);
if ((data.getPassword() != null) &amt;&amt; (data.getPassword().length() > 0) {
...
}

When creating the user, you must specify that the password should be in clear text,
otherwise it will be stored in hashed form, which will obvoiusly be of no use to you.

If using the Web-GUI there is a checkbox for storing the password in clear format.

If using the command line gui there is a command 'ra setclearpwd'

If using programatically:
In IUserAdminSession there is a flag 'clearpwd' to the method addUser, or you can use
the method setOpenPassword on the UserDataBean object returned from findUser.