<?xml version="1.0"?>
<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-->

<document>

 <properties>
  <title>Coding Standards</title>
  <author email="jon@latchkey.com">Jon S. Stevens</author>
  <author email="jvanzyl@apache.org">Jason van Zyl</author>
 </properties>

<body>

<section name="Coding Standards">

<p>
This document describes a list of coding conventions that are required
for code submissions to the project. By default, the coding conventions
for most Open Source Projects should follow the existing coding conventions
in the code that you are working on. For example, if the bracket is on
the same line as the if statement, then you should write all your code
to have that convention.
</p>

<p>
<strong>If you commit code that does not follow these conventions, you
are responsible for also fixing your own code.</strong>
</p>

<p>
Below is a list of coding conventions that are specific to Apache Commons Net
everything else not specificially mentioned here should follow the official
<a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html">Sun
Java Coding Conventions</a>.
</p>

<p>
1. Brackets should begin and end on a new line and should exist even
for one line statements. Examples:
</p>

<source test=""><![CDATA[
if ( foo )
{
    // code here
}

try
{
    // code here
}
catch (Exception bar)
{
    // code here
}
finally
{
    // code here
}

while ( true )
{
    // code here
}
]]></source>

<p>
2. Though it's considered okay to include spaces inside parens, the
preference is to not include them. Both of the following are okay:
</p>

<source test=""><![CDATA[
if (foo)

or

if ( foo )
]]></source>

<p>
3. 4 space indent. <strong>NO tabs</strong>. Period. We understand
that many developers like to use tabs, but the fact of the matter is
that in a distributed development environment where diffs are sent to
the mailing lists by both developers and the version control system
(which sends commit log messages), the use tabs makes it impossible to
preserve legibility.
</p>

<p>
In Emacs-speak, this translates to the following command:
</p>

<source><![CDATA[
(setq-default tab-width 4 indent-tabs-mode nil)
]]></source>

<p>
4. Native linefeeds (svn:eol-style native) for all .java source code and text files.
Platform specific files should have the platform specific linefeeds.
</p>

<p>
5. JavaDoc <strong>MUST</strong> exist on all public and protected methods.
JavaDoc on private and default access methods and members is preferred and
encouraged.  If your code modifications use an existing class/method/variable
which lacks JavaDoc, it is required that you add it.  This will improve the
project as a whole.
</p>

<p>
6. The Apache License header <strong>MUST</strong> be placed at the top
of each and every file.
</p>

<p>
9. Import statements must be fully qualified for clarity.
</p>

<source><![CDATA[
import java.util.ArrayList;
import java.util.Hashtable;

import org.apache.foo.Bar;
import org.apache.bar.Foo;
]]></source>

<p>
And not
</p>

<source><![CDATA[
import java.util.*;
import org.apache.foo.*;
import org.apache.bar.*;
]]></source>

<hr noshade="true" size="1"/>

<p>
X/Emacs users might appreciate this in their .emacs file.
</p>

<source><![CDATA[
(defun apache-jakarta-mode ()
  "The Java mode specialization for Apache Jakarta projects."
  (if (not (assoc "apache-jakarta" c-style-alist))
      ;; Define the Apache Jakarta cc-mode style.
      (c-add-style "apache-jakarta" '("java" (indent-tabs-mode . nil))))

  (c-set-style "apache-jakarta")
  (c-set-offset 'substatement-open 0 nil)
  (setq mode-name "Apache Jakarta")

  ;; Turn on syntax highlighting when X is running.
  (if (boundp 'window-system)
      (progn (setq font-lock-support-mode 'lazy-lock-mode)
             (font-lock-mode t))))

;; Activate Jakarta mode.
(if (fboundp 'jde-mode)
    (add-hook 'jde-mode-hook 'apache-jakarta-mode)
  (add-hook 'java-mode-hook 'apache-jakarta-mode))
]]></source>

<p>
Thanks for your cooperation.
</p>

</section>

</body>
</document>
