This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
The following commit(s) were added to refs/heads/master by this push:
new 5856e5b QPID-8361: [Broker-J] Create a developer guide for Qpid
Broker-J
5856e5b is described below
commit 5856e5bed957a4d98d5e8ce14944770f6fa75b64
Author: Alex Rudyy <[email protected]>
AuthorDate: Fri Sep 13 07:24:00 2019 +0100
QPID-8361: [Broker-J] Create a developer guide for Qpid Broker-J
The Guide was written in collaboration with Tomas Vavricka
<[email protected]>
This closes #36
---
README.md | 107 +---
doc/developer-guide/pom.xml | 55 ++
doc/developer-guide/src/main/bash/toc-generator.sh | 58 ++
.../src/main/markdown/architecture.md | 601 +++++++++++++++++++++
.../src/main/markdown/build-instructions.md | 310 +++++++++++
.../src/main/markdown/code-guide.md | 466 ++++++++++++++++
.../main/markdown/consumer-queue-interactions.md | 164 ++++++
.../src/main/markdown/examples/maven-settings.md | 36 ++
.../src/main/markdown/ide-integration.md | 46 ++
.../src/main/markdown/images/broker-loggers.gliffy | 1 +
.../src/main/markdown/images/broker-loggers.png | Bin 0 -> 100236 bytes
.../src/main/markdown/images/exchanges.gliffy | 1 +
.../src/main/markdown/images/exchanges.png | Bin 0 -> 58921 bytes
.../src/main/markdown/images/io.gliffy | 1 +
.../src/main/markdown/images/io.png | Bin 0 -> 76626 bytes
.../src/main/markdown/images/model.gliffy | 1 +
.../src/main/markdown/images/model.png | Bin 0 -> 44231 bytes
.../src/main/markdown/images/pluggability.gliffy | 1 +
.../src/main/markdown/images/pluggability.png | Bin 0 -> 51018 bytes
.../src/main/markdown/images/subscriptions.gliffy | 1 +
.../src/main/markdown/images/subscriptions.png | Bin 0 -> 21943 bytes
.../src/main/markdown/images/transactions.gliffy | 1 +
.../src/main/markdown/images/transactions.png | Bin 0 -> 47086 bytes
.../markdown/images/virtualhost-loggers.gliffy | 1 +
.../main/markdown/images/virtualhost-loggers.png | Bin 0 -> 83183 bytes
doc/developer-guide/src/main/markdown/index.md | 30 +
.../src/main/markdown/quick-start.md | 124 +++++
.../src/main/markdown/release-instructions.md | 192 +++++++
doc/pom.xml | 1 +
29 files changed, 2105 insertions(+), 93 deletions(-)
diff --git a/README.md b/README.md
index 6afc788..38bb999 100644
--- a/README.md
+++ b/README.md
@@ -32,108 +32,29 @@ Below are some quick pointers you might find useful.
## Building the code
-The project requires Maven 3. Some example commands follow.
+The [Quick Start Guide](doc/developer-guide/src/main/markdown/quick-start.md)
walks you through the steps required
+to build, test and run Qpid Broker-J.
-Clean previous builds output and install all modules to local repository
without running the tests:
-
- mvn clean install -DskipTests
-
-Install all modules to the local repository after running all the tests:
-
- mvn clean install
-
-## Running the tests
-
-Maven profiles are used to run tests for the supported protocols and storage
options.
-Profile names follow the form *java-store.n-n*, where
- *store* signifies the storage module and
- *n-n* the AMQP protocol version number.
-
-For store, the options include:
-
-* *bdb* - Oracle BDB JE
-* *dby* - Apache Derby
-* *mms* - an in-memory store principally used for testing.
-
-If no profile is explicitly selected, *java-mms-1.0* is activated by default.
-
- mvn verify
-
-To activate a BDB with AMQP 1.0 protocol use:
-
- mvn verify -P java-bdb.1-0
-
-To see all the available profiles.
-
- mvn help:all-profiles
-
-When activating AMQP 0-8..0-10 profiles, it is also necessary to pass the
system property *-DenableAmqp0-x*
-
- mvn verify -P java-dby.0-9-1 -DenableAmqp0-x
-
-Perform a subset of tests on the packaged release artifacts without installing:
-
- mvn verify -Dtest=TestNamePattern* -DfailIfNoTests=false
-
-Integration tests except for protocol tests are disabled by default.
-In order to run all integration tests, they need to be enabled with a flag
-DskipITs=false, for example
-
- mvn verify -DskipITs=false
-
-Execute the tests and produce code coverage report:
-
- mvn clean test jacoco:report
-
-## Distribution assemblies
-
-To produce broker assemblies, use:
-
- mvn clean package -DskipTests
-
-The broker distribution assemblies will then be found beneath:
-
- apache-qpid-broker-j/target
+The [Build
Instructions](doc/developer-guide/src/main/markdown/build-instructions.md)
cover all details behind building
+and testing.
## Running the Broker
-For full details, see the Getting Started documentation in the docbook
documentation mentioned below. For convenience brief instructions are repeated
here.
-
-
-### Start the Broker
-
-#### From an assembly on the command line
+For full details, see the `Getting Started` in User documentation mentioned
below.
-Expand the assembly produced by the Maven package lifecycle stage, and the
execute the qpid-server script or batch file.
+For convenience, the brief instructions are repeated in the
+[Quick Start Guide](doc/developer-guide/src/main/markdown/quick-start.md).
-On UNIX:
+### IDE Integration
- tar xvfz
apache-qpid-broker-j/target/apache-qpid-broker-j-x.x.x-SNAPSHOT-bin.tar.gz
- ./java-broker/x.x.x/qpid-server
-
-On Windows:
-
- Expand zip
apache-qpid-broker-j/target/apache-qpid-broker-j-x.x.x-SNAPSHOT-bin.zip
- .\java-broker\x.x.x\qpid-server.bat
-
-#### From an IDE
-
-These instructions assume Intellij.
-
-1. Within the IDE import the top level pom.xml file as a project.
-2. Create a new Application run configuration called "Qpid Broker"
- * Classname org.apache.qpid.server.Main
- * Classpath of module: qpid-broker
- * Save the new run configuration.
-3. Go into the module settings of qpid-broker and add an additional classpath
entry pointing to the dojo-x.x.x-distribution.zip. It is easiest to point to a
location in the local maven repo e.g.
~/.m2/repository/org/dojotoolkit/dojo/x.x.x/dojo-x.x.x-distribution.zip. (This
manual step is required to workaround
https://issues.apache.org/jira/browse/MNG-5567).
-
-### Connecting to the Broker
-
-By default, the Broker listens on port 5672 for AMQP and 8080 for http
management. The default
-username 'guest' and password 'guest'.
-
-To get to the management console, point a browser to http://localhost:8080
+Tips on setting up IDE to work with Qpid Broker-J project are provided in
+[IDE Integration](doc/developer-guide/src/main/markdown/ide-integration.md).
## Documentation
Documentation (in docbook format) is found beneath the *doc* module.
+Links to latest published User documentation can be found in overview of
+[Broker-J Component](http://qpid.apache.org/components/broker-j/index.html).
+
+Please check [Developer Guide](doc/developer-guide/src/main/markdown/index.md)
for developer documentation.
diff --git a/doc/developer-guide/pom.xml b/doc/developer-guide/pom.xml
new file mode 100644
index 0000000..ef38575
--- /dev/null
+++ b/doc/developer-guide/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-java-doc</artifactId>
+ <version>8.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>qpid-broker-j-developer-guide</artifactId>
+ <name>Apache Qpid Broker-J Developer Guide</name>
+ <description>Apache Qpid Broker-J Developer Guide</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/*.gliffy</exclude>
+ <exclude>**/*.md</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/doc/developer-guide/src/main/bash/toc-generator.sh
b/doc/developer-guide/src/main/bash/toc-generator.sh
new file mode 100755
index 0000000..e66c3ce
--- /dev/null
+++ b/doc/developer-guide/src/main/bash/toc-generator.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+SCRIPT=$(readlink -f "$0")
+SCRIPT_PATH=$(dirname "$SCRIPT")
+DOC_PATH=$(readlink -f "$SCRIPT_PATH/../markdown")
+declare -a ARTICLES=("architecture" "build-instructions"
"consumer-queue-interactions" "code-guide" "release-instructions")
+
+function npm-do { (PATH=$(npm bin):$PATH; eval $@;) }
+
+function generate-toc {
+ for ARTICLE in "${ARTICLES[@]}"
+ do
+ ARTICLE_PATH=${DOC_PATH}/${ARTICLE}.md
+ if [ -f "${ARTICLE_PATH}" ]; then
+ echo "Generating TOC for ${ARTICLE}.md"
+ npm-do markdown-toc ${ARTICLE_PATH} -i:
+ else
+ echo "Cannot find ${ARTICLE}.md at ${DOC_PATH}"
+ fi
+ done
+}
+
+if [ ! -f "${DOC_PATH}/index.md" ]; then
+ echo "Cannot find developer guide 'index.md' at expected location
'${DOC_PATH}'"
+ exit 1
+fi
+
+if ! command npm -v >/dev/null 2>&1 ; then
+ echo "This script uses 'npm' and 'markdown-toc' to generate table of
contents for develop guide articles"
+ echo "Please install npm or/and Node.js"
+ exit 2
+fi
+
+if ! command echo "## header" | npm-do markdown-toc - >/dev/null 2>&1 ; then
+ echo "This script uses 'npm' and 'markdown-toc' to generate table of
contents for develop guide articles"
+ echo "Please install 'markdown-toc': npm install --save markdown-toc"
+ exit 3
+fi
+
+generate-toc
diff --git a/doc/developer-guide/src/main/markdown/architecture.md
b/doc/developer-guide/src/main/markdown/architecture.md
new file mode 100644
index 0000000..8c8f0db
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/architecture.md
@@ -0,0 +1,601 @@
+# High Level Architecture
+
+This article provides a high level description of the architecture of Qpid
Broker-J.
+
+<!-- toc -->
+
+- [Introduction](#introduction)
+- [Model](#model)
+- [Category Specializations](#category-specializations)
+ * [Attributes](#attributes)
+ * [Context Variables](#context-variables)
+- [Lifecycle](#lifecycle)
+- [AbstractConfiguredObject](#abstractconfiguredobject)
+- [Threading Model](#threading-model)
+- [Configuration Persistence](#configuration-persistence)
+- [AMQP Transport Layer](#amqp-transport-layer)
+ * [TCP/IP](#tcpip)
+ * [IO Threading](#io-threading)
+ * [TLS](#tls)
+ * [Idle timeout](#idle-timeout)
+ * [Websocket](#websocket)
+- [AMQP Protocol Engines](#amqp-protocol-engines)
+ * [Accepting bytes](#accepting-bytes)
+ * [Producing bytes](#producing-bytes)
+- [Exchanges](#exchanges)
+- [Queues](#queues)
+ * [Enqueueing](#enqueueing)
+ * [Subscriptions](#subscriptions)
+ * [Messages](#messages)
+ * [Message and Configuration Store](#message-and-configuration-store)
+- [Messaging Transactions](#messaging-transactions)
+- [Management](#management)
+ * [AMQP management](#amqp-management)
+ * [HTTP management](#http-management)
+- [Pluggable Architecture](#pluggable-architecture)
+- [Logging](#logging)
+
+<!-- tocstop -->
+
+## Introduction
+
+Broker-J is messaging broker that implements the AMQP protocols (version 0-8,
0-9, 0-91, 0-10 and 1.0).
+Any AMQP compliant messaging library can be used with the Broker. The Broker
supports on the fly message translation
+from one AMQP protocol to another, meaning it is possible to use the Broker to
allow clients that use different
+AMQP protocol version to exchange messages. It can be managed over a built in
HTTP interface
+(that presents a REST API and a Web Management Console) or by AMQP Management
(early draft implementation).
+
+The Broker has a highly pluggable architecture that allows alternative
implementations to be substituted for any concern.
+For instance, you can simply build a module delegating to your own storage or
own authentication provider linking
+to your enterprise authentication backend.
+
+Broker-J is 100% pure Java. It can be run standalone or embedded within
another Java applications.
+
+## Model
+
+A tree of manageable categories, all of which extend of the interface
`ConfiguredObject`, underpin the `Broker`.
+A `ConfiguredObject` has zero or more attributes, zero or more children and
zero or more context variable name/value pairs.
+A `ConfiguredObject` may be persisted to a configuration store so its state
can be restored when the Broker is restarted.
+The manageable categories are arranged into a tree structure. `SystemConfig`
is at the root and has a single descendent
+`Broker`. The `Broker` itself has children: `Port`, `AuthenticationProvider`,
`VirtualHostNode` amongst others.
+`VirtualHostNode` has a child `VirtualHost`. The children of the `VirtualHost`
are categories that directly involved
+in messaging such as `Queue`. The diagram below illustrates the category
hierarchy but many categories are elided for brevity.
+The model tree structure is codified in the `BrokerModel` class.
+
+
+
+## Category Specializations
+
+Some categories have specialisations. An example is the category `Queue`. It
has specialisations corresponding to
+the queue types supported by the `Broker` e.g. `StandardQueue`,
`PrirorityQueue` etc.
+
+### Attributes
+
+Each `ConfiguredObject` instance has zero or more attributes. Attributes have
a name and a value which can be
+a Java primitive value or an instance of any class for which an
`AttributeValueConverter` exist. This mechanism allows
+attribute values to be `Lists`, `Sets`, `Maps`, or arbitrary structured types
`ManagedAttributeValues`.
+
+Attributes are marked up in the code with method annotations
`@ManagedAttribute` which defines things
+whether the attribute is mandatory or mutable. Attributes can also be marked a
secure which indicates restrictions
+on how the attribute is used (used for attributes that that store passwords or
private-keys).
+
+Attributes can have default values. The default value applies if the user
omits to supply a value when the object
+is created. Defaults themselves can be defined in terms of `context variable`
references.
+
+### Context Variables
+
+Each `ConfiguredObject` instance has zero or more context variable
assignments. These are simply name/value pairs
+where both name and value are strings.
+
+When resolving an attribute's value, if the attribute's value (or attribute's
default) contains a context variable
+reference (e.g. `${foo}`), the variable is first resolved using the
`ConfiguredObject`'s own context variables.
+If the `ConfiguedObject` has no definition for the context variable, the
entity's parent is tried,
+then its grandparent and so forth, all the way until the `SystemContext` is
reached.
+If the `SystemContext` provides no value, the JVM's system properties are
consulted.
+
+A context variable's value can be defined in terms of other context variables.
+
+Context variables are useful for extracting environment specific information
from configuration for instance path stems
+or port numbers.
+
+## Lifecycle
+
+`ConfiguredObjects` have a lifecycle.
+
+A `ConfiguredObject` is created exactly once by a call its parent's
`#createChild()` method.
+This brings the object into existence. It goes through a number of phases
during creation (`ConfiguredObject#create`)
+
+ * resolution (where the attribute values are resolved and assigned to the
object)
+ * creation validation (ensuring business rules are adhered to)
+ * registration with parents
+ * implementation specific creation (`#onCreate`)
+ * implementation specific opening (`#onOpen`)
+
+When the `Broker` is restarted objects that exist in the configuration store
are said to be recovered.
+During recovery, they follow the opening (`ConfiguredObject#open`)
+
+ * resolution (where the attribute values are resolved and assigned to the
object)
+ * validation (ensuring business rules are adhered to)
+ * implementation specific opening (#onOpen)
+
+Some `ConfiguredObjects` support starting (`ConfiguredObject#start()`) and
stopping (`ConfiguredObject#stop()`)
+but this have not yet been extended to all objects.
+
+`ConfiguredObject#delete()` caused the object to be deleted.
+
+## AbstractConfiguredObject
+
+Most configured object implementations extend `AbstractConfiguredObject`
(ACO). ACO provides the mechanics
+behind the configured implementations: attributes, context variables, state
and lifecycle,
+and a listener mechanism: `ConfigurationChangeListener`.
+
+## Threading Model
+
+The threading model used by the model must be understood before changes can be
made safely.
+
+The `Broker` and `VirtualHost` `ConfiguredObject` instances have a task
executor backed by single configuration thread.
+Whenever the a configuration object needs to be changed, that change MUST be
made by the nearest ancestor's
+configuration thread. This approach ensures avoids the need to employ locking.
Any thread is allowed to observe
+the state of a `ConfiguredObject` at any time. For this reasons, changes must
be published safely, so they can be
+read consistently by the observing threads.
+
+The implementations of the mutating methods (`#setAttributes()`, `#start()`,
#`stop()`, etc) within
+`AbstractConfiguredObject` are already implemented to adhere to these rules.
+
+## Configuration Persistence
+
+`ConfiguredObject` categories such as `SystemConfig` and `VirtualhostNode`
take responsibility for managing the storage
+of their children. This is marked up in the model with the `@ManagedObject`
annotation (`#managesChildren`).
+These objects utilise a `DurableConfigurationStore` to persist their durable
children to storage.
+`ConfigurationChangeListener` is used to trigger the update of the storage
each time a `ConfiguredObject` is changed.
+
+## AMQP Transport Layer
+
+At the high level, the transport layer
+
+ * accepts bytes from the wire and passes them to the protocol engines.
+ * pulls bytes from the protocol engines and pushes them down the wire.
+
+There are two AMQP Transport Layers in Broker-J.
+
+ * Traditional TCP/IP connections
+ * Websocket
+
+We'll consider the two layers separately below.
+
+The transport is responsible for TLS. The TLS configuration is defined on the
`Port`, `Keystore` and `Truststore`
+model objects. If so configured, it is the transport's responsibility to
manage the TLS connection.
+
+### TCP/IP
+
+This layer is implemented from first principles using Java NIO.
+
+It is non-blocking in nature.
+
+It uses a `Selector` to monitor all connected sockets (and the accepting
socket) for work.
+Once work is detected (i.e. the `selector` returns) the connection work is
serviced by threads drawn from
+an IO thread pool. An
[eat-what-you-kill](https://webtide.com/eat-what-you-kill/) pattern is used to
reduce dispatch latency.
+This works in the following way. The worker thread that performed the select,
after adding all the ready connections
+to the work queue, adds the selector task to the work queue and then starts to
process the work queue itself
+(this is the eat what you kill bit). This approach potentially avoids the
dispatch latency between the thread
+ that performed select and another thread from the IO thread pool. The
`Selector` is the responsibility of the
+`SelectorThread` class.
+
+A connections to a client is represented by a `NonBlockingConnection`
instance. The `SelectorThread` causes the
+`NonBlockingConnections` that require IO work to be executed
(`NonBlockingConnection#doWork`) on a thread from
+an IO thread pool (owned by `NetworkConnectionScheduler`). On each work cycle,
the `NonBlockingConnection` first goes
+through a write phase where pending work is pulled from the protocol engine
producing bytes for the wire in the process.
+If all the pending work is sent completely (i.e. the outbound network buffer
is not exhausted),
+the next phase is a read phase. The bytes are consumed from the channel and
fed into the protocol engine.
+Finally, there is a further write phase to send any new bytes resulting from
the input we have just read.
+The write/read/write sequence is organised so in order that the `Broker` first
evacuates as much state from memory
+ as possible (thus freeing memory) before reading new bytes from the wire.
+
+In addition to the `NonBlockingConnection` being scheduled when singled by the
`Selector`, the `Broker` may need
+to awaken them at other times. For instance, if a message arrives on a queue
that is suitable for a consumer,
+the `NonBlockingConnection` associated with that consumer must awoken. The
mechanism that does this is
+`NetworkConnectionScheduler#schedule` method which adds it to the work queue.
This is wired to the protocol engine via
+a listener.
+
+The class diagram below depicts IO Model
+
+
+
+### IO Threading
+
+The only threads that execute `NonBlockingConnnections` are those of the
`NetworkConnectionScheduler`.
+Furthermore, it is imperative that no `NonBlockingConnnection` is executed by
more than one thread at once.
+It is the job of `ConnectorProcessor` to organise this exclusivity. Updates
made by `NonBlockingConnnection` must
+be published safely so they can be read consistently by the other threads in
the pool.
+
+There is a `NetworkConnectionScheduler` associated with each AMQP Port and
each `VirtualHost`.
+When a connection is made to the `Broker`, the initial exchanges between peer
and broker
+(protocol headers, authentication etc) take place on the thread pool of the
`NetworkConnectionScheduler` of the `Port`.
+Once the connection has indicated which `VirtualHost` it wishes to connect to,
responsibility for the
+`NonBlockingConnection` shifts to the `NetworkConnectionScheduler` of the
`VirtualHost`.
+
+### TLS
+
+The TCP/IP transport layer responds to the TLS configuration provided by the
`Port`, `Keystore` and `Truststore` model
+objects. It does this using the `NonBlockingConnectionDelegates`.
+
+ * The `NonBlockingConnectionUndecidedDelegate` is used to allow Plain/TLS
port unification feature
+ (that is support for plain and TLS from the same port). It sniffs the
initial incoming bytes to determine
+ if the peer is trying to negotiate a TLS connection or not. Once the
determination is made one of the following
+ delegates is substituted in its place.
+ * `NonBlockingConnectionTLSDelegate` is responsible for TLS connections. It
feeds the bytes through an SSLEngine.
+ * `NonBlockingConnectionPlainDelegate` is used for non-TLS connections.
+
+### Idle timeout
+
+All versions of the AMQP protocol support the idea of the peers regularly
passing null data to keep a wire that would
+otherwise by silent (during quiet times) busy. This is called idle timeout or
heartbeating. It is configured during
+connection establishment. If a peer detects that counterpart has stopped
sending this data, it can infer
+that the network connection has failed or the peer has otherwise become
inoperable and close the connection.
+Sending of the null data is the responsibility of the
`ServerIdleWriteTimeoutTicker`. Responsibility of detecting
+the absence of data from the peer is `ServerIdleReadTimeoutTicker`. When the
`Selector` blocks awaiting activity
+the timeout is the minimum timeout value of all Tickers.
+
+### Websocket
+
+AMQP 1.0 specification defines AMQP 1.0 over web sockets. The earlier version
of the protocols didn't do this
+but the implementation within the `Broker` actually supports Websocket
transport.
+
+The websocket transport layer (`WebSocketProvider`) uses Jetty's websocket
module. The methods of class
+`AmqpWebSocket` are annotated with the Jetty websocket annotations
`OnWebSocketConnect`, `OnWebSocketMethod`,
+and `OnWebSocketClose`. The method implementations cause `ProtocolEngine`
instances to handle new connection,
+process bytes passed to the engine, or close respectively. When the protocol
engine signals the need to work,
+a Jetty thread is used to pull the pending bytes bytes from the protocol engine
+`WebSocketProvider.ConnectionWrapper#doWork`. The websocket transport tries to
remain as close to the TCP/IP
+transport layer.
+
+The `Port`, `Keystore` and `Truststore` model objects are used to configure
the websocket connection according
+to the TLS requirements.
+
+
+## AMQP Protocol Engines
+
+The `ProtocolEngine`:
+
+ * accepts bytes from the transport (`ProtocolEngine#received`).
+ * exposes a public method (`ProtocolEngine#processPendingIterator`) which is
used by the transport layer
+ to pull pending tasks that produce bytes for the wire from the engine.
+
+The engine never pushes bytes onto the transport.
+
+### Accepting bytes
+
+The transport references an instance of the `MultiVersionProtocolEngine`.
Internally the `MultiVersionProtocolEngine`
+delegates to other `ProtocolEngine` implementations. It switches from one
implementation to another during
+this connection's life.
+
+In this beginning, the `MultiVersionProtocolEngine` does not know which
version of the AMQP protocol the peer wishes
+to use. Internally it begins by delegating to a `SelfDelegateProtocolEngine`
until sufficient header bytes have arrived
+from the wire to make a determination (all AMQP protocols begin with the bytes
AMQP followed by a version number).
+Once a determination is made, a `ProtocolEngine` that supports the correct
AMQP protocol is substituted in its place
+(an implementation of `AMQPConnection`). The other alternative is that the
desired protocol is not supported.
+In this case a supported AMQP header is sent down the wire and the connection
closed.
+
+There is an implementation of `AMQPConnection` for every AMQP protocol:
+
+ * `AMQPConnection_0_8Impl` - for AMQP 0-8..0-91
+ * `AMQPConnection_0_10Impl` - for AMQP 0-10
+ * `AMQPConnection_1_0Impl` - for AMQP 1.0
+
+The `AMQPConnection#received` method accepts the raw bytes. The connection
implementation uses AMQP codecs
+to turn this stream of bytes into a stream of objects representing the AMQP
frames.
+The frames are then dispatched to the connection implementation itself (or
other objects that the connection has caused
+to come into existence).
+
+Unfortunately, there is no commonality between the AMQP codec implementations.
For 0-8..0-91 it is a `ServerDecoder`,
+for 0-10 a `ServerDisassembler` and for AMQP 1.0 a `ProtocolHandler`.
+
+As the AMQP protocols differ, the dispatch methods are necessarily different
but the approach is similar across
+the protocols. Here's some examples to get you started.
+
+ * `AMQPConnection_0_8Impl#received` ultimately delegates to methods such as
`AMQPConnection_0_8Impl#receiveConnectionStartOk`
+ * `AMQPConnection_0_10Impl#received` ultimately delegates to delegate
`ServerConnectionDelegate#connectionStartOk`
+ * `AMQPConnection_1_0Impl#received` ultimately delegates to
`AMQPConnection_1_0Impl#receiveOpen`
+
+### Producing bytes
+
+As already said, the transport pulls tasks from the protocol engine. These
tasks produce bytes. To do this,
+the transport calls the pending iterator which provides a stream of tasks that
generate bytes for the wire.
+The transport keeps pulling until the output exceeds the buffer. It then tries
to write the buffered bytes to the wire.
+If it writes more than half to the wire it continues to pull more tasks from
the engine.
+The cycle continues until the transport cannot take more bytes (back pressure
at the TCP/IP layer
+or the pending iterator yields no more tasks). This arrangement always means
that the transport retains control of
+backlog of bytes to be written to the wire.
+
+The protocol engines' pending iterators are responsible for maintaining
fairness within the connection.
+They do this by maintaining state between invocations. For instance if a
connection had sessions A, B, C,
+all with tasks to producer and on this output cycle, the network stopped
accepting bytes after A's tasks,
+on the next output cycle. B would be considered first, even if A had
subsequently had more work. This fairness pattern
+is repeated through each layer of the protocol.
+
+## Exchanges
+
+`Exchange` model objects provide the message routing functionality.
+
+There are several specialisations of `Exchange`
+
+ * `Direct`; routes messages into bound queues based on exact match of message
routing key and queue binding key
+ * `Topic`; routes messages into bound queues using wildcard match of message
routing key and the binding key pattern
+ defined on queue binding
+ * `Fanout`; routes messages to all bound queues regardless their binding key
+ * `Headers`; routes messages to bound queues based on message header
properties satisfying the `x-match expression`
+ specified as part of queue binding arguments
+
+Please, refer [Qpid Broker-J
Documentation]((http://qpid.apache.org/components/broker-j/index.html)) for
more detailed
+description of `Exchange` routing algorithms.
+
+Please note, that `VirtualHost` provides special routing functionality for
messages published into so-called `default`
+destination, which works similar to direct exchange and routes messages into a
`VirtualHost` `Queue` based on exact
+match of message routing key and a queue name. This functionality is mandated
by AMQP 0-x protocols.
+
+The model class diagram is provided below
+
+
+All exchange implementations extend `AbstractExchange` and implement the
exchange specific routing functionality in
+methods declared as abstract in `AbstractExchange`:
+
+ * `#doRoute` - implements exchange routing functionality
+ * `#onBind` - implements exchange specific binding functionality
+ * `#onUnbind` - implements exchange specific unbinding functionality
+ * `#onBindingUpdated` - implements exchange specific functionality for
updating existing bindings
+
+The `AbstractExchange` implements category interface `Exchange` which in turn
extends a more generic interface
+`MessageDestination`.
+
+## Queues
+
+`Queue` model objects provide the messaging queues. There are several
specialisations of `Queue`
+
+ * `StandardQueue` which provides a FIFO behaviour
+ * `PriorityQueue` which provides queuing ordered by a message's priority
+ * `LVQQueue` which provides a last-value or conflation queue.
+ * `SortedQueue` which sorts message based on message sorting key value using
red-black tree algorithm.
+
+Internally queues are implemented as a linked list (`QueueEntryList`) of nodes
(`QueueEntry`).
+The linked list is implemented from first principals. It uses a thread safe
and lock-less algorithm
+(it uses compare and swap operations).
+
+### Enqueueing
+
+When a message is enqueued (using the `AbstractQueue#enqueue()` method) it
adds the message to the tail
+of the queue and notifies a subscriber (consumer) about the new message. The
connection that owns the consumer is
+then awoken and events proceed as described above in the [Producing
Bytes](#producing-bytes).
+This is described by
[Consumer-Queue-Interactions](consumer-queue-interactions.md)
+
+### Subscriptions
+
+Each subscription keeps a "pointer" (`QueueContext#_lastSeenEntry`) into the
list denoting the point at which
+that particular subscription has reached. A subscription will only take a
message if it is the next `AVAILABLE`
+(`MessageInstance.State.AVAILABLE`) entry.
+
+The diagram below shows point to point queue with three subscribers attached.
+
+
+
+### Messages
+
+Each queue node `QueueEntry` refers to a `ServerMessage`. The server message
encapsulates:
+
+ * Message meta-data (loosely the message's headers)
+ * Message payload
+ * Original routing information,
+
+Many `QueueEntries` may refer to the same `ServerMessage`. In the case where a
incoming message is routed through
+an exchange to many queues, the `QueueEntry` point to the same
`ServerMessage`. This means only one copy of
+the message exists in the `Broker`, regardless of however many queues refer to
it. This is important for topics
+where the same message may be sent to hundreds of subscribers.
+
+`ServerMessage` uses a `Reference` counting system to control its lifecycle.
When the reference reaches zero,
+it knows no one references it and it can safely delete itself.
+
+The `ServerMessage` refers to `StoredMessage`. The `StoredMessage` backs the
underlying message storage.
+It provides methods that get the content and the metadata. This might return
cached copies,
+or it might cause store operations to fetch the data from the disk.
+
+`StoredMessage` can be flowed to disk. The `Broker` (`FlowToDiskCheckingTask`)
responds to memory pressure
+by flowing messages that are in-memory only (i.e. transient messages) to disk
and freeing the cached copies
+of persistent messages from memory. This approach frees up memory for messages.
+
+### Message and Configuration Store
+
+Messages are written to the `MessageStore` and configuration to the
`DurableConfigurationStore`.
+It is possible to back these with the same underlying provider or use a
different provider for configuration and messages.
+
+There are several store provider implementations:
+
+ * JSON - Configuration Store only
+ * Berkeley BDB JE - Durable Configuration and/or Message Store
+ * Derby - Durable Configuration and/or Message Store
+ * JDBC - Durable Configuration and/or Message Store
+
+These interfaces are pluggable.
+
+## Messaging Transactions
+
+Multiple messages can be consumed or/and published as a single atomic
operation within messaging transaction.
+The transaction is usually initiated and discharged (committed or rolled back)
on client side, but, `Broker`
+can also use messaging transactions for performing operations on group of
messages in atomic way, for example,
+moving/copying messages between queues, deleting messages from queue using
management interfaces, etc.
+
+An interface `ServerTransaction` represents messaging transaction on broker
side. The following operations
+can be invoked as part of messaging transactions:
+
+ * `dequeue` - dequeue message or collection of messages
+ * `enqueue` - enqueue message into a `TransactionLogResource` or collection
of `BaseQueue`
+ * `commit` - commit transaction
+ * `rollback` - rollback transaction
+ * `addPostTransactionAction` - an auxiliary operation to add some
post-transactional work, which is executed after
+ transaction is discharged
+
+`LocalTransaction` is a concrete implementation of `ServerTransaction` which
is responsible for performing messaging
+transaction. It delegates transactional operations to `Transaction` object
provided by `MesssageStore`. Each message
+store type has its own implementation of `Transaction`.
+
+The class diagram below illustrates the transactional model of Qpid Broker-J.
+
+
+
+As per diagram, apart from `LocalTransaction`, there are three other
implementations of `ServerTransaction`.
+
+ * `DistributedTransaction` is used to run distributed transaction (for AMQP
protocol 0-10)
+ * `AutoCommitTransaction` is used to model auto-commit transaction
functionality
+ * `AsyncAutoCommitTransaction` is used to model auto-commit transaction
functionality
+ with asynchronous discharge (i.e., the caller does not wait for finish of
transaction discharge and proceed
+ with invocation of next operations, but, the transaction eventually get
discharged).
+
+`AsyncAutoCommitTransaction` is used to invoke enqueueing and dequeueing
operations when `client`
+ does not need transaction but broker implementation semantic requires passing
`ServerTransaction` object.
+
+`AutoCommitTransaction` is used to run a number of messaging operations
requiring atomicity, for example,
+`clearQueue`, `publishMessage` from management interface, etc.
+
+## Management
+
+The Broker exposes two management layers:
+
+ * AMQP management
+ * HTTP management
+
+The management layers essentially expose the Broker model over the management
interface.
+
+### AMQP management
+
+AMQP management is defined by the AMQP Management specification which is
currently a Working Draft at Oasis.
+It defines a standard way to identify objects within the `Broker`, to invoke
operations
+(CRUD operations or arbitrary operations such as `clearQueue`) and pass
arguments and get results, all over AMQP itself.
+When interacting with management, you send management messages to a special
node (`$management`)
+which support a reply-to address.
+
+It also defines a standard way to discover the objects that an device managed
by AMQP exposes.
+One idea here is that is should be possible to produce a generic console which
is capable of managing
+(at least at a basic level) any device managed by AMQP.
+
+For Broker-J:
+
+ * To manage a virtualhost, you connect with AMQP to the virtualhost as
normal, then send management messages to `$management`.
+ * To manage the Broker as a whole, you connect with AMQP to a synthetic
virtualhost `$management`
+ and then send management messages to `$management`.
+
+`ManagementNode` provides the implementation.
+
+The model (objects, attributes, operations) are simply exposed verbatim over
AMQP Management.
+In AMQP management, objects have a name identifying the type of the object.
This is defined using an annotation
+`ManagedObject#amqpName`.
+
+### HTTP management
+
+The Broker's model is exposed as a REST API. This allows simple tools such as
cURL to be an effective way
+to both manage and monitor the `Broker`.
+
+The URI for the REST API is `/api/latest` or `/api/v<version>`. Currently, the
`Broker` supports a current
+version of the API and couple of preceding versions. Though, the support for
more older versions can be added,
+if there will be a need for it. It is envisages that future version of
management layer will maintain a support
+for at least one previous version, thus allowing a smooth upgrade for those
migrating to new Broker versions.
+
+The URI is mapped to the object's within the tree. The form of the URI is
+
+ /api/latest/<category type>/<name1>/<name2>/.../<namen>
+
+where the names describe a path to an object starting at the root. It is
always possible to refer to objects by ids.
+
+ * POST/PUT - create or update
+ * DELETE - delete an object
+ * GET - get an object or a collection of objects.
+
+The `Broker` embeds `Jetty` to provide the HTTP management interface.
`HttpManagment` configures `Jetty` according
+to the configuration provided to by the `Port/KeyStore/TrustStore` model
objects.
+
+The embedded server also provides a Web Management Console. This is written
using the Dojo framework.
+It uses the REST API to interact with the `Broker`.
+
+## Pluggable Architecture
+
+The Broker utilizes java `java.util.ServiceLoader` for implementation of
pluggable architecture.
+The `org.apache.qpid.server.plugin.QpidServiceLoader` is a thin wrapper around
`java.util.ServiceLoader`. It is
+responsible for loading of services extending
`org.apache.qpid.server.plugin.Pluggable`. All Broker extension
+interfaces extend `org.apache.qpid.server.plugin.Pluggable`. The diagram below
illustrates some of the extension points.
+
+
+
+The Broker allows alternative implementations for various entities. For
example, a custom implementation of
+`AcceptingTransport` can be plugged into the Broker by adding into a broker
classpath an implementation of
+`TransportProviderFactory` responsible for instantiation of the custom
`AcceptingTransport`.
+
+A new type of `ConfiguredObject` can be plugged into the Broker by
implementing `ConfiguredObjectTypeFactory`
+responsible for creation and recovery of this `ConfiguredObject` type.
+
+The `ConfiguredObjectTypeFactory` are auto-generated for majority of
`ConfiguredObject` types. An abstract factory
+`AbstractConfiguredObjectTypeFactory` is used as a stub for auto-generated
factory classes. An annotation
+`@ManagedObjectFactoryConstructor` needs to be declared on a constructor of
`ConfiguredObject` implementation
+in order to have factory auto-generated by `ConfiguredObjectFactoryGenerator`
from `qpid-broker-codegen` module.
+
+Another useful annotation is `@PluggableService`. It is used for
auto-generation of services files
+under `META-INF/services/`.
+
+All implementations of `ConfiguredObjectTypeFactory` are aggregated in
implementation of `ConfiguredObjectFactory`.
+The latter delegates `ConfiguredObject` creation and recovery to required
implementation of
+`ConfiguredObjectTypeFactory`. The right `ConfiguredObjectTypeFactory` is
selected based on value of `type` attribute.
+
+Some of configured object categories have specialized implementations of
`ConfiguredObjectTypeFactory` which are
+responsible for determining right `ConfiguredObjectTypeFactory` based on
values of different attributes. For example,
+factories `PortFactory` and `QueueFactory` are used for creation/opening of
`Port` and `Queue` accordingly.
+`PortFactory` examines attribute `protocols` to identify the `Port` type,
whilst `QueueFactory` checks existence
+of attributes like `priority`, `sortKey` and `lvqKey` when attribute `type` is
not specified in order to determine
+the type of the Queue.
+
+A new type of `SystemConfig` can be plugged-in with `SystemConfigFactory`.
+
+Please, check Broker code for all extension points by building type hierarchy
for `Pluggable`.
+
+## Logging
+
+Qpid Broker-J uses **slf4j** API for logging. The **slf4j** abstraction allows
to plug-in any logging framework.
+The **logback** logging framework is used by the Broker. Though, only handful
of modules (`qpid-broker` containing
+code for starting the broker and logging-logback plugins implementing
management functionality) have compile time
+dependency to **logback**. The rest of Broker modules including
`qpid-broker-core` and plugins modules
+(except for logging-logback plugins) depend only on **slf4j** API. The Broker
can be easily started without logback
+dependent modules. Any other logging framework can be used with the Broker if
required.
+
+The Broker defines a number of `ConfiguredObject` categories to be able to
dynamically configure logging settings
+at runtime and access generated logs from Broker management API.
+
+ * *Logger* is responsible for production of logs
+ * *InclusionRule* governs what appears within the logs. Loggers can include
any number of InclusionRules for log collection.
+
+In order to isolate applications running on dedicated VirtualHosts from each
other, the Broker provides separate
+`VirtualHost` logging API. If configured, the users of specific `VirtualHost`
can access their logs without seeing
+logs not related to their `VirtualHost` (including logs from other
applications on different VirtualHosts
+and Broker own logs).
+
+Thus, there are two sub-sets of logging API: Broker Logger Model and
VirtualHost Logger Model.
+
+The class diagram below illustrates Broker Logger Model.
+
+
+
+The class diagram below illustrates VirtualHost Logger Model.
+
+
+
+Both `Broker` and `VirtualHost` support
+ * *FileLogger* which is responsible for storing logs in files on file system
+ * *SysLogLogger* is responsible for storing logs in SysLogs of Linux/Unix OS
+ * *JDBCLogger* is responsible for storing logs in RDBMS
+
+In addition to Loggers listed above, the Broker supports the following Loggers:
+ * *MemoryLogger* is responsible for accumulation of predefined number of log
records in cyclic memory buffer
+ * *ConsoleLogger* is responsible for redirection of the logs into system
standard output
+ * *BrokerLogbackSocketLogger* is responsible for sending logs into *socket*
(used in integration tests)
+
+Both `Broker` and `VirtualHost` support the following inclusion rules
+ * *NameAndLevel* is responsible for accepting log events that match a given
log event source name and have a level
+ that equals or exceeds the specified value
+ * *UserOrConnection* is responsible for accepting the log events matching
given regular expressions for principal name,
+ container id and remote connection address
+
+All existing logback-based Logger implementations (for both `Broker` and
`VirtualHost`) extend `AbstractLogger`.
diff --git a/doc/developer-guide/src/main/markdown/build-instructions.md
b/doc/developer-guide/src/main/markdown/build-instructions.md
new file mode 100644
index 0000000..1ea6027
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/build-instructions.md
@@ -0,0 +1,310 @@
+# Build Instructions
+
+[Quick Start Guide](quick-start.md) only gives a minimum set of instructions
to start quickly building and developing
+Qpid Broker-J code. The materials provided here intend to give a deeper
understanding of various options for building,
+and testing Qpid Broker-J.
+
+<!-- toc -->
+
+- [Prerequisites](#prerequisites)
+ * [Sources](#sources)
+ * [Maven](#maven)
+ * [Java](#java)
+- [Project structure](#project-structure)
+- [Building](#building)
+ * [Maven Commands](#maven-commands)
+ * [Maven Profiles](#maven-profiles)
+ * [Maven Build Output](#maven-build-output)
+ * [Distribution bundles](#distribution-bundles)
+- [Running tests](#running-tests)
+ * [Joram JMS Testsuite](#joram-jms-testsuite)
+ * [JMS TCK](#jms-tck)
+ * [Performance Tests](#performance-tests)
+ * [Python Tests](#python-tests)
+
+<!-- tocstop -->
+
+## Prerequisites
+
+### Sources
+
+The Qpid project employs [Git distributed version-control
system](https://git-scm.com) for tracking changes in source code.
+
+The Git repository can be found at
<https://gitbox.apache.org/repos/asf/qpid-broker-j.git>.
+
+The mirror of Git repository exists on GitHub at
<https://github.com/apache/qpid-broker-j>.
+
+Changes need to be committed into Apache Git repository. They immediately get
propagated into GitHub mirror.
+Only members of Qpid project with commit rights can commit the changes. The
contributors without commit rights need
+to raise [Pull
Request](https://help.github.com/en/articles/creating-a-pull-request) on GitHub
in order to have
+their changes be committed by Qpid project committers.
+
+Git client is required to checkout sources from Git repo
+
+ git clone https://gitbox.apache.org/repos/asf/qpid-broker-j.git
qpid-broker-j
+
+For complete reference and documentation on Git please check [Git
Book](https://git-scm.com/book/en/v2)
+
+### Maven
+
+Qpid Broker-J project uses [Maven](http://maven.apache.org/) as its build and
management tool. Maven version 3 or above
+is required for building the project.
+
+You should set the `M2_HOME` environment variable and include its `bin`
directory in your `PATH`.
+
+Check that maven is installed on your system by executing the following at
your command prompt.
+
+ mvn --version
+
+For full maven install instructions visit [Maven Installation
Instructions](http://maven.apache.org/download.cgi#Installation).
+
+For complete reference and documentation on Maven please visit the following
online resources.
+
+* [Apache Maven Project](http://maven.apache.org/)
+* [Maven: The Complete Reference by
Sonatype](http://books.sonatype.com/mvnref-book/reference/public-book.html)
+
+
+### Java
+
+The build requires a Java 8 or later. You should set the `JAVA_HOME`
environment variable and include its `bin` directory
+in your `PATH`.
+
+Check java version by executing the following at your command prompt.
+
+ java -version
+
+## Project structure
+
+Qpid Broker-J consists of a number of modules and sub-modules located in their
own directories. Each Qpid Broker-J module
+has its own POM file (pom.xml) located in its root directory. This file
defines the modules version, dependencies and
+project inheritance as well as the configuration of the relative maven plugins
specific to this module.
+The Qpid Broker-J parent pom.xml is located in the root of the project and
declares all qpid modules, dependencies,
+plugins, etc.
+
+## Building
+
+The project is built by executing maven command in conjunction with
pre-defined profiles. For example, the command below
+cleans previous build output and install all modules to local repository
without running the tests:
+
+ mvn clean install -DskipTests
+
+The following command installs all modules to the local repository after
running all the tests:
+
+ mvn clean install
+
+### Maven Commands
+
+Here is a quick reference guide outlining some of the maven commands you can
run and what the outcome will be.
+
+Please visit [Introduction To The Maven
Lifecycle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)
+reference guide for full details on all the maven lifecycle phases.
+
+| Command | Description | Notes
|
+|---------------|:-----------------------------------------------------|:---------------------------------------|
+| mvn clean | removes all the files created by the previous build
|Usually means it deletes the contents of the modules `*/target/` directory.|
+| mvn validate | validates that the maven poms are all correct and that no
config is missing | Useful to run when making build modifications to ensure
consistency.|
+| mvn compile | compiles the source code of the project | This will verify
that project dependencies are correct.|
+| mvn test | executes the unit tests | Should not rely on code being
packaged or deployed, only unit tests.|
+| mvn package | packages the code into the its distributable formats (jar,
zip etc)| Each pom specifies what the distribution format is, default is POM.|
+| mvn verify | verifies that the packaged code is valid| This will run the
integration and system tests.|
+| mvn install | installs the package into the local maven repository | This
will result in the module being available, locally, as a depedency|
+| mvn deploy | copies the final artifacts to the remote maven repository
for sharing | This would happen only when modules ready to be shared with other
developers or projects|
+| mvn site:stage| creates a staged version of the maven site with all the
reports | Staging output defaults to the `*/target/staging/` directory |
+| mvn jacoco:report | generates the code coverage report for the tests that
have been executed | Test output appears in the `*/target/site/jacoco/`
directory |
+
+### Maven Profiles
+
+Maven profiles are used to run tests for the supported protocols and storage
options.
+The specific profile can be enabled at the command line using option `-P`.
+If no profile is selected, `java-mms.1-0` is run by default.
+
+An example below executes integration tests using profile `java-bdb.1-0`.
+
+ mvn verify -Pjava-bdb.1-0
+
+Please visit [Introduction To Maven
Profiles](http://maven.apache.org/guides/introduction/introduction-to-profiles.html)
+for full details on the use of profiles in a maven build.
+
+Profiles can be listed using command
+
+ mvn help:all-profiles
+
+The test profile names follow the form *java-store.n-n*, where
+ *store* signifies the storage module and
+ *n-n* the AMQP protocol version number.
+
+For store, the options include:
+
+* *bdb* - Oracle BDB JE
+* *dby* - Apache Derby
+* *mms* - an in-memory store principally used for testing.
+
+For protocols, the options include:
+
+* *1-0* - AMQP 1-0
+* *0-10* - AMQP 0-10
+* *0-9-1* - AMQP 0-9-1
+* *0-9* - AMQP 0-9
+
+To activate profile for BDB and AMQP 1.0 protocol use:
+
+ mvn verify -Pjava-bdb.1-0
+
+When activating AMQP 0-8..0-10 profiles, it is also necessary to pass the
system property *-DenableAmqp0-x*.
+For example,
+
+ mvn verify -Pjava-dby.0-9 -DenableAmqp0-x
+
+The table below lists some of profiles defined in parent pom.xml.
+
+|Profile Name | Description |
+|----------------|--------------------------------------------------------|
+|apache-release | Release profile for performing Apache software releases|
+|dependency-check|Dependency check to validate project licensing ahead of
release|
+|java-mms.1-0 | Test profile to run integration tests using AMQP protocol
1.0 against broker with memory message store|
+|java-bdb.1-0 | Test profile to run integration tests using AMQP protocol
1.0 against broker with bdb message store|
+|java-dby.1-0 | Test profile to run integration tests using AMQP protocol
1.0 against broker with Derby message store|
+|java-mms.0-10 | Test profile to run integration tests using AMQP protocol
0-10 against broker with memory message store|
+|java-bdb.0-10 | Test profile to run integration tests using AMQP protocol
0-10 against broker with bdb message store|
+|java-dby.0-10 | Test profile to run integration tests using AMQP protocol
0-10 against broker with Derby message store|
+|java-mms.0-9-1 | Test profile to run integration tests using AMQP protocol
0-9-1 against broker with memory message store|
+|java-bdb.0-9-1 | Test profile to run integration tests using AMQP protocol
0-9-1 against broker with bdb message store|
+|java-dby.0-9-1 | Test profile to run integration tests using AMQP protocol
0-9-1 against broker with Derby message store|
+
+There is a set of test profiles to run tests against broker with in-memory
Derby store, for example
+
+ mvn verify -Pjava-dby-mem.0-10 -DenableAmqp0-x -DskipITs=false
+
+### Maven Build Output
+
+By default the build output for a maven module will appear in the modules
`target` directory:
+For example, the broker core module output appears in:
+
+ broker-core/target
+
+Depending on the goals specified in the last build, one or all of the
following can be found in the `target` directory.
+
+| Location | Description | Note |
+|----------|-------------|------|
+| */target/|Packaged build artifacts|JAR, WAR, ZIP, etc as well as any release
specific artifacts specified in assembly files i.e. release tars|
+| */target/surefire-reports/<profile name>|Logs from unit/system test and
Surefile summary|Logs files generated by the tests (named
TEST-<test-class>-<test-method>.txt). Surefire summary has an .xml extension.|
+| */taget/site/| Maven site output|Maven reports generated in HTML format i.e.
test reports, code coverage etc|
+| */target/staging/|The staged maven site|Local attempt to generate the full
maven site|
+
+
+### Distribution bundles
+
+The broker distribution assemblies can be found beneath:
+
+ apache-qpid-broker-j/target
+
+How to run Qpid broker is covered in [Quick Start Guide](quick-start.md)
+
+## Running tests
+
+Integration tests except for protocol tests are disabled by default.
+In order to run all integration tests, they need to be enabled with a flag
`-DskipITs=false`, for example
+
+ mvn verify -DskipITs=false
+
+Running all integration tests using BDB and AMQP 1.0 protocol:
+
+ mvn verify -Pjava-bdb.1-0 -DskipITs=false
+
+Perform a subset of tests on the packaged release artifacts without installing:
+
+ mvn verify -Dtest=TestNamePattern* -DfailIfNoTests=false
+
+Execute the tests and produce code coverage report:
+
+ mvn clean test jacoco:report
+
+### Joram JMS Testsuite
+
+The Joram JMS Testsuite is integrated into the Maven build but is disabled by
default.
+It allows the Joram JMS test suite to be executed using the specified Qpid JMS
client against Qpid Broker-J.
+The Broker must be running already.
+
+The following clients are supported:
+
+* *qpid-jms-client* - Qpid JMS Client for AMQP 1.0
+* *qpid-amqp-1-0-client-jms* - the proof of concept Qpid Client AMQP 1.0
(development ceased after 0.32)
+* *jms-client* - Legacy Qpid JMS Client for AMQP 0-x
+
+To use the test suite, first configure the Qpid Broker-J to permit HTTP
basic-authentication, then run the following command:
+
+ mvn -f joramtests/pom.xml integration-test -Djoramtests=<jms client
identifier>
+
+where `<jms client identifier>` is one of: `qpid-jms-client`,
`qpid-amqp-1-0-client-jms`, `jms-client-0-9`, `jms-client-0-10`.
+
+The Maven failsafe plugin will run the tests. Unit output is produced into
`joram-tests/target/failsafe-reports`
+ and the log from the client is written to `joramtests/target/joramtest.log`.
+
+To run a particular test use the failsafe plugin property `-Dit.test`:
+
+ mvn -f joramtests/pom.xml integration-test
-Djoramtests=qpid-amqp-1-0-client-jms -Dit.test=ConnectionTest
+
+### JMS TCK
+
+The configuration for the JMS TCK is integrated into the Maven build but the
profile is disabled by default.
+The JMS TCK itself is proprietary and must be provided by the user.
+The Broker must be running and HTTP management available. The test suite will
automatically set-up/teardown
+ the JMS objects required by the TCK.
+
+ * *qpid-jms-client* - Qpid JMS Client for AMQP 1.0
+ * *jms-client* - Legacy Qpid JMS Client for AMQP 0-x
+
+To use the test suite, first unpack the JMS TCK into a directory, then invoke
tests in the following way:
+
+ mvn post-integration-test -Dtck=qpid-jms-client -f tck/pom.xml
-Dtck.directory=/path/to/jmstck/
+
+To run an individual test, use the `tck.test` system property.
+
+ mvn post-integration-test -Dtck=qpid-jms-client -f tck/pom.xml
-Dtck.directory=/path/to/jmstck/
-Dtck.test=com/sun/ts/tests/jms/ee/all/sessiontests/SessionTests.java
+
+JMS 2.0 TCK can be run against Qpid Broker-J only with `qpid-jms-client` (for
AMQP 1.0) by specifying profile `jms20-tck`
+and location of directory containing expanded TCK. For example,
+
+ mvn post-integration-test -f tck/pom.xml -Pjms20-tck
-Dtck.directory=/home/alex/tck/jmstck20 -Dqpid-jms-client-version=0.45.0
+
+### Performance Tests
+
+The Performance test suite is integrated into Maven.
+It is bound to the `integration-test` phase and it is activated by the
`perftest` system property.
+The Broker must be running and HTTP management available. The test suite will
automatically set-up/teardown
+the JMS objects required for the performance tests.
+
+The following clients are supported:
+
+ * *qpid-jms-client* - Qpid JMS Client for AMQP 1.0
+ * *jms-client* - Legacy Qpid JMS Client for AMQP 0-x
+
+To invoke:
+
+ mvn -f perftests/pom.xml integration-test -Dperftests=jms-client-0-9
+
+Most things can be overridden from system properties. Take a look in the first
few lines of the POM.
+
+### Python Tests
+
+The Python Test suite runs against the Qpid Broker-J too but is not currently
integrated into Maven.
+To run the 0-8..0-10 test suites use the following steps. It assumes that
qpid-python and qpid-cpp are checked out.
+
+Configure the Qpid Broker-J to allow so that the authentication provider
permits plain connections.
+
+ curl --user admin:admin -d '{"secureOnlyMechanisms": []}'
http://localhost:8080/api/latest/authenticationprovider/passwordFile
+
+Install the Python packages to a suitable location.
+
+ LOCALROOT=~/myroot
+ (cd qpid-cpp/management/python && python setup.py install --root
${LOCALROOT})
+ (cd qpid-python && python setup.py install --root ${LOCALROOT})
+ export PYTHONPATH=${LOCALROOT}/lib/python2.7/site-packages
+
+Run the tests will the following command:
+
+ QPID_HOME=/path/to/my/qpid-broker-j
+ cd qpid-python
+ ./qpid-python-test -b amqp://guest/guest@localhost:5672
-I${QPID_HOME}/test-profiles/python_tests/Java010PythonExcludes
-I${QPID_HOME}/test-profiles/python_tests/JavaPre010PythonExcludes -m
qpid_tests.broker_0_10 -m qpid_tests.broker_0_9 -m qpid_tests.broker_0_8 -m
qmf.console [<fully qualified test name>]
+
+
diff --git a/doc/developer-guide/src/main/markdown/code-guide.md
b/doc/developer-guide/src/main/markdown/code-guide.md
new file mode 100644
index 0000000..1360f81
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/code-guide.md
@@ -0,0 +1,466 @@
+# Qpid Broker-J Coding Standards
+
+This article documents the standard adopted for Java code in the Qpid project.
+All committers are expected to follow this standard.
+
+<!-- toc -->
+
+- [Executive Summary](#executive-summary)
+- [Details](#details)
+ * [Introduction](#introduction)
+ * [Source files](#source-files)
+ * [Java Elements](#java-elements)
+ + [Class definitions](#class-definitions)
+ + [Variables](#variables)
+ + [Methods](#methods)
+ * [Expressions](#expressions)
+ * [Statements](#statements)
+ + [Simple Statements](#simple-statements)
+ + [Compound Statements](#compound-statements)
+ * [General](#general)
+ * [Exceptions](#exceptions)
+
+<!-- tocstop -->
+
+## Executive Summary
+
+The main things for layout purposes in the standard are:
+
+ * Indent using four spaces. No tabs.
+ * braces always go on new lines, e.g.
+```java
+if (x == 5)
+{
+ System.out.println("Hello");
+}
+```
+
+rather than
+
+```java
+if (x == 5} {
+ System.out.println("Hello");
+}
+```
+
+Always add braces, e.g.
+
+```java
+ if (x == 5)
+ {
+ System.out.println("Hello");
+ }
+```
+rather than
+
+```java
+if (x == 5}
+ System.out.println("Hello");
+```
+
+Fields prefixed with underscores, e.g. `_messageCount`
+
+Spaces after keywords but no spaces either before or after parentheses in
method calls, e.g.
+
+```java
+ if (x == 5)
+```
+
+rather than
+
+```java
+ if(x==5)
+```
+
+but
+
+```java
+ foo.bar(4, 5)
+```
+
+rather than
+
+```java
+ foo.bar( 4, 5 )
+```
+
+## Details
+
+### Introduction
+
+This document describes two types of coding standard:
+
+1. **Mandatory** standards must be followed at all times.
+2. **Recommended** standards should in general be followed but in particular
cases may be omitted
+ where the programmer feels that there is a good reason to do so.
+
+Code that does not adhere to mandatory standards will not pass the automated
checks
+(or a code review if the guideline is not stylistic).
+
+### Source files
+
+This section defines the general rules associated with the contents of a Java
source file and the order
+in which the each part should be presented. No rules on programming style,
naming conventions or indentation are given here.
+
+1. Java source files must have a ".java" suffix (this will be enforced by the
compiler) [mandatory].
+2. The basename of a Java source file must be the same as the public class
defined therein
+ (this will be enforced by the compiler) [mandatory].
+3. Only one class should be defined per source file (except for inner classes
and one-shot uses
+ where the non-public class cannot conceivably be used outside of its
context) [mandatory].
+4. Source files should not exceed 1500 lines [recommended].
+5. No line in a source file should exceed 120 characters [mandatory].
+6. The sections of a source file should be presented in the following order
[mandatory]:
+ * File information comment (see rule 7 below).
+ * Package name (see rule 8 below).
+ * Imports (see rules 9 to 10 below).
+ * Other class definitions.
+ * Public class definition.
+7. Do not use automatically expanded log or revision number provided by your
source code management system
+ unless it provides a facility to avoid "false conflicts" when doing merges
due simply to revision number changes
+ (which happens, for example, with cvs when branches are used). [mandatory]
+8. Every class that is to be released must be a member of a package
[mandatory].
+ Rationale: classes that are not explicitly put in a package are placed in
the unnamed package by the compiler.
+ Therefore as the classes from many developers will be being placed in the
same package the likelihood of a name
+ clash is greatly increased.
+9. All class imports from the same package should be grouped together. A
single blank line should separate imports
+ from different packages [recommended].
+10. Wildcard imports should be avoided as they could lead to conflicts between
classes in different packages
+ with the same name. [recommended].
+11. Use javadoc tags and use HTML mark-up to enhance the readability of the
output files [mandatory].
+
+### Java Elements
+
+This section gives advice on coding the various elements of the Java
programming language.
+
+#### Class definitions
+
+This section gives guidelines for class and interface definitions in Java.
+The term class in this section is used more broadly to mean class and
interface:
+
+1. Class names should start with a capital letter with every subsequent word
capitalised,
+ for example: `DataProcessor` [mandatory].
+2. All classes should be preceded by a javadoc comment describing the purpose
of the class [recommended].
+3. Class-level javadoc comments should specify the thread-safety of the class
[recommended].
+4. The name of exception classes should end in the word exception, for
example: UnknownMungeException [mandatory].
+5. Class names should in general not be overloaded. For example, defining a
class "com.foo.bar.String"
+ should be avoided as there is already a class "java.lang.String"
[recommended].
+ Rationale: adhering to this rule reduces the likelihood of confusion and
means that the use of fully qualified
+ class names should not be required.
+6. The definition of the primary class (i.e. the class with the same name as
the java file) should start in column 0
+ of the source file. Inner class definitions should be indented 4 spaces
more than their enclosing class [mandatory].
+7. Declare a class as final only if specialisation will never be required and
improved performance is essential.
+ With modern JVMs there in fact may be no performance advantage. Warning:
use of final limits code reuse [mandatory].
+8. For all but simplest classes the following methods should have useful
definitions [recommended]:
+ ```java
+ public boolean equals(Object obj)
+ public int hashCode()
+ public String toString()
+ ```
+9. The order of presentation of the sections in a class should be [mandatory]:
+ * Variables
+ * Methods
+
+#### Variables
+This section gives guidelines for class and instance variable definitions in
Java.
+In this section if a rule uses the term variable rather than instance variable
or class variable,
+then the rule applies to both types of variable.
+
+1. The order of presentation of variables in a class definition should be
[recommended]:
+ * private, protected, public: static final variables (aka constant class
variables).
+ * private, protected, public: static variables (aka class variables).
+ * private, protected, public: final variables (aka constant instance
variables).
+ * private, protected, public: variables (aka instance variables).
+ It should be noted that as javadoc will automatically order variables in a
consistent manner,
+ rigid adherence to this rule is not necessary.
+2. Variable modifiers should be presented in the following order: static,
final, transient, volatile [mandatory].
+3. The names of static final variables should be upper case with subsequent
words prefixed with an underscore [mandatory].
+ For example:
+ ```java
+ public static final int NOT_FOUND = -1;
+ ```
+4. When a subclass refers to a static final variable defined in a parent
class, access should be qualified
+ by specifying the defining class name [mandatory].
+ For example: use `ParentClass.MAX` rather than `MAX`.
+5. The names of variables (other that static final) should start with a lower
case letter.
+ Any words that are contained in the rest of the variable name should be
capitalised [mandatory].
+ For example:
+ ```java
+ String name;
+ String[] childrensNames;
+ ```
+6. Class and instance variables must be prefixed with an underscore (_)
[mandatory].
+7. Variables must not be named using the so-called Hungarian notation
[mandatory].
+ For example:
+ ```java
+ int nCount = 4; // not allowed
+ ```
+8. Only one variable may be defined per line [mandatory].
+9. Variable declarations should be indented 4 spaces more than their enclosing
class [mandatory].
+10. Class instance variables might be preceded by a javadoc comment that
specifies what the variable is for,
+ where it is used and so forth. Though, the self-explanatory variable name
should be preferred over comments.
+ If comment is necessary, it should be indented to the same level as the
variable it refers to [recommended]
+11. Never declare instance variables as public unless the class is effectively
a "struct" [mandatory].
+12. Never give a variable the same name as a variable in a superclass
[mandatory].
+13. Ensure that all non-private class variables have sensible values even if
no instances have been created
+ (use static initialisers if necessary, i.e.`static { ... }`) [mandatory].
+ Rationale: prevents other objects accessing fields with
undefined/unexpected values.
+
+#### Methods
+This section gives guidelines for class and instance method definitions in
Java.
+In this section if a rule uses the term method rather than instance method or
class method,
+then the rule applies to both types of method.
+
+1. Constructors and `finalize` methods should follow immediately after the
variable declarations [mandatory].
+2. Do not call non-final methods from constructors. This can lead to
unexpected results when the class is subclassed.
+ If you must call non-final methods from constructors, document this in the
constructor's javadoc [mandatory].
+ Note that private implies final.
+3. Methods that are associated with the same area of functionality should be
physically close to one another [recommended].
+4. After grouping by functionality, methods should be presented in the
following order [recommended]:
+ * private, protected, public: static methods.
+ * private, protected, public: instance methods.
+ It should be noted that as javadoc will automatically order methods in a
consistent manner,
+ rigid adherence to this rule is not necessary.
+5. Method modifiers should be presented in the following order: abstract,
static, final, synchronized [mandatory]
+6. When a synchronized method is overloaded, it should be explicitly
synchronized in the subclass [recommended].
+7. Method names should start with a lower case letter with all subsequent
words being capitalised [mandatory].
+ For example:
+ ```java
+ protected int resize(int newSize)
+ protected void addContentsTo(Container destinationContainer)
+ ```
+8. Methods which get and set values should be named as follows [mandatory]:
+ ```java
+ Type getVariableName()
+ void setVariableName(Type newValue)
+ ```
+ Exceptions should be used to report any failure to get or set a value.
+ The `@param` description should detail any assumptions made by the
implementation,
+ for example: "Specifying a null value will cause an error to be reported".
+9. Method definitions should be indented 4 spaces more than their enclosing
class [mandatory].
+10. All non-private methods should be preceded by a javadoc comment specifying
what the method is for,
+ detailing all arguments, returns and possible exceptions [mandatory]
+11. The braces associated with a method should be on a line on their own and
be indented to the same level
+ as the method [mandatory]. For example:
+ ```java
+ public void munge()
+ {
+ int i;
+ // method definition omitted...
+ }
+ ```
+12. The body of a method should be indented 4 columns further that the opening
and closing braces associated with it [mandatory].
+ See the above rule for an example.
+13. When declaring and calling methods there should be no white space before
or after the parenthesis [mandatory].
+14. In argument lists there should be no white space before a comma, and only
a single space (or newline) after it [mandatory].
+ For example:
+ ```java
+ public void munge(int depth, String name)
+ {
+ if (depth > 0)
+ {
+ munge(depth - 1, name);
+ }
+ // do something
+ }
+ ```
+15. Wherever reasonable define a default constructor (i.e. one that takes no
arguments)
+ so that `Class.newInstance()` may be used [recommended]. If an instance
which was created by default construction
+ could be used until further initialisation has been performed, then all
unserviceable requests should cause
+ a runtime exception to be thrown.
+16. The method public static void main() should not be used for test purposes.
+ Instead a test/demo program should be supplied separately. [mandatory].
+17. Public access methods (i.e. methods that get and set attributes) should
only be supplied when required [mandatory].
+18. If an instance method has no natural return value, declare it as void
rather than using the "return this;"
+ convention [mandatory].
+19. Ensure that non-private static methods behave sensibly if no instances of
the defining class have been created [mandatory].
+
+### Expressions
+This section defines the rules to be used for Java expressions:
+
+1. Unary operators should not be separated from their operand by white space
[mandatory].
+2. Embedded `++` or `--` operators should only be used when it improves code
clarity [recommended]. This is rare.
+3. Extra parenthesis should be used in expressions to improve their clarity
[recommended].
+4. The logical expression operand of the `?:` (ternary) operator must be
enclosed in parenthesis.
+ If the other operands are also expressions then they should also be
enclosed in parenthesis [mandatory]. For example:
+ ```java
+ biggest = (a > b) ? a : b;
+ complex = (a + b > 100) ? (100 * c) : (10 * d);
+ ```
+5. Nested `?:` (ternary) operators can be confusing and should be avoided
[mandatory].
+6. Use of the binary "," operator (the comma operator) should be avoided
[mandatory].
+ Putting all the work of a for loop on a single line is not a sign of great
wisdom and talent.
+7. If an expression is too long for a line (i.e. extends beyond column 119)
then it should be split after the lowest
+ precedence operator near the break [mandatory]. For example:
+ ```java
+ if ((state == NEED_TO_REPLY) ||
+ (state == REPLY_ACK_TIMEOUT))
+ {
+ // (re)send the reply and enter state WAITING_FOR_REPLY_ACK
+ }
+ ```
+ Furthermore if an expression requires to be split more than once, then the
split should occur at the same logical
+ level if possible.
+8. All binary and ternary operators (exception for ".") should be separated
from their operands by a space [mandatory].
+
+### Statements
+
+#### Simple Statements
+
+This section defines the general rules for simple Java statements:
+
+1. There must only be one statement per line [mandatory].
+2. In general local variables should be named in a similar manner to instance
variables [recommended].
+3. More than one temporary variable may be declared on a single line provided
no initialisers are used [mandatory].
+ For example:
+ ```java
+ int j, k = 10, l; // Incorrect!
+ int j, l; // Correct
+ int k = 10;
+ ```
+4. A null body for a while, for, if, etc. should be documented so that it is
clearly intentional [mandatory].
+5. Keywords that are followed by a parenthesised expression (such as while,
if, etc) should be separated from
+ the open bracket by a single space [mandatory]. For example:
+ ```java
+ if (a > b)
+ {
+ munge();
+ }
+ ```
+6. In method calls, there should be no spaces before or after the parentheses
[mandatory]. For example:
+ ```java
+ munge (a, 10); // Incorrect!
+ munge(a, 10); // Correct.
+ ```
+#### Compound Statements
+This section defines the general rules associated with compound statements in
Java:
+
+1. The body of a compound statement should be indented by 4 spaces more than
the enclosing braces [mandatory].
+ See the following rule for an example.
+2. The braces associated with a compound statement should be on their own
line and be indented to the same level
+ as the surrounding code [mandatory]. For example:
+ ```java
+ if ((length >= LEN_BOX) && (width >= WID_BOX))
+ {
+ int i;
+ // Statements omitted...
+ }
+ ```
+3. If the opening and closing braces associated with a compound statement are
further than 20 lines apart
+ then the closing brace should annotated as follows [mandatory]:
+ ```java
+ for (int j = 0; j < SIZE; j++)
+ {
+ lotsOfCode();
+ } // end for
+ ```
+4. All statements associated with an if or if-else statement should be made
compound by the use of braces [mandatory].
+ For example:
+ ```java
+ if (a > b)
+ {
+ statement();
+ }
+ else
+ {
+ statement1();
+ statement2();
+ }
+ ```
+5. The case labels in a switch statement should be on their own line and
indented by a further 4 spaces.
+ The statements associated with the label should be indented by 4 columns
more than the label and not be enclosed
+ in a compound statement. [mandatory]. For example:
+ ```java
+ switch (tState)
+ {
+ case NOT_RUNNING:
+ start();
+ break;
+ case RUNNING:
+ default:
+ monitor();
+ break;
+ }
+ ```
+6. In switch statements - the statements associated with all cases should
terminate with a statement
+ which explicitly determines the flow of control, for example `break`
[recommended].
+7. In switch statements - fall through should be avoided wherever possible,
however if it is unavoidable it must
+ be commented with `// FALLTHROUGH` [mandatory].
+8. In switch statements - a default case must be present and should always be
the last case [mandatory].
+
+### General
+This section gives general rules to be followed when programming in Java:
+
+1. When comparing objects for equivalence use the method equals() and not the
== operator.
+ The only exceptions to this are static final objects that are being used
as constants and interned Strings [mandatory].
+2. In general labelled break and continue statements should be avoided
[recommended].
+ This is due to the complex flow of control, especially when used with
try/finally blocks.
+3. Unless some aspect of an algorithm relies on it, then loops count forward
[mandatory]. For example:
+ ```java
+ for (int j = 0; j < size; j++)
+ {
+ // Do something interesting
+ }
+ ```
+4. Use local variables in loops [recommended]. For example:
+ ```java
+ ArrayList clone = (ArrayList)listeners.clone();
+ final int size = clone.size();
+ for (int j = 0; j < size; j++)
+ {
+ System.out.println(clone.elementAt(j));
+ }
+ ```
+5. Anonymous inner classes should define no instance variables and be limited
to three single line methods.
+ Inner classes that declare instance variables or have more complex methods
should be named [mandatory].
+6. Use final local variables where possible to help avoid errors in code
[recommended]. For example:
+ ```java
+ public void foo()
+ {
+ final int x = dataSource.getCount();
+ // do things with x
+ // ...
+ }
+ ```
+7. To indicate that further work is intended on a section of code, add a
comment prefixed by "TODO" explaining
+ what needs to be done and why [recommended].
+8. If code is so incomplete that executing it would lead to incorrect or
confusing results,
+ throw UnsupportedOperationException with an explanatory message
[mandatory].
+
+### Exceptions
+
+This section gives general guidance on the use of exceptions when programming
in Java.
+
+1. try/catch blocks should be laid out like any other compound statement
[mandatory]. For example:
+ ```java
+ try
+ {
+ String str = someStrings[specifiedIndex];
+ }
+ catch (IndexOutOfBoundsException ex)
+ {
+ // The user specified an incorrect index, better take
+ // some remedial action.
+ }
+ ```
+2. When an exception is caught but ignored then a comment should be supplied
explaining the rationale
+ (note that this rule includes InterruptedException, which should almost
never be ignored) [mandatory]. For example:
+ ```java
+ try
+ {
+ propertySet.setProperty("thingy", new Integer(10));
+ }
+ catch (UnknownPropertyException ignore)
+ {
+ // This exception will never occur as "thingy" definitely exists
+ }
+ ```
+3. All exceptions that are likely to be thrown by a method should be
documented,
+ except if they are runtime exceptions (note: the compiler will not enforce
catch blocks for runtimes even
+ if they are mentioned in the throws clause) [mandatory]. For example:
+ ```java
+ /* Comment snippet:
+ * @exception IllegalValueException Thrown if values is null or
+ * any of the integers it contains is null.
+ */
+ private Integer sum(Integer[] values) throws IllegalValueException
+ ```
diff --git
a/doc/developer-guide/src/main/markdown/consumer-queue-interactions.md
b/doc/developer-guide/src/main/markdown/consumer-queue-interactions.md
new file mode 100644
index 0000000..fa7ceb6
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/consumer-queue-interactions.md
@@ -0,0 +1,164 @@
+# Consumer-Queue Interactions
+
+This article overviews implementation behind interactions between consumers
and queue.
+
+<!-- toc -->
+
+- [Overview](#overview)
+- [Responsibilities](#responsibilities)
+ * [Simple Example](#simple-example)
+ * [Threading Model](#threading-model)
+ * [Interfaces Between Consumers and
Queues](#interfaces-between-consumers-and-queues)
+ * [QueueConsumerManager internals](#queueconsumermanager-internals)
+ + [QueueConsumerNodeList](#queueconsumernodelist)
+ + [The "All" List](#the-all-list)
+ + [The "NonAcquiring" List](#the-nonacquiring-list)
+ + [The "NotInterested" List](#the-notinterested-list)
+ + [The "Interested" List](#the-interested-list)
+ + [The "Notified" List](#the-notified-list)
+ + [Handling Consumer Priorities](#handling-consumer-priorities)
+
+<!-- tocstop -->
+
+## Overview
+
+The main players are
+
+ * Queue - model object providing the messaging queue functionality.
+ * QueueConsumerManager - queue entity responsible for managing queue
consumers
+ * Consumers - queue consumers
+
+The `ConsumerTarget` is the broker-side representation of a consuming client.
Due to multi-queue consumers
+a `ConsumerTarget` has one or more `Consumers` associated with one `Queue`
each. It is this `Consumer` that
+interacts with the `Queue`.
+
+## Responsibilities
+
+A `Queue` is responsible for notification of at least one interested
`Consumer` when there is work to be done
+(message to consume).
+
+A `Consumer` is responsible for notification of its `Queue` when it is ready
to do some work (for example, consume messages).
+When notified by a `Queue` of available work, a `Consumer` MUST try to pull
messages of said `Queue` until either
+it notifies the `Queue` that it is no longer interested OR there are no more
messages available on the `Queue`
+(i.e., the Queue does not return a message).
+
+### Simple Example
+
+ 1. `Message` arrives on the `Queue`
+ 2. The `Queue` notifies some of interested `Consumers` that there is work to
be done
+ 3. The `Consumers` notify their `ConsumerTarget` that they would like to do
work
+ 4. The `ConsumerTargets` notify their `Sessions` that they would like to do
work
+ 5. The `Sessions` notify their `Connections` that they would like to do work
+ 6. The `Connections` schedule themselves. This is the switch from the
incoming `Thread` to the `IO-Thread`.
+ 7. The `Scheduler` kicks off a IO-Thread to process the work of a `Connection`
+ 8. The `Connection` iterates over its `Sessions` that want to do work
+ 9. The `Sessions` iterate over its `ConsumerTargets` that want to do work
+ 10. The `ConsumerTargets` iterate over its `Consumers` that want to do work
+ 11. The Consumer tries to pulls a message from the `Queue`
+ 12. If successful, the message is put on the IO-buffer to be sent down the
wire
+
+### Threading Model
+
+The consuming part is always invoked from the consuming connection's IO-Thread
+whereas the publishing part might be invoked from different threads (producing
connection's IO-Thread,
+Housekeeping thread for held or TTLed messages, a consuming connection's
IO-Thread in case for message reject).
+
+Therefore, the interfaces between `Consumers` and the `Queue` MUST be
thread-safe and SHOULD be lock free.
+
+### Interfaces Between Consumers and Queues
+
+These are the interfaces between `Consumers` and `Queues` and the scenarios
when they are called.
+
+ * `AbstractQueue#setNotifyWorkDesired`
+ Called by the `Consumer` to notify the `Queue` whether it is interested in
doing work or not.
+ * FlowControl
+ * Credit
+ * TCP backpressure
+ * `QueueConsumer#notifyWork`
+ Called by the `Queue` to notify the `Consumer` that there is potentially
work available.
+ * Consumer becomes Interested
+ * A new message arrives
+ * A previously unavailable (acquired, held, blocked by message grouping)
message becomes available
+ * A notified consumer did not do the work we expected it to do we need to
notify someone else
+ * A high priority consumer becomes uninterested and thus allows a low
priority consumer to consume messages
+ * `AbstractQueue#deliverSingleMessage`
+ Called by the `Consumer` to get a message from the Queue.
+ * A consumer was notified and now tries to pull a message of a queue
+
+### QueueConsumerManager internals
+
+The `QueueConsumerManager` (QCM for short) keeps track of the state of
`Consumers` from the perspective of the `Queue`.
+It shares and decides which `Consumer` to notify of work with the `Queue`. To
do this in a performant way it maintains
+a number of lists and moves `Consumers` between those lists to indicate state
change. The lists it maintains are:
+
+ * All (all queue consumers)
+ * NonAcquiring
+ * NotInterested
+ * Interested
+ * Notified
+
+Typically we want these lists to be thread-safe and give us O(1)
access/deletion if we know the element and O(1) size information.
+Unfortunately there is no data structure in the Java standard library with
those characteristics
+which is why they are based on our own data structure `QueueConsumerNodeList`.
+
+#### QueueConsumerNodeList
+
+The `QueueConsumerNodeList` is the underlying data structure of all of QCM's
lists.
+It is thread-safe and allows O(1) appending and given you have a pointer to an
entry O(1) deletion.
+It is essentially a singly linked list. To achieve O(1) deletion entries are
marked for deletion
+but only actually removed upon the next iteration. The rationale being that,
to delete an entry you would need
+to update the previous entry's "next" pointer but to get to the previous
element you would need a doubly linked list
+which it impossible to maintain in a thread-safe way without locking. Special
care must be taken when removing elements
+from the tail since we keep an explicit reference to it in the
`QueueConsumerNodeList` to achieve O(1) appending.
+The data structure in the `QueueConsumerNodeList` are called
`QueueConsumerNodeListEntries` which themselves have
+a reference to a `QueueConsumerNode` which is the persistent entity that moves
between QCM's lists and has a reference
+to the `QueueConsumer`. The `QueueConsumer` itself also has a reference to the
`QueueConsumerNode` to enable O(1)
+deletion given a Consumer. This tightly couples the `QueueConsumer` and QCM
classes.
+
+#### The "All" List
+
+The `All` list contains all `Consumers` registered with the `Queue`.
`Consumers` are added to this list when they are
+created and only removed when the `Consumer` is closed. This list is necessary
to be able to iterate over all consumers
+in a thread-safe way without locking. The danger of using several lists
instead of a single `All` list is that you might
+miss a `Consumer` if it moves between lists during iteration.
+
+#### The "NonAcquiring" List
+
+This is a list of `Consumers` that do not acquire messages for example `Queue
Browsers`. These need to be handled
+separately because they should always be notified about new messages. Where
they kept in the same list
+as the acquiring consumers we would have to iterate of the entire list to make
sure we did not miss
+a non-acquiring consumer. Non-acquiring consumers can only move between the
"NonAcquiring" and "NotInterested" lists.
+
+#### The "NotInterested" List
+
+This list contains all `Consumer`s that indicated to the `Queue` that they
currently are not interested in doing any
+work (i.e., taking messages). This typically happens when a
Consumer/Connection is suspended due to
+FlowControl/TCP backpressure. The main purpose of this list is to avoid
spurious wake-ups of `Consumers` which we know
+are not going to do any work.
+
+#### The "Interested" List
+
+This is the default list for acquiring `Consumers`. It signifies that they are
ready to process messages.
+When a message becomes available, the `Queue` will notify `Consumers` from
this list and move them to the
+"Notified" list. It will only notify a single interested `Consumer` to avoid
spurious wake-ups.
+
+#### The "Notified" List
+
+Once an acquiring `Consumer` is notified that there is work to do it is moved
from the "Interested" list to the
+"Notified" list. The QCM expects such a `Consumer` to either indicate that it
is no longer interested
+(e.g., it became suspended in the meantime and therefore will not do the work
we expected it to) or call
+`AbstractQueue#deliverSingleMessage`. The `Consumer` should remain in the
"Notified" list and continue to call
+`deliverSingleMessage` until `deliverSingleMessage` cannot deliver a message
to it any more, in which case it is moved
+to the back of the "Interested" list. This is to decrease latency due to
wake-ups when there continues to be work
+available (i.e., there is a steady stream of messages). Appending it to the
end of the "Interested" list ensures
+some level of fairness. Note that this is not perfect. It is possible that a
consumer is notified but at the time
+it tries to pull a message of the Queue there no longer is a message available
and the Consumer is returned to the end
+of the "Interested" list without having done work. The assumption is that
while this may happen it is unlikely to always
+happen to the same consumer leading to a kind of "asymptotic fairness".
+
+#### Handling Consumer Priorities
+
+When deciding which `Consumer` to notify the QCM should take consumer
priorities into account.
+To do this in a performant way it maintains a `QueueConsumerNodeList` per
consumer priority in a list of
+`PriorityConsumerListPairs`. This ensures that iteration of the Interested
list happens in the right order and lookup
+of consumers with higher priority can be performed efficiently.
diff --git a/doc/developer-guide/src/main/markdown/examples/maven-settings.md
b/doc/developer-guide/src/main/markdown/examples/maven-settings.md
new file mode 100644
index 0000000..baf2793
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/examples/maven-settings.md
@@ -0,0 +1,36 @@
+# Maven settings with GPG keys
+
+An example of maven `settings.xml` illustrating how to configure gpg keys
+
+```xml
+<settings>
+ <servers>
+ <server>
+ <id>apache.snapshots.https</id>
+ <username>YOUR_APACHE_SVN_USERNAME</username>
+ <password>YOUR_APACHE_SVN_PASSWORD</password>
+ </server>
+ <server>
+ <id>apache.releases.https</id>
+ <username>YOUR_APACHE_SVN_USERNAME</username>
+ <password>YOUR_APACHE_SVN_PASSWORD</password>
+ </server>
+
+ <!-- optional -->
+ <server>
+ <id>gpg.passphrase</id>
+ <passphrase>{XXXX}</passphrase>
+ </server>
+ </servers>
+
+ <profiles>
+ <profile>
+ <id>apache-release</id>
+ <properties>
+ <gpg.keyname>A2889D83</gpg.keyname>
+ <gpg.executable>gpg2</gpg.executable>
+ </properties>
+ </profile>
+ </profiles>
+</settings>
+```
diff --git a/doc/developer-guide/src/main/markdown/ide-integration.md
b/doc/developer-guide/src/main/markdown/ide-integration.md
new file mode 100644
index 0000000..791baf5
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/ide-integration.md
@@ -0,0 +1,46 @@
+# IDE integration
+
+Nowadays, most of the team chose [IntelliJ](https://www.jetbrains.com/idea).
+
+## Integration with IntelliJ
+
+To setup the project, simply import Qpid Broker-J parent pom.xml as a project.
+
+## Running the Broker within Intellij
+
+After importing maven projects create Application configuration following
instructions below
+
+1. Create a new Application run configuration called "Qpid Broker"
+ * Classname org.apache.qpid.server.Main
+ * Classpath of module: qpid-broker
+ * Save the new run configuration.
+2. Go into the module settings of qpid-broker and add an additional classpath
entry pointing to the dojo-x.x.x-distribution.zip.
+ It is easiest to point to a location in the local maven repo e.g.
~/.m2/repository/org/dojotoolkit/dojo/x.x.x/dojo-x.x.x-distribution.zip.
+ (This manual step is required to workaround
https://issues.apache.org/jira/browse/MNG-5567).
+3. Specify the following JVM options for the Qpid Broker Application
+ *
-Dprofile.virtualhostnode.context.blueprint='{"type":"ProvidedStore","globalAddressDomains":"${dollar.sign}{qpid.gloabalAddressDomains}"}'
+ * -Dqpid.globalAddressDomains=[]
+ * -DQPID_WORK=/path/to/Qpid/work/directory
+
+## Running System Tests within Intellij
+
+Running system tests from within IntelliJ requires a bit of fiddeling.
+You first create a template configuration which you then need to adapt every
time you want to run a different systest.
+This means this method does not support running the entire test suite.
+
+1. Add a new JUnit Configuration
+ * "Run" --> "Edit Configurations..."
+ * Press the plus sign at the top left to add a new configuration and select
"JUnit"
+ * Change the name to "Systest"
+ * Add the following to the "VM options"
+ *
-Dprofile.virtualhostnode.context.blueprint='{"type":"ProvidedStore","globalAddressDomains":"${dollar.sign}{qpid.gloabalAddressDomains}"}'
+ * -Dqpid.globalAddressDomains=[]
+ * -DQPID_WORK=/path/to/Qpid/work/directory
+2. When you want to actually run a specific test, copy the fully qualified
class name of the test into the "Class"
+ field of this configuration before executing it.
+
+## IDE Code Style
+
+There is a code style file for the IntelliJ IDE located at
/etc/IntelliJ_Qpid_Style.xml in the source tree.
+All Qpid Java developers should use this or an equivalent style for their IDE.
+Refer [Qpid Broker-J Coding Standards](code-guide.md) for more details about
code style.
diff --git a/doc/developer-guide/src/main/markdown/images/broker-loggers.gliffy
b/doc/developer-guide/src/main/markdown/images/broker-loggers.gliffy
new file mode 100644
index 0000000..09118cd
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/broker-loggers.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":857,"y":301,"rotation":0,"id":112,"uid":"com.gliffy.shape.uml.uml_v1.default.aggregation","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":112,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"end
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/broker-loggers.png
b/doc/developer-guide/src/main/markdown/images/broker-loggers.png
new file mode 100644
index 0000000..f61c470
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/broker-loggers.png differ
diff --git a/doc/developer-guide/src/main/markdown/images/exchanges.gliffy
b/doc/developer-guide/src/main/markdown/images/exchanges.gliffy
new file mode 100644
index 0000000..c2e03d7
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/exchanges.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":673,"y":189,"rotation":0,"id":81,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":81,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"en
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/exchanges.png
b/doc/developer-guide/src/main/markdown/images/exchanges.png
new file mode 100644
index 0000000..727fdca
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/exchanges.png differ
diff --git a/doc/developer-guide/src/main/markdown/images/io.gliffy
b/doc/developer-guide/src/main/markdown/images/io.gliffy
new file mode 100644
index 0000000..2291288
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/io.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":786,"y":625,"rotation":0,"id":136,"uid":"com.gliffy.shape.uml.uml_v1.default.implements","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":136,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":"8.0,2.0","startArrow":0,
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/io.png
b/doc/developer-guide/src/main/markdown/images/io.png
new file mode 100644
index 0000000..f1a0f17
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/io.png differ
diff --git a/doc/developer-guide/src/main/markdown/images/model.gliffy
b/doc/developer-guide/src/main/markdown/images/model.gliffy
new file mode 100644
index 0000000..308cbf6
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/model.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":619,"y":442,"rotation":0,"id":78,"uid":"com.gliffy.shape.uml.uml_v1.default.composition","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":78,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endAr
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/model.png
b/doc/developer-guide/src/main/markdown/images/model.png
new file mode 100644
index 0000000..668830a
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/model.png differ
diff --git a/doc/developer-guide/src/main/markdown/images/pluggability.gliffy
b/doc/developer-guide/src/main/markdown/images/pluggability.gliffy
new file mode 100644
index 0000000..4321551
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/pluggability.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":251,"y":485,"rotation":0,"id":70,"uid":"com.gliffy.shape.uml.uml_v1.default.composition","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":70,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endAr
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/pluggability.png
b/doc/developer-guide/src/main/markdown/images/pluggability.png
new file mode 100644
index 0000000..9be522c
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/pluggability.png differ
diff --git a/doc/developer-guide/src/main/markdown/images/subscriptions.gliffy
b/doc/developer-guide/src/main/markdown/images/subscriptions.gliffy
new file mode 100644
index 0000000..1944f3d
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/subscriptions.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":26,"y":36,"rotation":0,"id":78,"uid":"com.gliffy.shape.basic.basic_v1.default.group","width":925,"height":349,"lockAspectRatio":false,"lockShape":false,"order":78,"graphic":null,"children":[{"x":425,"y":283.5,"rotation":0,"id":77,"uid":"com.gliffy.shape.basic.basic_v1.default.rectangle","width":2
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/subscriptions.png
b/doc/developer-guide/src/main/markdown/images/subscriptions.png
new file mode 100644
index 0000000..e8d64ac
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/subscriptions.png differ
diff --git a/doc/developer-guide/src/main/markdown/images/transactions.gliffy
b/doc/developer-guide/src/main/markdown/images/transactions.gliffy
new file mode 100644
index 0000000..db71e55
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/transactions.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":439,"y":400,"rotation":0,"id":46,"uid":"com.gliffy.shape.uml.uml_v1.default.implements","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":46,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":"8.0,2.0","startArrow":0,"e
[...]
\ No newline at end of file
diff --git a/doc/developer-guide/src/main/markdown/images/transactions.png
b/doc/developer-guide/src/main/markdown/images/transactions.png
new file mode 100644
index 0000000..cb5706e
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/transactions.png differ
diff --git
a/doc/developer-guide/src/main/markdown/images/virtualhost-loggers.gliffy
b/doc/developer-guide/src/main/markdown/images/virtualhost-loggers.gliffy
new file mode 100644
index 0000000..fe5bb91
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/images/virtualhost-loggers.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":1227.5,"y":257,"rotation":0,"id":94,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":94,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,
[...]
\ No newline at end of file
diff --git
a/doc/developer-guide/src/main/markdown/images/virtualhost-loggers.png
b/doc/developer-guide/src/main/markdown/images/virtualhost-loggers.png
new file mode 100644
index 0000000..5b7cf3b
Binary files /dev/null and
b/doc/developer-guide/src/main/markdown/images/virtualhost-loggers.png differ
diff --git a/doc/developer-guide/src/main/markdown/index.md
b/doc/developer-guide/src/main/markdown/index.md
new file mode 100644
index 0000000..1908220
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/index.md
@@ -0,0 +1,30 @@
+# Qpid Broker-J Developer Guide
+
+This guide is intended for developers and contributors of Qpid Broker-J
project to provide guidance and
+reference materials to aid them in developing, building and releasing Qpid
Broker-J.
+
+Each chapter in this guide is intended to be self-contained, so the reader can
jump to an interesting topic.
+
+## Quick Start Guide
+
+A quick start beginner's guide for getting involved with Qpid Broker-J. [Read
it](quick-start.md)
+
+## Working with Source Code
+
+The chapter provides an overview of coding style. [Read it](code-guide.md)
+
+## Build Instructions
+
+The chapter covers build and test options in details. [Read
it](build-instructions.md)
+
+## Release Instructions
+
+The chapter covers release process. [Read it](release-instructions.md)
+
+## IDE integration
+
+Tips on setting up IDE to work with Qpid Broker-J project. [Read
it](ide-integration.md)
+
+## Qpid Broker-J Architecture
+
+The chapter provides an Overview of Qpid Broker-J Architecture. [Read
it](architecture.md)
diff --git a/doc/developer-guide/src/main/markdown/quick-start.md
b/doc/developer-guide/src/main/markdown/quick-start.md
new file mode 100644
index 0000000..a6beb6a
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/quick-start.md
@@ -0,0 +1,124 @@
+# Quick Start Guide
+
+## Prerequisites
+
+The following tools are needed to build Qpid Broker-J
+
+ * Git client
+ * JDK 1.8 or above; you should set the `JAVA_HOME` environment variable and
include its bin directory in your `PATH`.
+ * Maven 3.0 or above; you should set the `M2_HOME` environment variable and
include its bin directory in your `PATH`.
+
+## Getting sources
+
+Checkout sources from git repository
+
+ git clone https://gitbox.apache.org/repos/asf/qpid-broker-j.git
+
+## Building
+
+Navigate into checkout directory and execute maven command
+
+ mvn clean package
+
+## Running tests
+
+Unit tests are executed as part of maven lifecycle phase `test` and
integration tests are executed as part of maven
+phase `verify`. An execution of integration tests is skipped by default
(except for protocol tests). In order to run
+all integration tests a flag `skipITs` needs to be set to `false`. For example,
+
+ mvn verify -DskipITs=false
+
+The command above executes both unit and integration tests. To run only unit
tests use the command below.
+
+ mvn test
+
+## Distribution bundle
+
+Broker distribution bundle is built as part of maven lifecycle phase
`package`, for example
+
+ mvn clean package -DskipTests
+
+The broker distribution assemblies will then be found beneath:
+
+ apache-qpid-broker-j/target
+
+## Running the Broker
+
+For full details, see chapter `Getting Started` in [broker
documentation](http://qpid.apache.org/components/broker-j/index.html).
+The brief instructions are repeated here.
+
+### Expand the broker distribution bundle
+
+Expand the assembly produced by the maven lifecycle stage `package`.
+
+On Linux/Unix:
+
+ tar xvfz
apache-qpid-broker-j/target/apache-qpid-broker-j-x.x.x-SNAPSHOT-bin.tar.gz -C
/target/directory
+
+On Windows:
+
+ Expand zip
apache-qpid-broker-j/target/apache-qpid-broker-j-x.x.x-SNAPSHOT-bin.zip
+
+
+### Declare QPID_WORK environment variable
+
+The Qpid Broker-J stores its configuration and message data in working
directory. The path to working directory can be
+specified using environment variable `QPID_WORK`.
+
+Examples of declaration of environment variable `QPID_WORK` are given below.
+
+On Linux/Unix:
+
+ export QPID_WORK=${HOME}/my-qpid-work
+
+On Windows:
+
+ set QPID_WORK=%APPDATA%\Qpid
+
+### Start broker
+
+Navigate to directory where Qpid broker bundle was expanded and execute Qpid
broker start-up script
+
+On Linux/Unix:
+
+ ./java-broker/x.x.x/qpid-server
+
+On Windows:
+
+ .\java-broker\x.x.x\qpid-server.bat
+
+### Connecting to the Broker
+
+By default, the Broker listens on port 5672 for AMQP and 8080 for http
management. The default username is 'guest'
+and password is 'guest'.
+
+To get to the management console, point a browser to `http://localhost:8080`
+
+## Reporting defect or requesting new feature or improvement
+
+[JIRA](https://issues.apache.org/jira/issues/?jql=project%20%3D%20QPID%20AND%20component%20%3D%20Broker-J%20order%20by%20created%20DESC)
+is used as an issue tracking system for Qpid Broker-J. A JIRA ticket needs to
be raised for the issue.
+
+## Submitting changes
+
+The changes can be submitted as pull request against github mirror of Apache
Qpid Broker-J repo:
+
+ https://github.com/apache/qpid-broker-j
+
+## How to contribute changes to Qpid Broker-J
+
+Here is a set of simple instructions to follow in order to contribute changes.
+Please note, that changes need to be implemented on master branch first before
they can be ported into specific version support branch.
+
+* Raise JIRA ticket
+* Fork github mirror of broker-j repository, if it is not forked yet
+* Create working branch from master in forked repo
+* Implement required changes and unit/integration tests
+* Verify that implementation follows [Qpid code standard](code-guide.md) and
[clean code practices](https://en.wikipedia.org/wiki/SOLID)
+* Verify that all tests are passing locally on a developer machine
+* Commit the changes into working branch
+* Create pull request in github mirror of broker-j repository
+* Verify that all tests executed for PR by project Continuous Integration
tools are still passing
+* Address comments submitted by pull request reviewers if any and applicable
+* The reviewed changes needs to be applied into the master branch by project
committer
+* Close the JIRA ticket
diff --git a/doc/developer-guide/src/main/markdown/release-instructions.md
b/doc/developer-guide/src/main/markdown/release-instructions.md
new file mode 100644
index 0000000..fda2b8e
--- /dev/null
+++ b/doc/developer-guide/src/main/markdown/release-instructions.md
@@ -0,0 +1,192 @@
+# Releasing Qpid Broker-J
+
+This document summarizes the steps of release process for Qpid Broker-J
+
+<!-- toc -->
+
+- [Pre-Requirements](#pre-requirements)
+ * [PGP](#pgp)
+ * [Maven](#maven)
+ * [Java](#java)
+ * [Git](#git)
+- [Release Steps](#release-steps)
+
+<!-- tocstop -->
+
+## Pre-Requirements
+
+The release process is based on [Apache Release
Policy](http://www.apache.org/dev/release.html),
+ [Release Signing](http://www.apache.org/dev/release-signing.html) and
+ [Publishing of Maven
Documents](http://www.apache.org/dev/publishing-maven-artifacts.html#dev-env).
+
+### PGP
+
+Release artifacts needs to be signed. GNU Privacy Guard from
[OpenPGP](https://www.openpgp.org) is used to sign on
+ Apache. Please, refer [Release
Signing](http://www.apache.org/dev/release-signing.html) about PGP public key
+ cryptography. The document provides basic information about release signing
and contains links to various resources
+ about PGP public key cryptography and how to use GNU Privacy Guard to
generate and sign the PGP keys. Install
+ [GNU Privacy Guard](http://www.gnupg.org), generate keys following steps
provided here and upload public keys to
+ keyservers. After publishing keys, login into <https://id.apache.org> and
enter PGP key fingerprint(s),
+ then the corresponding keys will be made available under
<https://people.apache.org/keys/> within a few hours.
+ Additionally, qpid project requires adding a public key into
<https://dist.apache.org/repos/dist/release/qpid/KEYS>.
+
+### Maven
+
+Maven is used to build and manage Qpid Java project. 3.x version of maven
needs to be installed and the development
+ environment should be setup as described at
+ [Publishing of Maven
Artifacts](http://www.apache.org/dev/publishing-maven-artifacts.html#dev-env).
+
+Please, note that repository id (server id) in `settings.xml` should be
**apache.releases.https**. Using different id
+would result in failures to publish release artifacts into staging maven repo.
+
+### Java
+
+JDK 1.8 is required to compile java classes. Install latest 1.8 JDK. At the
moment of writing this document JDK version
+1.8.0_192 was the latest one.
+
+### Git
+
+Sources are kept in a Git repository. Thus a git client is required.
+
+## Release Steps
+
+1. Checkout Qpid Broker-J Sources
+ * For new major/minor release; checkout sources master
+
+ git clone https://gitbox.apache.org/repos/asf/qpid-broker-j.git
qpid-broker-j
+ * For bugfix release
+ * if support branch does not exist, cut the support branch and set the
correct version in maven.
+ For example, here are the commands to cut branch '8.0.x'
+
+ git clone
https://gitbox.apache.org/repos/asf/qpid-broker-j.git qpid-broker-j
+ cd ./qpid-broker-j
+ git checkout -b 8.0.x
+ git push -u origin 8.0.x
+ * if branch exists, checkout branch sources
+
+ git clone -b 8.0.x
https://gitbox.apache.org/repos/asf/qpid-broker-j.git 8.0.x
+ cd 8.0.x
+2. Run RAT tool to verify that all source files have license headers
+
+ mvn apache-rat:check
+3. Add license headers to the files which do not have licenses. Update RAT
excludes if required.
+4. Check that images don't have a non-free ICC profile.
+
+ find . -regextype posix-extended -iregex '.*\.(jpg|png|ico|tif)' -exec
sh -c 'identify -verbose "$0" | grep -i copyright && echo "$0"' {} \;
+5. Check that build completes successfully using profile **apache-release**
+
+ mvn clean install -Papache-release -DskipTests
+ The gpg plugin will prompt for the password of PGP signing key. If
password is asked for every release artifact,
+ then gpg2 should be configured to use. The easiest way to configure gpg2
is to add an active profile with pgp
+ plugin settings into `settings.xml` as illustrated in [maven settings
example](examples/maven-settings.md).
+6. Verify third party licenses
+
+ mvn -Pdependency-check prepare-package -DskipTests
+ The check should finish successfully. Otherwise, dependencies with not
compliant licenses should be resolved
+ before taking next release step.
+7. Check JIRA system for any unresolved JIRAs for the release and notify
assigned developers to take actions
+ on uncompleted JIRAs.
+8. Build RC
+ * If it is not a first RC, remove previous tag from git
+
+ git push --delete origin x.y.z
+ git tag --delete x.y.z # deletes local tag
+ * Cut the tag using maven:prepare
+
+ mvn release:clean
+ mvn release:prepare -Papache-release,java-mms.1-0
-DautoVersionSubmodules=true -DpreparationGoals=test
+ Release plugin will ask about new release version, tag name and new
development version.
+ Enter the same values for version and tag.
+ On successful execution a tag with a provided name will be created, the
tag version will be set to the specified
+ release version and development version on the branch will be changed to
the provided one.
+ * Build the RC and publish release artifacts into maven staging repo
+
+ mvn release:perform -Papache-release,java-mms.1-0
-Darguments="-DskipTests"
+ * The staging maven repository needs to be closed. Log into
+ [Apache Nexus UI](https://repository.apache.org/#stagingRepositories),
select the repository under
+ **Staging Repository** and click `Close` button to close staging
repository for any publishing of artifacts.
+ After closing, a permanent link to the staging repository will be
available.
+ * Copy source and binary bundles and their signatures/checksum files from
the nexus staging repository into
+ qpid dev staging area at
<https://dist.apache.org/repos/dist/dev/qpid/broker-j/> under the sub-folder
with
+ the same name as tag. Binary bundles and their signatures/checksum
files need to be put into sub-folder
+ with name binaries. (Not doing so would break the site). Manually rename
the source artifact to keep with
+ the source artifact name consistent.
+
+ version=x.y.z
+
root=https://repository.apache.org/content/repositories/orgapacheqpid-####
+ mkdir binaries
+
+ for i in "" ".asc"; do
+ curl -O
$root/org/apache/qpid/apache-qpid-broker-j/${version}/apache-qpid-broker-j-$version-src.tar.gz$i
+ if [[ "$i" == "" ]]; then
+ sha512sum apache-qpid-broker-j-$version-src.tar.gz >
apache-qpid-broker-j-$version-src.tar.gz.sha512
+ fi
+ done
+
+ cd binaries
+
+ for i in "" ".asc"; do
+ for j in "tar.gz" "zip"; do
+ curl -O
$root/org/apache/qpid/apache-qpid-broker-j/${version}/apache-qpid-broker-j-$version-bin.$j$i
+ done
+ done
+
+ for j in "zip" "tar.gz"; do
+ sha512sum apache-qpid-broker-j-$version-bin.$j >
apache-qpid-broker-j-$version-bin.$j.sha512
+ done
+
+ for j in "zip" "tar.gz"; do
+ sha512sum -c apache-qpid-broker-j-$version-bin.$j.sha512
+ gpg --verify apache-qpid-broker-j-$version-bin.$j.asc
+ done
+
+ cd ..
+
+ sha512sum -c apache-qpid-broker-j-$version-src.tar.gz.sha512
+ gpg --verify apache-qpid-broker-j-$version-src.tar.gz.asc
+ * Send an email into **[email protected]** about RC availability with
links to the maven staging repository
+ and qpid dev staging area folder containing source and binary bundles.
+9. If RC is OK and voting passes, publish release artifacts:
+ * send a email to **[email protected]** to close the vote. This should
include the number of binding and
+ non-binding votes, the result, and a link to the voting thread (use
Apache services -
+ [this](https://mail-archives.apache.org/mod_mbox/qpid-users/) or
+ [this](https://lists.apache.org/[email protected])).
+ * promote maven staging artifacts from staging repository into the world
by pressing Release button in
+ [Apache Nexus UI](https://repository.apache.org/#stagingRepositories).
+ * copy source and binary bundles and their signatures/checksum files form
dev staging are into
+ release distribution area.
+
+ svn cp -m "Publish x.y.z release artifacts"
https://dist.apache.org/repos/dist/dev/qpid/broker-j/x.y.z-rc1 \
+ https://dist.apache.org/repos/dist/release/qpid/broker-j/x.y.z
+ If voting does not pass, resolve found issues, drop staging repository,
delete svn tag and repeat instructions
+ from step 8 until voting passes.
+10. Wait for 24 hours after closing the vote
+11. Update Qpid web site pages for new release of Qpid Broker-J component and
publish new release documentation
+ following instructions [in site
README.md](https://gitbox.apache.org/repos/asf?p=qpid-site.git;a=blob;f=README.md).
+ Here are sample commands which could be used to create 7.0.0 release pages
on the website based on the 7.0.0 tag.
+
+ git clone https://gitbox.apache.org/repos/asf/qpid-site.git site
+ cd ./site
+ make gen-broker-j-release RELEASE=7.0.0
ISSUES_RELEASE=qpid-java-broker-7.0.0
+ vim ./input/releases/qpid-broker-j-7.0.0/release-notes.md # headline
major enhancements and new features
+ vim ./input/_transom_config.py # Update the current
release pointer
+ vim ./input/releases/index.md # Add current release,
move the previous
+ make render
+ make check-links
+ make publish
+ git add input/
+ git add content/
+ git commit -m "Update site for Qpid Broker-J release 7.0.0"
+ git push
+12. Mark release as released in JIRA and close any unresolved JIRAs if required
+13. Send the release notification email into **[email protected]**,
**[email protected]** and
+ **[email protected]**.
+ * Note, In order to send messages into **[email protected]** one need to
send the mail with the **From** field
+ set to one's apache.org address. Gmail can be set-up to do so via use of
the ASF mail relay.
+ The details how to set up apache account to use ASF mail relay can be
found in the following resources
+ * <https://blogs.apache.org/infra/entry/committers_mail_relay_service>
+ *
<https://reference.apache.org/committer/email#sendingemailfromyourapacheorgemailaddress>
+ *
<http://gmailblog.blogspot.co.uk/2009/07/send-mail-from-another-address-without.html>
+14. Remove the previous release binaries from
<https://dist.apache.org/repos/dist/release/qpid/broker-j>
+ when a new one is announced.
+15. Create jenkins jobs for new major/minor version if required
diff --git a/doc/pom.xml b/doc/pom.xml
index dac68c1..ac4e69a 100644
--- a/doc/pom.xml
+++ b/doc/pom.xml
@@ -74,6 +74,7 @@
<modules>
<module>java-broker</module>
<module>java-perftests</module>
+ <module>developer-guide</module>
</modules>
<build>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]