ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r1641501 [4/4] - in /ace/site/trunk/content: ./ dev-doc/ docs/ docs/analysis/ docs/analysis/src/ docs/design/ docs/design/src/ docs/use-cases/ user-doc/
Date Mon, 24 Nov 2014 22:42:03 GMT
Added: ace/site/trunk/content/docs/user-guide.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/user-guide.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/user-guide.mdtext (added)
+++ ace/site/trunk/content/docs/user-guide.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,521 @@
+Title: ACE User guide
+
+This article describes how to use ACE and is a good starting point for new users of Apache
+ACE. The remainder of this article assumes you have an ACE server and target up and
+running. Follow the [getting started in 5 minutes](/docs/getting-started-5-mins.html)
+guide in case you have not done so yet.
+
+[TOC]
+
+
+## Introduction
+
+Apache ACE is a framework that enables you to provision OSGi software (components) in a
+controlled manner. What this means is that you have a central server to which clients, or
+"targets" in ACE terminology, connect and fetch their software from. This allows one to
+control which target gets which software. 
+
+The software that is deployed to a target is composed of one or more distributions. A
+distribution is roughly similar to a piece of self-contained software. For example, it
+could be a plugin or even a full application. On their own, distributions consist of one
+or more features, that provide pieces of functionality to your software. The difference
+between a feature and distribution is that the former is not necessarily fully
+self-contained: it might need other features in order to operate properly. Each feature
+groups one or more artifacts. An artifact is anything from an OSGi bundle to a
+configuration file or any other kind of artifact that is needed for the software to work.
+
+The artifacts themselves reside in an OSGi Bundle Repository (OBR). Think of an OBR as a
+repository, like the Maven repository or a content repository, storing *immutable*
+versions of artifacts[^1]. You can use either the default OBR supplied by ACE or an
+external one, such as [Sonatype's
+Nexus](http://books.sonatype.com/nexus-book/reference/osgi-sect-hosted.html) for storing
+your artifacts.  
+As the OBR is the *single source* for all artifacts, and therefore the software that is
+deployed on a target, ACE is able to calculate how to upgrade a target from one version to
+another version. This is possible because *all* changes made to (the metadata of) ACE are
+stored in an internal versioned database. In other words, ACE always keeps a full history
+and audit trail for all changes, making it possible to go back and forth between versions
+deployed on each target.
+
+
+## Use cases and workflow
+
+The typical use case for using ACE is where you want to control and manage which software
+runs on what target. So, how does one use ACE in practice? To explain the typical workflow
+of ACE, let's take the following example.
+
+Assume you are working on a large OSGi-based system that provides some kind of service to
+your users (the exact details on what it does isn't relevant for this example).
+
+As professional taking development seriously, you want to set up a [DTAP
+environment](http://en.wikipedia.org/wiki/Development,_testing,_acceptance_and_production).
+Your developers are working on their development machines, creating and using the latest,
+bleeding, edge of software they are working on. Even though they are smart guys that know
+the software inside out and can set up their own environments, they still might want to
+use ACE on their local machines to validate that changes they make indeed work when
+deployed. In this cases it makes sense to use the same deployment method that is used in
+production lateron as well.
+
+There are also testers on your team, responsible for testing all the new features and bug
+fixes made by your developers. This tester does not want to have to set up his own
+environment and fiddle around with configuration files and such. Instead, he simply wants
+a working test environment that runs a recent version of the software, or even want to go
+back and forth between versions of the software. This is also were ACE can help you out.
+All you need to do is create targets for testing, on which a recent software version gets
+deployed. That "recent version", can, for example, be a nightly build that comes out of
+your CI server that automatically gets pushed to ACE after the nightly build is finished.
+Alternatively, the tester also can deploy an older version to his testing target through
+the ACE server UI, for example, to do some regression testing. A third scenario might be
+to duplicate the exact configuration and version that is currently deployed to a specific
+user's target.
+
+Before a new version of your software is put into production, your users want to do
+acceptance testing to see whether this new version does not break anything. The acceptance
+environment should only be updated when a new version is released and after that remains
+as-is. In practice, this is most often not the case, as the acceptance environment is,
+when not used by any user, confiscated by your tester for its daily testing purposes,
+simply, because ACE allows him to easily deploy other versions to the acceptance
+environment. When a user asks for an acceptance test, he simply deploys the latest
+greatest official release to the acceptance environment, and lets the user do its testing.
+After that, he can repurpose it again. Another scenario obviously is that users setup
+dedicated targets for the purpose of acceptance testing.
+
+When all acceptance tests are successful, the new version of your software needs to be
+deployed on several production environments, which is done by you, the release manager. As
+most production environments only differ in a few details, such as IP addresses and maybe
+the database credentials, you use the template engine of ACE to make specific
+configuration files for each production target. This way, you can easily scale up your
+production environment by defining new targets and provide them with the necessary
+configuration values.
+
+### Workflow
+
+Apache ACE can be used in many different workflows, which makes it rather difficult for
+new users to comprehend to use ACE to its full extent. By default, that is, without any
+configuration, the workflow of ACE is as follows (see also figure 1):
+
+1. a "release manager" (either you, or somebody designated to that role), ensures that the
+targets are defined. This is where the software is deployed and running. You can predefine
+each target using the ACE web UI, or start each target (and configure them properly to
+contact your ACE server) and make them appear automatically in your workspace (you might
+need to refresh your workspace before targets appear in the web UI);
+2. the release manager defines the features and distributions that need to be deployed. In
+the simplest case, you can define only one feature and distribution, but go also define
+much more fine-grained features and distributions if needed. The easiest way to define
+features and distributions and to link them to each other is by using the ACE web UI. This
+allows you to simply use the "add" buttons and drag-and-drop to achieve this;
+3. the artifacts are added to your OBR. This can be done by uploading them through on of
+the ACE clients, for example, the web UI. Once uploaded, the artifacts need to be linked
+to features in order to be deployed to targets. Again, the ACE web UI makes this easy by
+simply using drag-and-drop to link artifacts to features;
+4. the next time the target contacts the ACE server, it will retrieve the configured
+distribution(s);
+5. If you linked artifacts to features using the ACE web UI, it will create "wildcard"
+assocations, meaning that it will automatically use the latest version available for each
+artifact. This means that if you update *existing* artifacts in the OBR, ACE will
+automatically deploy them to all affected targets. If you add new artifacts, you need to
+link them to existing or new features and distributions to deploy them.
+
+<a href="simple-workflow.png" target="_blank"><img src="simple-workflow.png" height="250px" title="Figure 1: Typical ACE workflow." /></a>  
+**Figure 1**: A graphical overview of a typical workflow of ACE (click on image to see full size).
+
+<!-- TODO: describe how you can extend/customize the workflow -->
+
+## Working with the ACE Server
+
+The ACE web UI (see figure 2) might look a bit daunting at first, but once you become more
+familiar with it, you'll see that it is rather easy to work with.
+
+<a href="ace_server_ui.png" target="_blank"><img src="ace_server_ui.png" width="640px" title="Figure 2: The server UI of ACE, showing the control area at the top, and the resource area below that." /></a>  
+**Figure 2**: The server UI of ACE after logging in, showing the control area at the top, and the resource area below that (click on image to see full size).
+
+After logging in, the main window consists of two main areas:
+
+1. The control area at the top of the screen, where you can perform actions like
+retrieving the latest repository changes, revert the changes you've made locally, add new
+artifacts, and so on;
+2. The resource area, consisting of (up to) four columns showing the current artifacts,
+features, distributions and targets that are known to ACE. When you select an entity here,
+the associated entities in other columns will automatically be highlighted, giving you an
+instant overview of the links within the system.
+
+Apache ACE allows for concurrent use at every aspect. Many targets can request different
+versions of software that need to be served, while at the same time one or more users are
+uploading artifacts and/or defining new features or distributions. To support this, ACE
+has the concept of a "workspace". This somewhat resembles a VCS you might already use for
+your software development. Prior to making changes, you need to "check out" a workspace in
+an ACE client. In the web UI, this is done implicitly if you hit the "Retrieve" button.
+Once the workspace is checked out, you can make any changes you want, that is, create
+features, distributions, targets and/or create links between them. If you are finished,
+you need to "commit" your workspace back to the ACE server to persist the changes.
+Committing your changes in the ACE web UI is done by using the "Store" button. The
+"Revert" button can be used to throw away your changes in the web UI. Note that this does
+*not* retrieve the latest changes from the ACE server! This is only done when using the
+"Retrieve" button.
+
+### Uploading artifacts
+
+The easiest way to add one or more *new* artifacts is by simply dragging and dropping them
+on the artifact column. *Note that a drop is accepted only when a blue line or border is
+shown around the artifacts column (see figure 3)*. The artifacts are uploaded
+automatically in the background, and when they are complete, a summary of the upload
+results is shown as notification (see figure 4).
+
+<a href="ace_dnd_artifacts.png" target="_blank"><img src="ace_dnd_artifacts.png" width="640px" title="Figure 3: Adding new artifacts by dragging them onto the artifacts column. Note the blue line surrounding the artifacts column denoting the drop can be accepted." /></a>  
+**Figure 3**: Adding new artifacts by dragging them onto the artifacts column. Note the blue line surrounding the artifacts column denoting the drop can be accepted (click on image to see full size).
+
+<a href="ace_dnd_artifacts_ok.png" target="_blank"><img src="ace_dnd_artifacts_ok.png" width="640px" title="Figure 4: A notification is shown when all artifacts are successfully uploaded." /></a>  
+**Figure 4**: A notification is shown when all artifacts are successfully uploaded (click on image to see full size).
+
+To add artifacts that are already in the OBR, you click the "Add artifact..." button. An
+"Add artifact" dialog opens, showing the artifacts currently in the OBR (but not yet in
+the list of selected artifacts) and a list of to-be-uploaded artifacts. This window also
+allows you to upload artifacts, and offers two options to do so:
+
+1. by uploading the individual artifacts by pressing the "Upload" button and selecting the
+artifact from the file chooser dialog, or;
+2. by using drag-and-drop: select all artifacts in an Explorer or Finder and drag them
+onto the "Upload artifact" area. This way, you can upload multiple artifacts in one go.
+
+If you try to upload an artifact that is not recognized by ACE, a failure notification is
+displayed noting that that particular artifact is not uploaded (see figure 5). Adding
+support for new types of artifacts in ACE is discussed in more details in [this
+article](/docs/adding-custom-artifact-types.html).
+
+<img src="ace_dnd_artifacts_fail.png" width="369px" title="Figure 5: A failure notification is shown when one or more artifacts could not be recognized by ACE." />  
+**Figure 5**: A failure notification is shown when one or more artifacts could not be recognized by ACE.
+
+Once all artifacts are uploaded, they appear as selected rows in the artifacts column. You
+can immediately drag them onto the feature column to link them to a particular feature. By
+double clicking on an artifact, you can edit some of its properties, for example, its
+description.  
+To remove an artifact from the artifacts column, you simply press its trash-can icon. Note
+that removing an artifact will only remove it from the artifacts column, *not* from the
+OBR.
+
+A very important concept to remember is that *all* metadata in Apache ACE is stored in
+versioned databases. This makes it possible to determine what differences there are
+between (any) two versions, but only if all artifacts in the OBR also remain the same once
+they are uploaded. This is why ACE does not allow you to add the same artifact twice.
+
+**NOTE**: As described earlier, all changes made through the Web UI need to be stored
+explicitly by pressing the "Store" button or by hitting CTRL+S (or CMD+S if you happen to
+use OSX), otherwise they will not be visible to the ACE server. In case you want to revert
+all changes, you can use the "Revert" button or CTRL/CMD+U. This will ignore all local
+changes but does *not* retrieve the latest state from the server. To retrieve the latest
+state from the server, use the "Retrieve" button or CTRL/CMD+G.
+
+### Creating a new feature, distribution and/or target
+
+Adding features and distributions are very similar. You either click the "+" button above
+the features column, or the "+" button above the distributions column. Alternatively, you
+canuse the shortcut keys CTRL/CMD+F and/or CTRL/CMD+D to add new features/distributions.
+In both cases, you are presented with a dialog that allows you to enter the (mandatory)
+name of the feature or distribution and an optional description.
+
+To define a new target in the ACE web UI, you can do either:
+
+1. pre-register a target by clicking the "+" button above the targets column and entering
+the name of the new target. This allows you to associate software to this target before it
+has ever been started or seen by the server; or,
+2. you can register a target that is already running and has already tried to fetch
+software from the ACE server. The details on this will be discussed later on.
+
+After a feature, distribution or target is created, you can edit its properties by double
+clicking it. For features and distributions, this means you can alter their description,
+while for targets, there are more possibilities to view and alter:
+
+* On the Management tab, you can change whether or not the target should be automatically
+  updated to the latest software. If selected, all updates will automatically be approved
+  and distributed to that target. If not, any update must be explicitly approved prior to
+  being distributed to the target;
+* On the Info tab, you can view the current state of the target, such as the currently
+  installed version, or the latest available software version;
+* On the LogViewer tab, you can view the installation log of the target. This allows you
+  to review the installation of updates on that target;
+* The Tag Editor tab allows you to define tags and their values. Tags can be used for many
+  things, but one of their more interesting use cases is that they can be used to replace
+  variables in template artifacts that contain those tags. This is useful, for example, to
+  have a single configuration file that can be used for multiple targets, because it is
+  largely the same for all of them.
+
+### Creating associations
+
+To link artifacts to features, you simply select the artifact and drag it on top of the
+feature to which it should be associated. The same principle also applies if you want to
+associate features to distributions and distributions to targets. To delete an association
+once is created, you can click either the left- or the right hand side of the association
+(viz. either the artifact or the feature), and click the "broken chain" button on the
+opposite side of the association. For example, to delete an association between an feature
+and distribution, you can select the feature first, and hit the "broken chain" button on
+the distribution. Alternatively, you can select the distribution first and hit the "broken
+chain" button on the feature to delete the association.
+
+There is a subtle, but *very* important, difference when you associate a bundle-artifact
+to a feature by dragging its symbolic name (without a version) onto a feature, or when you
+drag a bundle-artifact with a version onto a feature. In the first case, you make a
+"dynamic" association (see figure 6), which states that you always want the *latest*
+version of that bundle to be associated to the feature, including any newer version that
+might be uploaded in the future. In the latter case, you make a "static" association (see
+figure 7), which states that you always want that particular version of that bundle to be
+associated to the feature.
+
+<img src="ace_dynamic_association.png" width="516px" title="Figure 6: Creating a dynamic association by dragging the BSN of a bundle onto a feature." />  
+**Figure 6**: Creating a dynamic association by dragging the BSN of a bundle onto a feature.
+
+<img src="ace_static_association.png" width="522px" title="Figure 7: Creating a static association by dragging a particular version of a bundle onto a feature." />  
+**Figure 7**: Creating a static association by dragging a particular version of a bundle onto a feature.
+
+Creating dynamic associations is currently only supported for bundle artifacts. For other
+types of artifacts, such as configuration files, only static associations can be
+created[^2]. 
+
+### Configuring the server
+
+The ACE server is completely modular and therefore can be configured in many different
+ways. As such, the configuration of the server is done by using the Configuration Admin
+service which is provisioned by means of configuration files that reside in the
+<tt>conf</tt> directory.  The filename of each configuration file equals the service PID
+of the managed service and **must** end with <tt>.cfg</tt>. Directories are considered as
+managed service factories of which the directory name equals the service PID.
+
+Configuration files itself are simple Java property files containing key-value pairs
+separated by newlines. Configuration values are allowed to contain "placeholders" or
+"variables". Everything between <tt>${</tt> and <tt>}</tt> is considered a variable and
+replaced by the value represented by that variable. For example, consider a variable
+<tt>var</tt> that is defined as "<tt>value</tt>", then <tt>${var}</tt> will be replaced
+with "<tt>value</tt>". Variables can refer to another value in the *same* configuration
+file, or to a property that is defined in the OSGi-framework or globally in your system as
+environment setting.
+
+The configuration files are watched continuously in the background, allowing you to adjust
+the configuration of the ACE server at runtime without having to restart it.
+
+## Running a target
+
+As mentioned, a target represents a client on which software can be deployed by ACE.
+Actually, a target consists of an OSGi runtime that runs *at least* the ACE management
+agent. This management agent periodically checks with the ACE server whether or not new
+software is available. In case new software is available for a target, it can
+automatically download and install it.
+
+ACE provides a single runnable JAR <tt>target.jar</tt> that starts an OSGi runtime, the
+ACE management agent, and a Gogo shell for easy debugging and demo purposes. It is also
+available in the ACE source repository as Eclipse project called <tt>run-target</tt>.  
+The management agent, or agent for short, does the following:
+
+1. it uploads the audit log of the target to the ACE server. The audit log contains all
+changes in bundle and framework state, such as the starting and stopping of the framework
+and (de)installation of bundles;
+2. it check whether or not software updates are available. If so, it will download it and
+install this update automatically.
+
+To run a target, you need to issue the following command:
+
+    :::sh
+    $ java \
+        -Dagent.identification.agentid=target-1 \
+        -Dagent.discovery.serverurls=http://my.ace.server:8080 \
+        -jar target.jar
+    ____________________________
+    Welcome to Apache Felix Gogo
+    ...
+
+### Target configuration
+
+The agent can be configured by supplying its options as commandline parameters (e.g.
+<tt>-Dname=value</tt>). A list of most used options are[^7]:
+
+<tt>agent.identification.agentid</tt>
+: defines the name to uniquely identify a target on the ACE server. In case this option is
+not supplied, a default value of <tt>defaultTargetID</tt> is used;
+<tt>agent.discovery.serverurls</tt>
+: defines the ACE server URLs to connect to. Multiple URLs can be given to get a form of
+fail-over: in case a connection to the first URL cannot be established, the second URL
+will be used, and so on. If this option is given, at least one URL should be supplied, and
+multiple URLs can be supplied by separating them with a comma. If this option is omitted,
+a default value of <tt>http://localhost:8080</tt> is used;
+<tt>agent.discovery.checking</tt>
+: defines whether or not server URLs should be checked whether they are alive prior to
+being used. This implies that a "ping" request is sent to the server URL that is going to
+be used. Server URLs that are not responding will not be used and will cause another URL
+(defined by <tt>agent.discovery.serverurls</tt>) to be picked instead. The default value
+is <tt>true</tt>, which means that all server URLs are checked. Use <tt>false</tt> if your
+ACE server(s) are not always available or when running the target on a flacky network;
+<tt>agent.logging.level</tt>
+: defines the log level of the agent, and should be one of the following values:
+<tt>DEBUG</tt>, <tt>INFO</tt>, <tt>WARNING</tt> or <tt>ERROR</tt>. The default log level
+is <tt>INFO</tt>;
+<tt>agent.controller.syncinterval</tt>
+: defines the interval (in seconds) in which the agent should synchronize with the ACE
+server. A default of <tt>60</tt> seconds is used in case this option is not supplied;
+<tt>agent.controller.syncdelay</tt>
+: defines how long the agent should wait (in seconds) after startup before it will
+synchronize with the ACE server for the first time. A default of <tt>5</tt> seconds is
+used in case this option is not supplied;
+<tt>agent.controller.streaming</tt>
+: if given a value of <tt>false</tt>, all software updates will be downloaded completely
+first after which it will be installed. Use this value in case you suffer from unreliable
+network connections. A value of <tt>true</tt> (the default) causes the agent to download
+and install any software update directly.
+<tt>agent.controller.fixpackages</tt>
+: if given a value of <tt>true</tt> (the default), software updates will only contain the
+deltas or changed artifacts. For large deployment packages, this can dramatically reduce
+the size of an update. Use a value of <tt>false</tt> to *always* get *all* artifacts for
+*each* software update;
+<tt>agent.controller.retries</tt>
+: defines the number of times the agent should retry to install a software update in case
+its installation fails. If omitted, an installation is retried <tt>3</tt> times;
+<tt>agent.feedback.channels</tt>
+: defines what feedback channels exist and should be synchronized with the ACE server.
+Feedback channels can be used to report any kind of information back to the ACE server,
+and is by default used to provide basic information on the OSGi environment to the ACE
+server. If omitted, the default of <tt>auditlog</tt> is used. Multiple feedback channels
+can be supplied by separating them with commas, like <tt>auditlog,myOwnLog</tt>. Note that
+all mentioned feedback channels *must* be configured on the ACE server as well;
+<tt>agent.logging.events.exclude</tt>
+: defines the audit events that should be *excluded* from appearing on the audit feedback
+channel. This parameter takes one or more event types represented by integers separated by
+commas, for example, <tt>2001,2003,2005,3001</tt>. By default, *no* events are excluded;
+<tt>agent.connection.authtype</tt>
+: defines how to connections to the server are to be authenticated. Valid values are
+<tt>NONE</tt> for no authentication, <tt>BASIC</tt> for using HTTP-BASIC authentication or
+<tt>CLIENTCERT</tt> for using client certificates. In case this option is omitted, a value
+of <tt>NONE</tt> is assumed and no authentication is used. In case of the values
+<tt>BASIC</tt> or <tt>CLIENTCERT</tt>, additional options should be supplied (see below);
+<tt>agent.connection.username</tt> and <tt>agent.connection.password</tt>
+: provide the username and password used for HTTP-BASIC authentication;
+<tt>agent.connection.sslProtocol</tt>
+: defines what SSL protocol is to be used for creating secure connections to the ACE
+server, defaults to <tt>TLS</tt>;
+<tt>agent.connection.keyfile</tt> and <tt>agent.connection.keypass</tt>
+: provide the keystore file and password that contain the certificate information for
+establishing a secure conncetion between agent and server;
+<tt>agent.connection.trustfile</tt> and <tt>agent.connection.trustpass</tt>
+: provide the truststore file and password that contain the trusted (server)
+certificate(s) for establishing a secure connection between agent and server.
+
+
+When the agent is started, a new target should appear in the ACE server after you
+"Retrieve" the latest changes in the web UI. Note that this can take a little while since
+the agent needs to synchronize with the server first, see
+<tt>agent.controller.syncdelay</tt> and <tt>agent.controller.syncinterval</tt> options
+above. If a new target is seen this way by an ACE server instead of adding it through the
+"+" button above the targets column, it initially will be *unregistered*. This means that
+no metadata is present in the ACE server yet and will not be created. To register a
+target, you can double click the target to edit its properties.  On the "Management" tab,
+you can check the "Registered?" option (and optionally the "Auto approve?" option as well)
+and close the dialog by pressing "Ok"[^3]. Once a target is registered, it cannot be
+unregistered unless it is deleted (using the trash-icon).
+
+
+### Using the template engine for targets
+
+If you want to provision software to multiple targets, each of those targets probably need
+to have their own specific configuration. For example, the IP address on which it should
+listen for web requests, or the credentials to access a database. One could create
+specific configuration files for each target, however, this can become quite tedious if
+you have lots of targets. Besides that, ACE requires that each artifact has a unique name,
+so you need to create unique file names for your configuration files for each change you
+make. Fortunately, ACE provides an easier way to solve this problem: a template engine.
+
+All configuration files[^4] can be regarded as templates, in which variables are replaced
+with values supplied by ACE. In fact, the values are definable per target, distribution,
+feature or artifact and ACE will collect all tags of entities that are associated with a
+specific target. To define variables and their replacement values (or "tags") for, for
+example, a distribution, open up its properties dialog by double clicking on it, and
+selecting the "Tag Editor" tab. Each line in this editor represents a tag. The key of a
+tag defines that (part of) the variable name to be replaced in configuration files, and
+the value of a tag the actual replacement value.  
+In order to let ACE provision your (templated) configuration files to your target, you
+need a **resource processor** that is capable of handling the configuration files. Without
+such a resource processor, the configuration files cannot be deployed to your target. See
+[this article](/docs/adding-custom-artifact-types.html) for more information about writing
+resource processor for your configuration files, or use an existing one, such as [Felix
+Autoconf resource
+processor](http://felix.apache.org/documentation/subprojects/apache-felix-autoconf.html). 
+
+Suppose a valid resource processor is available that recognizes [Java Properties
+XML](http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html), consider the
+following configuration file:
+
+    :::xml
+    <properties version="1.0">
+      <entry key="ipAddress">${context.address}</entry>
+      <entry key="port">${context.port}</entry>
+      <entry key="logLevel">INFO</entry>
+    </properties>
+
+The <tt>${context.address}</tt> and <tt>${context.port}</tt> represent variables that can
+be replaced. The <tt>context.</tt> (including the dot) prefix is mandatory, and everything
+after this prefix is user-definable and considered as variable name. In this example, two
+variables are expected: <tt>address</tt> and <tt>port</tt>. The values for these variables
+can be added to entities by using the "Tag Editor", available when you double click on an
+artifact, feature, distribution or target in the web UI[^5]. It does not really matter on
+what entity the variables are actually defined, but in most cases they are either defined
+on a distribution and/or target.
+
+Suppose we want to deploy the aforementioned configuration file to two targets,
+"target-1", which is supposed to listen on <tt>192.168.2.1:80</tt> and "target-2", which
+is supposed to listen on <tt>192.168.2.2:8080</tt>. To make the configuration file
+specific for both targets, we simply need to define two tags on "target-1", like (see also
+figure 7):
+
+* <tt>address</tt> -&gt; <tt>192.168.2.1</tt>;
+* <tt>port</tt> -&gt; <tt>80</tt>.
+
+And similar tags on "target-2": 
+
+* <tt>address</tt> -&gt; <tt>192.168.2.2</tt>;
+* <tt>port</tt> -&gt; <tt>8080</tt>.
+
+<img src="ace_target_tag_editor.png" width="600px" title="Figure 8: Using the Tag Editor of a target to supply configuration variables." />  
+**Figure 8**: Using the Tag Editor of a target to supply configuration variables.
+
+Under the covers, ACE uses Velocity[^6] to parse the template. This means that, apart from
+variable substitution, you can also use other Velocity macros and create more complex
+configurations that might contain conditional sections, loops and other features Velocity
+provides. See the Velocity documentation for more information on how to use this
+functionality.
+
+In case a variable cannot be resolved, it will simply not be replaced, but left as-is.
+This could lead to invalid or unparsable artifacts (configuration files) on your target!
+
+ACE will scan all configuration files and replace all known variables as soon as a new
+deployment is created. This means that for our example, both "target-1" and "target-2"
+will get a processed version of the configuration file, each with its own specific
+content. ACE also automatically versions these generated files, to aid downgrading
+software.
+
+
+
+[^1]: Once an artifact is uploaded to the OBR, it cannot be modified anymore. This is
+necessary in order to allow both software upgrades as downgrades and to ensure that
+everything you do is reproducible. One thing to note is that this is not compatible with
+the way that Maven handles snapshot versions. A snapshot can contain anything. In stead we
+usually use the version qualifier to append a timestamp in such scenarios.
+
+[^2]: This is a limitation of the current web UI. It is possible to create more
+sophisticated associations by using the REST API or the Gogo shell commands.
+
+[^3]: Do not forget to store your changes!
+
+[^4]: In fact any artifact can be considered as an template, but by default ACE only
+considers configuration files. 
+
+[^5]: In other UIs, such as the Gogo shell, you need to supply these tags manually.
+
+[^6]: Apache Velocity is an engine that can generate documents by combining a template
+with a context that contains variables. To learn more about it, visit the [Velocity
+website](http://velocity.apache.org/).
+
+[^7]: A complete list of recognised options can be found in
+[<tt>org.apache.ace.agent.AgentConstants</tt>](https://svn.apache.org/repos/asf/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java).
+
+
+*[OBR]: OSGi Bundle Repository
+
+*[DTAP]: Development, Testing, Acceptance and Production
+
+*[CI]: Continuous Integration
+

Propchange: ace/site/trunk/content/docs/user-guide.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/user-management-guide.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/user-management-guide.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/user-management-guide.mdtext (added)
+++ ace/site/trunk/content/docs/user-management-guide.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,109 @@
+Title: User Management Guide
+
+This article describes how to use ACE's user management. This article is meant for users
+who have at least a basic understanding of how ACE works and have it up and running. It
+describes which type of users are provided, and how to add, remove, view and edit users
+using the UI facility supplied with ACE.
+
+## Introduction
+
+ACE provides a standard set of users and roles in which they reside. This determines not
+only user permissions regarding releases, but also regarding user management. Using the
+built in user management system, users can be assigned to administrator or
+non-administrator roles. Currently the provided set of users only contains one
+administrator role, literally called 'Administrator'. When logged in as a user with this
+permission, one can perform CRUD (Create, Read, Update, Delete) operations on an ACE
+userbase. All other roles provide standard user functionality, which only allows a user to
+change his or her own password. Both roles also have a different management window as
+explained below.
+
+## Administrator view
+
+ACE supplies a default set of users, as seen
+[here](https://cwiki.apache.org/confluence/display/ACE/Permissions+and+roles#).
+Currently, the only administrator is the user 'd', with a password 'f'.
+
+When logged in as an administrator, a 'Manage Users' button appears in the top menu bar.
+When clicking this button, the following window appears:
+
+<a href="ace_user_management_admin_ui.png" target="_blank"><img src="ace_user_management_admin_ui.png" width="640px" title="Figure 1: The user management UI of ACE, seen from an administrator account." /></a>  
+**Figure 1**: The user management UI of ACE, seen from an administrator account. (click on image to see full size).
+
+The window is essentially divided into two columns, a table on the left side showing all
+registered users, and the selected user's specific data on the right side. Below the
+table, two buttons are displayed, a '+' and a '-' button. These buttons allow an
+administrator to add or remove users.
+
+The available user management actions are:
+
+1. Viewing all users
+2. Adding a new User
+3. Deleting an existing user
+4. Changing existing user data (Username, Password & Role)
+5. Changing your own password
+
+The below section describes how to perform these actions.
+
+**NOTE**: Allowing only a password change for an administrator is done on purpose. It
+should be noted that changing an active user's username should not be done, and a role
+change is very unsafe because a situation could occur where no administrators are left to
+manage the userbase.
+
+### Viewing all users
+
+This is rather self explanatory, but to view all users and their data, just click on any
+user in the table.
+
+### Adding a new user
+
+To add a new user, click the '+' button, the form then changes to input fields where the
+new user's details can be supplied as seen below.
+
+<a href="ace_user_management_newuser_ui.png" target="_blank"><img src="ace_user_management_newuser_ui.png" width="640px" title="Figure 2: The user management UI when adding a new user." /></a>  
+**Figure 2**: The user management UI when adding a new user. (click on image to see full size).
+
+The form supplies two fields, for a username and password, and a select box to choose a
+role.  After completing the form and selecting a role, clicking the 'Add' button adds the
+new user to ACE. Clicking the cancel button discards all input and cancels the addition of
+a new user.
+
+**NOTE**: Both fields and the selection of a role are mandatory!
+
+### Deleting an existing user
+
+Select the user to be deleted, and click the '-' button, located under the table.
+
+**NOTE**: An administrator cannot remove his or her own account!
+
+### Changing existing user data
+
+Click any user in the table who's data should be added. The form on the right then changes
+to input fields, allowing changes to be made. Click 'Apply' to save the changes made. When
+the changes should not be applied, just select another user, and the input is discarded.
+
+**NOTE**: Changes are only saved per user, and only when clicking the 'Apply' button.
+Batch editing is not possible!
+
+### Changing your own password
+
+As an administrator you can only change your own password. This is done by selecting your
+own username in the table, and then editing the password field on the right. Clicking
+'Apply' saves your new password, selecting another user discards the change.
+
+
+## Default User View
+
+All other users supplied with ACE are default users. Regarding user management, they're
+only allowed to change their own password.  When a logged in as a default user, a 'My
+Info' button appears in the top menu bar. When clicking this button, the following window
+appears:
+
+<a href="ace_user_management_user_ui.png" target="_blank"><img src="ace_user_management_user_ui.png" width="640px" title="Figure 3: The user management UI of ACE, seen from a default user's account." /></a>  
+**Figure 3**: The user management UI of ACE, seen from a default user's account. (click on image to see full size).
+
+### Changing a default user's password
+
+To change a default user's password, a user has to click the 'My Info' button. The desired
+password can then be inserted into the password field on the right. Clicking the 'Apply'
+button saves the change.
+

Propchange: ace/site/trunk/content/docs/user-management-guide.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/using-client-certificates.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/using-client-certificates.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/using-client-certificates.mdtext (added)
+++ ace/site/trunk/content/docs/using-client-certificates.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,134 @@
+Title: Using client certificate authentication
+
+_Using two-way SSL as authentication mechanism in ACE_
+
+Revision 1.0, last updated: May 2nd, 2012.
+
+[TOC]
+
+## Introduction
+
+One-way SSL authentication is used to let a client verify the identity of the server it is communicating with. The server itself does not verify the identity of the client. In two-way SSL authentication, a client first verifies the identity of the server after which the server identifies the client. This way, the identity of both the client and server can be established allowing a trust relation to be created.  
+This article describes how to configure the ACE server and the management agent(s) in such way that they use two-way SSL authentication. The remainder of this article assumes the reader has basic knowledge of the principles behind ACE, and has basic knowledge about creating and using certificates. For this article, the latest code of ACE (0.8.1-SNAPSHOT, rev.1332609) was used.
+
+
+## Outline
+
+As described in detail in [1], there are multiple communication paths that can (and need) to be secured. For two-way SSL authentication, several scenarios can be identified:
+
+1. only the communication between management agent and ACE server is secured by means of two-way SSL. This implies that there is only  a trust relation between management agent and ACE server, but the other clients that make use of the ACE server have no trust relation (i.e., they still communicate by means of one-way SSL or might not even use SSL at all);
+2. all the communication paths for the ACE server are secured by means of two-way SSL. This means that not only a trust relation exists between management agent and ACE server, but also between, for example, the web-UI and the ACE server or the REST-API and the ACE server[^1].
+
+In conclusion, we need to configure the trust relation between management agent and the ACE server, and, optionally, the trust relation between ACE server and other components.
+
+
+## Configuring two-way SSL authentication
+
+For two-way SSL authentication, you need two (or more) certificates. These can be issued either by an official external certificate authority (CA), or by means of a self-signed CA[^2].  
+The details on how to create a self-signed CA and certificates is well documented on many places on the Internet, and therefore goes beyond this article. Let's assume we've got the following:
+
+* a self-signed CA whose certificate is added to a Java keystore file, called <tt>truststore</tt>. This file will be used as *truststore* for both the management agent and the ACE server[^3];
+* a certificate (signed by our self-signed CA) for the management agent, available in a Java keystore file, called <tt>keystore-ma</tt>;
+* a certificate (signed by our self-signed CA) for the ACE server, available in a Java keystore file, called <tt>keystore-server</tt>.
+
+For the management agent, we need to add some system properties in order to let Java find and use the correct truststore and keystore (see also [2]):
+
+    :::sh
+    [localhost:/]$ java \
+      -Djavax.net.ssl.trustStore=/path/to/truststore \
+      -Djavax.net.ssl.trustStorePassword=secret \
+      -Djavax.net.ssl.keyStore=/path/to/keystore-ma \
+      -Djavax.net.ssl.keyStorePassword=secret \
+      -jar org.apache.ace.launcher-0.8.1-SNAPSHOT.jar \
+      discovery=https://10.0.1.16:8443 \
+      identification=MyTarget
+
+*Note to double check the paths to both files, as there will not be printed any error in case one of them points to an incorrect file!*
+
+For the ACE server, the configuration is provided by means of a property-file called <tt>platform.properties</tt>. Similar to the management agent, we should add some additional properties to it:
+
+    :::properties
+    -Dorg.osgi.service.http.port.secure=8443
+    -Dorg.apache.felix.https.enable=true
+    -Dorg.apache.felix.https.truststore=/path/to/truststore
+    -Dorg.apache.felix.https.truststore.password=secret
+    -Dorg.apache.felix.https.keystore=/path/to/keystore-server
+    -Dorg.apache.felix.https.keystore.password=secret
+    -Dorg.apache.felix.https.clientcertificate=needs
+
+This will not only ensure that the Jetty container inside ACE will obtain the correct keystore and truststore and start a listener on port <tt>8443</tt>, but also mandates that all clients **must** provide a certificate upon connecting (as denoted by the last property). Without this, clients that do not offer a certificate will simply be accepted as well, hence resulting in only one-way SSL authentication.  
+
+In order to secure all internal communication paths as well, we need to specify some additional properties in <tt>platform.properties</tt>:
+
+    :::properties
+    -Djavax.net.ssl.keyStore=/path/to/keystore-server
+    -Djavax.net.ssl.keyStorePassword=secret
+    -Djavax.net.ssl.trustStore=/path/to/truststore
+    -Djavax.net.ssl.trustStorePassword=secret
+
+This will ensure that all created HTTPS connections will use the mentioned keystore and truststore.  
+Note that in order to let **all** communication to use HTTPS, you need to modify the configuration files of ACE (as found in the <tt>conf</tt> directory) to mention this, for example, the <tt>org.apache.ace.webui.vaadin.cfg</tt> file would look like:
+
+    :::properties
+    # The endpoint of the Vaadin UI
+    org.apache.ace.server.servlet.endpoint = /ace
+    # Vaadin UI settings
+    ui.authentication.enabled = true
+    #ui.authentication.user.name = d
+    #ui.authentication.user.password = f
+    # ACE MS settings
+    ace.host = https://10.0.1.16:8443/
+    # OBR settings
+    obr.url = https://10.0.1.16:8443/obr/
+
+Alternatively, one could also provide a keystore with a *different* certificate for securing the internal communication as well. The only thing needed is to change the <tt>javax.net.ssl.keyStore</tt> property to let it point to another keystore file.
+
+
+### Using multiple different keystores
+
+So far, we only used the "standard" Java functionality to secure the communication paths with two-way SSL authentication. While this works for most use cases, one can think of more sophisticated scenario's in which multiple trust relations between different hosts have to be created. For example, when the OBR of ACE runs on a different host, secured with its own certificate. In order to support this use case, we can leverage the authentication framework of ACE by providing it configurations for all URLs that need their own keystore and/or truststore. In our OBR example, we could supply the following configuration to the <tt>ConnectionFactory</tt>:
+
+    :::properties
+    authentication.baseURL = https://10.0.1.17:8443/obr/
+    authentication.type = client_cert
+    # optional: use a specific keystore for this URL
+    authentication.keystore.file = /path/to/obr-keystore
+    authentication.keystore.storepass = secret
+    # optional: use a specific truststore for this URL
+    authentication.truststore.file = /path/to/obr-truststore
+    authentication.truststore.storepass = secret
+
+Different configurations can be supplied for different URLs, allowing many different trust relations to be established.
+
+Be sure that in order to let ACE correctly map certificates to users, you need to install the <tt>ClientCertAuthenticationProcessor</tt> as additional authentication processor! 
+
+
+## FAQ
+
+How should I name the certificates?
+: One should use the hostname of the calling side as common name (CN) of the certificate's distinguished name (DN), for example, <tt>CN=localhost</tt> or <tt>CN=10.0.1.16</tt>;
+
+How should I name the users that are authenticated through certificates?
+: The user should have the same name as the common name of the certificate, for example, <tt>localhost</tt> or <tt>10.0.1.16</tt>;
+
+I've enabled two-way SSL authentication, but it doesn't work!
+: There can be many reasons for this, like, can the truststore and keystore files be loaded (*no warnings or errors will be printed for this!*), or, is the name of the certificate matching the name of the host, or …? In general, if it doesn't work, one should enable SSL-debugging in Java by adding <tt>-Djavax.net.debug=ssl</tt> as system property. This will print *lots* of information about the keystore and truststore, the communication itself as well as detailed error messages. Also, the authentication parts in ACE provide lots of debugging information, logged at <tt>DEBUG</tt> level.
+
+What if my target runs on a machine with a dynamic IP address? Can I still use client certificates for authentication?
+: Not directly. Java uses the common name of the certificate and *assumes* this to be a valid, resolvable, hostname. If not, it will fail to accept the certificate as being valid. In the near future, ACE should [support this functionality](https://issues.apache.org/jira/browse/ACE-271).
+
+
+## References
+
+1. Developer documentation on [ACE Authentication](/docs/ace-authentication.html);
+2. [JSSE Reference Guide for JDK 5.0](http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Customization);
+
+
+## Notes
+
+[^1]: One can argue whether this is strictly necessary for **all** internal communication paths, as we will see later on, one can configure which paths use two-way SSL authentication and which paths do not.
+
+[^2]: Using a self-signed CA for two-way SSL authentication is not that much of a problem as one needs to make the certificate of the client available to the server, and the other way around. When both certificates are signed by the same CA, and both sides also trust this self-signed CA, the trust relation between client and server can be established as well.
+
+[^3]: Based on the certificate in the truststore, each side will be able to validate the certificate of the other side.
+

Propchange: ace/site/trunk/content/docs/using-client-certificates.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/writing-tests.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/writing-tests.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/writing-tests.mdtext (added)
+++ ace/site/trunk/content/docs/writing-tests.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,146 @@
+Title: Writing unit/integration tests
+
+This tutorial describes how to write unit and integration tests for ACE. For its unit tests, ACE relies on [TestNG](http://testng.org), while for the integration tests a combination of [BndTools](http://www.bndtools.org) and [JUnit](http://junit.org) is used.
+
+
+## Writing unit tests
+
+Unit tests test the behavior of classes or methods in complete isolation. In case this is not possible, due to dependencies on other classes, one can make use of a mocking framework such as [Mockito](http://code.google.com/p/mockito/) to replace those dependencies with stub implementations.
+
+Writing unit tests with TestNG is much like writing tests with JUnit: you create a class which contains methods annotated with the `@Test` annotation. Also, you can add methods that are run before or after each test or test case. One feature that is distinct to TestNG is the ability to group tests, making it possible to run only a certain group of tests instead of all[^1].
+
+All unit tests are placed in the same project they are testing, in a separate directory named `test`. This allows the tests to be compiled and run independently from the remaining code. It is good practice to have the same package structure for your tests and other code. 
+
+### Example
+
+Lets take a look at an excerpt from the unit test[^2] for `AuthenticationServiceImpl`:
+
+    :::java
+    public class AuthenticationServiceImplTest {
+       private LogService m_log;
+        
+       @BeforeMethod(alwaysRun = true)
+       public void setUp() {
+           m_log = Mockito.mock(LogService.class);
+       }
+
+       /**
+        * Tests that an exception is thrown if a null context is given.
+        */
+       @Test(groups = { "UNIT" }, expectedExceptions = IllegalArgumentException.class)
+       public void testAuthenticateFailsWithNullContext() {
+          new AuthenticationServiceImpl(m_log).authenticate((Object[]) null);
+       }
+
+       /**
+        * Tests that without any authentication processors, no authentication will take place.
+        */
+       @Test(groups = { "UNIT" })
+       public void testAuthenticateFailsWithoutAuthProcessors() {
+           Assert.assertNull(createAuthenticationService().authenticate("foo", "bar"), "Expected authentication to fail!");
+       }
+       
+       // ...
+    }
+
+This snippet shows us almost all important concepts for TestNG:
+
+* The <tt>@BeforeMethod</tt> annotation allows us to run a method before each individual test. In this 'setUp' method, we create a stub implementation of a <tt>LogService</tt>. **Note:** the `alwaysRun = true` is needed to ensure that this method is run, even though it does not belong to any test-group;
+* The method <tt>testAuthenticateFailsWithNullContext</tt> is annotated with the <tt>@Test</tt> annotation, and its parameters tell us two more things: it belongs to a group UNIT, and there's a failure to expect in the form of an 'IllegalArgumentException'. In this method, we instantiate the class-under-test (using the stub 'LogService') and invoke a method on it;
+* The last method (<tt>testAuthenticateFailsWithoutAuthProcessors</tt>) shows us how to make assertions on the results of methods. The <tt>Assert</tt> class of TestNG is almost equivalent to its equally named counterpart in JUnit with one difference: the failure message always comes last.
+
+To run the unit tests for a project, you simply go to the root directory of the project itself, and call:
+
+    :::sh
+    $ ant testng
+
+This will run the unit tests using TestNG. The output of the tests can be found in the <tt>test-output</tt> directory of your project. To run the test from Eclipse, you can right click on it, and select "Run As -> TestNG Test" from its context menu.
+
+
+## Writing integration tests
+
+In an integration test you test whether a small part of your system works as expected. For this, you need to set up an environment which resembles the situation in which the system is finally deployed. For ACE, this means that we need to set up an OSGi environment and a subset of the bundles we want to test. Fortunately, BndTools provides us with easy tooling to just do that with the use of [JUnit3](http://pub.admc.com/howtos/junit3x/)[^3].
+
+### Integration test principles
+
+To write a very basic (OSGi) integration test, you need to extend your test from <tt>junit.framework.TestCase</tt>. To access the bundle context of your test case, you can make use of some standard OSGi utility code:
+
+    :::java
+    public class MyIntegrationTest extends junit.framework.TestCase {
+        private volatile org.osgi.framework.BundleContext m_context;
+        
+        //...
+        
+        protected void setUp() throws Exception {
+            m_context = org.osgi.framework.FrameworkUtil.getBundle(getClass()).getBundleContext();
+        }
+    }
+
+With this in place, we can now make OSGi calls from our test methods.
+
+To ease the writing of integration tests, ACE provides a `IntegrationTestBase`[^4] helper class that provides you with some  boilerplate code commonly used in integration tests. Internally, it makes use of Felix Dependency Manager to control and manage the desired service dependencies. 
+
+### Example
+
+In this section, we'll describe how to write an integration test that makes use of a 'UserAdmin' service in its test method.
+
+The first we need to do is create our test class:
+
+    :::java
+    public class UserAdminIntegrationTest extends IntegrationTestBase {
+        private volatile org.osgi.service.useradmin.UserAdmin m_userAdmin;
+        
+        protected org.apache.felix.dm.Component[] getDependencies() {
+            return new org.apache.felix.dm.Component[] {
+                createComponent()
+                    .setImplementation(this)
+                    .add(createServiceDependency().setService(org.osgi.service.useradmin.UserAdmin.class).setRequired(true))
+            };
+        }
+        
+        // ...
+    }
+
+Having explained that our test depends upon the 'UserAdmin' service, and that its a required dependency, means that our test won't run if this service is not available[^5].
+
+Sometimes, you need to do some additional set up before or after the dependencies are resolved. For example, one might need to provision some configuration in order to get dependencies in the correct state, or wait until some other condition is met after all dependencies have been resolved. In order to do this, one can override the `before()` or `after()` methods[^6] in `IntegrationTestBase`.  
+For our simple integration test, however, we do not need such "advanced" set up.
+
+The only thing left is the actual test itself. As the 'UserAdmin' service is being tracked for us, we can simply direct use it in our test:
+
+    :::java
+    public class UserAdminIntegrationTest extends IntegrationTestBase {
+        // ...
+        
+        public void testUserAdminCreateGroupRoleOk() throws Exception {
+            org.osgi.service.useradmin.Role group = 
+                m_userAdmin.createRole("MyGroup", org.osgi.service.useradmin.Role.GROUP);
+            
+            Assert.assertNotNull(group);
+            Assert.assertEquals("MyGroup", group.getName());
+        }
+        
+        // ...
+    }
+
+That is it! The only thing left is to run the test, which is as simple as:
+
+    :::sh
+    $ ant test
+
+When running Eclipse, you can also run your integration test by right clicking on it, and selecting <tt>Run As -> OSGi JUnit Test</tt> from its context menu.
+
+
+## Notes
+
+[^1]: The consequence is that TestNG also allows you to write other kinds of tests than unit tests, like integration tests or performance tests. ACE does not make use of this kind of functionality, and only uses TestNG for its unit testing.
+
+[^2]: This test can be found in the `org.apache.ace.authentication` project.
+
+[^3]: The current version of BndTools still uses JUnit3, while there is some effort already to support JUnit4 as well, see: <https://github.com/bndtools/bnd/issues/156>.
+
+[^4]: This helper class can be found in the `org.apache.ace.test` project.
+
+[^5]: To be more precise: the test will wait a couple of seconds to allow all dependencies to be satisfied. If after this waiting period any dependency is not satisfied, the test will fail.
+
+[^6]: The naming of these methods could use a second thought, see also: <https://issues.apache.org/jira/browse/ACE-289>.

Propchange: ace/site/trunk/content/docs/writing-tests.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message