Behind the scenes

1.  Architecture
2.  Core Engine
        - Main Flow
        - Configuration Manager
        - Project Definition Processor
        - Type Definition Processor
        - Project Resolver
        - Project API
        - Dumpers Manager
        - Template Handlers Mechanism
3.  Component Types

4.  Template Handlers

5.  Dumpers

1. Architecture

Invicta's Core is a Java application.  For simple users, this application is the only relevant part of Invicta, used for creating a build script for their projects according to simple definition files they maintain.  For advanced developers or administrators, Invicta is a complete framework for the build environment of projects.

In order to make Invicta a general framework and not a specific application, its design is based on modularity and extensibility.  Invicta project includes some built-in components that use the framework for providing initial strong build environment methods, which can be extended.

 The architecture of the Invicta project fits the actions performed in the project: processing XML definition files, generating build script code, being modular and extensible and more.

The following diagram describes the content of the Invicta project:

The Core Engine, as its name suggests, is the main part of the Invicta project.  It is a Java application that processes Project Definition Files for creating Output Files, while using built-in Component Types, Template Handlers and Dumpers.  These built-in elements are only basic implementations; Invicta users can add their own Custom Types, Custom Handlers and Custom Dumpers.

Return to top

2. Core Engine

As previously explained, the Core Engine is a Java application that is the heart of the Invicta framework.  It is responsible for processing definition files in order to create output files.  It is also responsible for managing the various extensible modules.

The following diagram shows the internal modules of the Core Engine and their relations:

Return to top

Main Flow

The Main Flow module implements the processing flow of Invicta.  The Main Flow is called by the main class of the Invicta Application (Core Engine). As shown in the following diagram, it is responsible for receiving instructions (properties) from the user, checking execution necessity, processing and resolving project definition, and performing the dumping into output files.

Return to top

Configuration Manager

The Configuration Manager manages the execution configuration of the Core Engine.  The configuration includes Project and Type definition locations, Dumpers to use, Dumpers' parameters and more.

The configuration is stored in standard Java Properties files, which are simple key-value pairs files.  Properties values can also be read from the System Properties of the Java Virtual Machine.

The configuration manager also stores the execution configuration in a temporary output properties file, in order to enable checking whether re-running Invicta for creating output files is required during the next execution.  The output properties include current configuration values and modification timestamps of involved files (Project and Type definition, etc.).

The interface of the Configuration Manager includes 'get' methods for fetching a property value, 'put' methods for storing a value in a temporary output file and a 'forceRun' method for checking whether the current execution configuration differs from the previous one.

The following diagram shows the general structure of the Configuration Manager.

Return to top

Project Definition Processor

The Project Definition Processor is responsible for processing the XML files of a project definition by parsing the files, validating their syntax correctness, creating a representative data structure and resolving their logical and semantic structure.

1. In order to create a data structure of class instances (objects) that represents the XML definition files, Digester of Apache Jakarta-commons is used.

Invicta's Project Definition Processor contains a DTD file that defines a project definition structure, a 'Ruleset' file for Digester processing and a set of classes for constructing the data structure.

The classes that construct the data structure are shown in the following diagram:

 2. Resolving:

At this point, the Project Definition Processor should have the data structure of the project definition. The resolving action performs semantic validation of the data structure by adding logical information according to the definition information.

Resolving is performed on the project definition data structure itself.  This means that the same classes that were filled by the Digester are resolved themselves, and then add the required logical information.

The resolving procedure works recursively on the data structure objects.  Below is a short summary of the main resolving actions:

  • Checking that the components with the names in the 'depend' lines exist in the project.

  • Checking that there are no dependency cycles.

  • Checking that the inner dependencies between products are valid.

  • Preparing various lists and maps of components and products that the component depends on directly and indirectly (recursively).

As a result of the Project Definition Processor, a valid resolved Project Definition data structure is returned.

Return to top

Type Definition Processor

Types are defined in XML files that the Type Definition Processor reads, and from which it creates data structures accordingly.  Each component in the project definition specifies its type.  A Type Manager, which is part of the Type Definition Processor, performs the type loading and resolving.  In general, a type definition contains a template of the build script code for that component type and properties required for the code. 

Type Definition is similar to an Object Oriented class whose instance object is a component. In order to model the type definition, the following elements are used:

·        Targets

Similar to class methods.  Each target matches an ANT target, and therefore includes ANT target header (attributes) and a template of the build script of that target.  For example, a Jar component type includes the targets 'compile' and 'pack'.

As used in ANT, a target has dependency definition.  In Invicta, a target may depend on a different target in the same component (same type), or on specific targets of other components that this component depends on.

The templates of the targets are ANT build script code with special tags (for example: %{mytag}) that are replaced with logical strings as a result of calling Template Handlers.

·        Properties

Properties are constants or variables required by the build script template.  They are explicitly defined as part of the type definition, and are similar to data members of a Class.  There are 4 types of Properties:

A type definition may extend one or more existing types.  For example, an EJB type extends a JAR type, because it performs the same actions (has the same targets); additionally, it has an extra target for invoking an EJB compiler on the packed JAR file.

The elements that are involved in the hierarchy of types are properties and targets. A type may override or add to targets of its parent types.  The developer will have to solve conflicts resulting from multiple inheritances Invicta will notify on.

The child type may remove from its definition targets of a specific parent (for solving conflicts). The following modes will be possible for a target definition in a child type:

·        replace (default): overriding the parents' target.

·        rename: renaming the parents' target (adding the type name as a prefix) and creating a new target in the child that depends on the renamed targets.

·        addAfter/addBefore: add more build script code to the template of a parent's target.

·        addAfterAll/addBeforeAll: add the build script code to a template which is an aggregation of the parents' template.

The Type Definition Processor acts in a way similar to the Project Definition Processor: it parses the XML files and creates a data structure accordingly using the Digester.  The instances of data structure classes created and filled by the Digester are used to resolve the logical and semantic information of the type definition.  The resolving process of a type definition contains the following steps:

Return to top

Project Resolver

The Project Resolver manages the process of creating objects of the Project API according to given lists of Project Definition and Type Definition files.  The following diagram shows the order of operations the Project Resolver is responsible for:

A list of files is received from the Main Flow.  The Project Definition Processor is used for processing the files and creating a resolved ProjectDefinition data structure that includes ComponentDefinition objects.  These ComponentDefinition objects are processed by creating required TypeDefinition objects using the Type Definition Processor and making sure that each specific ComponentDefinition matches its TypeDefinition.

This matching is performed by creating TypedComponent objects as shown in the following diagram:

A TypedComponent object has both a ComponentDefinition object and a TypeDefinition object.  It acts as a delegate to both of them. TypedComponent is resolved by checking that the ComponentDefinition answers all requirements of its TypeDefinition (required properties, products, etc.).  The TypedComponent class implements the InvictaComponent interface, which represents a single component while hiding the internal structure of having separate components and type definitions.

After resolving the TypedComponent objects of the project, the Project Resolver creates an InvictaProjectImpl class.  This class is an implementation of the Project API of Invicta for the specific project.  It enables accessing the project-scope settings and components of the project.

Return to top

Project API

The Project API is a well-defined and easy-to-use interface for accessing the project definition objects (components, types, templates, products, etc.). This API is used by Dumpers and Template Handlers.  The API is both for internal Invicta modules and for extensions developed by advanced users of Invicta.

The API is a read-only view of the internal data structure objects that were created by the processor of the Core Engine. It contains the following Java interfaces and classes:

See the API documentation for more details.

Return to top

Dumpers Manager

The Dumpers Manager is responsible for finding the available enabled Dumpers, checking whether they should run, and executing them.  The Dumpers are classes that receive the Project API data structure and create output files accordingly.  The main dumper that is part of the Invicta Project is AntDumper – it creates an ANT build script.

The list of available dumpers is found using the service locator technology.  Multiple dumpers can be defined inside Invicta Project, or as extensions.

The Dumpers Manager module is also responsible for the dumping interfaces and classes.

A dumper must implement the Java interface: net.sf.invicta.InvictaDumper.  This interface has the following methods (among others):

Most dumpers share the same actions: writing output file, accessing Invicta properties, etc.  Therefore, an abstract class named InvictaBasicDumper should be extended by each new dumper.  This class implements the Dumper interface and should has the following abstract methods:

There are many built-in utility methods of InvictaBasicDumper. The main ones are:

See the API documentation for more details.

Return to top

Template Handlers Mechanism 

Component types contain templates of ANT build script code. These templates are free strings that the Invicta application is indifferent about.  In order to allow template strings of a type to include dynamic logical information of a specific component definition of a project, special 'tags' can be used. Example of such a tag:  %{product;jar}.

A tag invokes a call to a Template Handler.  In the example above, 'product' is the name of the Template Handler to call and 'jar' is a parameter for this handler.

Template Handlers are Java classes that are given the relevant InvictaComponent data structure and a set of parameters.  The Template Handlers return a result string, which is stored in the formatted template instead of the original tag.

The following is the definition syntax of a Template Handler tag:

Invicta project contains a few built-in Template Handlers. External users can create additional ones for preparing specific logical strings for their custom types.

The Template Handler Mechanism uses similar methods to those used by the Dumpers Manager. An interface net.sf.invicta.InvictaHandler is defined.  The Service Locator method is used for finding all available handlers (built-in or external).

A utility class named InvictaBasicHandler is extended by handlers. This class implements the InvictaHandler interface.  It contains a common implementation of a handler and some utility methods. The following methods should be overridden by an actual template handler:

The Template Handler Mechanism module contains a Template Formatter element that parses the template strings, looks for tags, invokes the required template handlers and formats the template according to the handlers' results.

Return to top

3. Component Types

Invicta includes a few built-in types. Future releases of Invicta should hopefully include more general types that are contributions of external developers.

The types are built according to the following guidelines:

 Invicta currently includes the following built-in types:

Each project will contain a special implicitly-defined component on which all components will depend.  This component will be of the type Global. This Global type will be responsible for the following:

Return to top

4. Template Handlers

The templates with the build script code of Invicta's built-in types requires some Template Handlers for fetching logical information from the data structure of the project. These handlers are built in a general way in order to enable external or future types use them.

The general Template Handlers return the following results (among others):

Return to top

5. Dumpers

Invicta Project contains the following built-in dumpers:

Invicta’s main dumper. Creates the ANT build script file using the templates of the component types according to the project definition.  Creates an implicit global component (Global type) that defines the 'general' and 'project' properties.  Creates properties and targets as are in the type definitions, while adding the component name as a prefix.  For example: a 'pack' target will be named 'mycomp.pack' for the 'mycomp' component.  Uses the properties concept of defining a general (or project) property that all specific properties point to by default.  This enables run-time customizability in two levels: per component, and globally.

Creates an Invicta project definition file of a project for distribution.  The original components of a project are converted into products of a single component definition that represents the distributed project.  Enables the distribution of the current project to be easily used in other projects.

Creates Javadoc-like HTML documentation of the project definition: components, dependencies, customizable properties, products, etc.

Return to top