Introduction

data/gvsig-orreili2.png

Note

The 2.0.0 version of gvSIG is still under development. It is important to keep this in mind because there may be changes that could affect the development, this guide, as well as other development documentation.

The gvSIG developers guide aims to provide developers who will work with gvSIG all the information necessary to compile, edit and further develop gvSIG.

The main topics covered in the guide are:


Maven

Introduction

Maven is a tool for the management and construction of software projects, especially for those based on Java. Maven has similar goals to make and ant, but with greater emphasis on the configuration by convention.

Maven is hosted by the Apache Software Foundation, and can be found at: http://maven.apache.org.

The main goals of Maven are:

Setting up a Maven project is done through the pom.xml file, which describes the main properties of the project and its dependencies with other modules and external components, as well as the Maven configuration to be applied. On the Maven website there is a reference guide on the pom.xml file format

Following the philosophy of configuration by convention, Maven defines a standard project structure:

project
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   `-- resources
    |                   
    `-- test
        |-- java
        `-- resources

If we follow this structure (but if it is different, it can be configured) with a basic configuration, we can perform the typical tasks of any Java project, already predefined in Maven:

Each task is determined by a Maven objective, with its name passed as a parameter. Example:

mvn install

There are two main versions of Maven: 1.0 and 2.0. The latter version is used in gvSIG.

Maven plugins

The functionality provided by Maven consists of a number of plugins that can be registered and configured for each project via the pom.xml.

The most commonly used plugins are registered and configured by default. If we use a different one for our project, or need to adapt the configuration of any existing ones, we can access the Maven plugins page.

For each plugin there is a user guide and documentation on the different parameters that are accepted by the plugin.

The Maven plugin page also provides links to other repositories of available plugins, mainly on codehaus.org and code.google.com.

Local and remote repositories

Maven manages two types of dependency repositories:

Local repository

Local disk location where Maven stores downloaded dependencies, so that they do not have to be downloaded every time. The structure corresponds to one folder per groupId (if the groupID contains points, a subfolder will be created for each element), a folder with the name of the artifactId and finally, a folder with the version.

The downloaded dependencies are stored in the folder of the version. For example, see the following dependency in a pom.xml:

<dependency>
    <groupId>org.gvsig</groupId>
        <artifactId>org.gvsig.tools</artifactId>
        <version>2.0-SNAPSHOT</version>
</dependency>

This will be stored in the local Maven repository with the path:

MAVEN_REPO/org/gvsig/org.gvsig.tools/2.0-SNAPSHOT/org.gvsig.tools-2.0-SNAPSHOT.jar

The files stored by Maven in the local repository can be of type:

When specifying a dependency for our project, Maven will by default download only the .jar file with the compiled classes. However, we can specify that the .jar with the source code and / or the javadoc must be downloaded as well.

Remote repositories

Remote repositories are dependency servers where Maven will look when it cannot find a dependency in the local repository.

Common remote repositories that can be accessed via standard protocols are HTTP/S, FTP, SSH, etc.

The Maven project itself has a dependency repository, accessible by HTTP, which is configured by default. In the pom.xml files you can add other external repositories, or repositories of your own project. For example, gvSIG has its own repository, which is registered by default for the gvSIG projects, in addition to the official repositories.

The gvSIG repository is currently accessible through HTTP as read-only, and through SCP in editing mode. This repository contains mainly the files that are generated by the gvSIG projects, as well as any external dependencies that are not available in the official repository.

Common tasks

The Maven Getting Started Guide describes the common tasks, among which:


Lessons learned

Disable unit tests

To launch Maven in a project and generate jars without launching the unit tests, add the following parameter:

-Dmaven.test.skip=true
Disable the updating of SNAPSHOT dependencies

When offline, or when you want to disable the updating of SNAPSHOT dependencies, add the -o parameter.

Debug unit tests

Sometimes we may need to debug the unit tests of a project, launched by Maven.

To do this, there is a parameter that causes Maven to wait for a remote debug connection on port 5005, before launching each test:

mvn -Dmaven.surefire.debug test

More information can be found in the documentation of the Maven debugging tests plugin

Memory usage

It is possible that for some of the tasks Maven launches, such as the compilation of Java classes, or the generation of Javadoc, the default memory settings will not be enough.

If this happens, an OutOfMemoryError message will appear in the console. We can increase the maximum memory allocation of the JVM by defining the MAVEN_OPTS variable that allows us to pass parameters to the JVM that launches Maven. For example:

Linux:

export MAVEN_OPTS=-Xmx256M

Windows:

set MAVEN_OPTS=-Xmx256M

When there is not enough space for the loading of classes (PermGenSpace), this will produce an error like:

[INFO] Compilation failure
Failure executing javac, but could not parse the error:

The system is out of resources.
Consult the following stack trace for details.
java.lang.OutOfMemoryError: PermGen space
      at java.lang.ClassLoader.defineClass1(Native Method)
      at java.lang.ClassLoader.defineClass(ClassLoader.java:621)

In this case, we will need to increase the PermGen space with the -XX:MaxPermSize parameter. For example:

Linux:

export MAVEN_OPTS=-Xmx256M -XX:MaxPermSize=64m

Windows:

set MAVEN_OPTS=-Xmx256M -XX:MaxPermSize=64m
Use Maven through a proxy

If you access the Internet through a proxy, you will need to configure Maven to download dependencies through this proxy, following the Configuring a proxy instructions at the Maven page.

Basically, this consists of including the corresponding configuration in the .m2/settings.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<settings 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/xsd/settings-1.0.0.xsd">

   ...

    <proxies>
        <proxy>
            <active>true</active>
            <protocol>http</protocol>
            <host>proxy.somewhere.com</host>
            <port>8080</port>
            <username>proxyuser</username>
            <password>somepassword</password>
            <nonProxyHosts>www.google.com|*.somewhere.com</nonProxyHosts>
        </proxy>
    </proxies>
</settings>

Available Maven resources


Create a gvSIG project

Before you start with developing a plugin

When developing a project for gvSIG 2.0 we must consider several things if we want it to have the official endorsement of gvSIG and become part of the official gvSIG release.

Project structure in gvSIG

Maven and Eclipse

One of the most interesting features of Maven is its ability to work with multi-module projects and the options for executing pre-defined targets to perform certain clearly defined tasks, such as code compilation and packaging.

Unfortunately, the current version of Eclipse does not include the necessary mechanisms to support multi-module projects, so that integration with the Maven mechanisms are complex and require the use of certain strategies to simulate such behavior.

Maven uses a Project Object Model (POM) to describe the software project to be built, the structure of the project and its sub-modules, their dependencies on other modules and external components, and the build order of the elements. Using these defined characteristics, you can get Eclipse to use the information in the POMs to simulate multi-module behavior.

Working with Maven in Eclipse

When working with Eclipse, as mentioned above, we will have to follow certain guidelines that will allow us to make use of the functionality Maven offers.

The first thing to note is the naming convention of the directories. The names applied to directories are not random, as they indicate the hierarchical structure of the project. Thus, the name of the parent project will be the name of the artifact_id, and its submodules will include the parent name (for example, if the parent project is org.gvsig.example, the submodule Example1 must be kept in the directory org.gvsig.example/org.gvsig.example.example1, and Example2 in org.gvsig.example/org.gvsig.example.example2. If Example1 has a submodule Example1a, it would be stored in org.gvsig.example/org.gvsig.example.example1/org.gvsig.example.example1a and so on). This gives the project a tree structure:

The parent nodes are not recognized as Java projects by Eclipse, because they are simply containers of the submodules. These projects contain the POM file with its definition and description of the submodules. In this way, you can launch commands at the parent module to run on that level and all its child nodes automatically (install, compile, etc.).

On the other hand, the child nodes (or leaves of the tree) are Java projects, with their usual project structure. These nodes can take advantage of the parent configuration (dependencies, properties, attributes, ...) if that parent is specified in the POM, simplifying its configuration.

Developing a gvSIG project

When we develop a gvSIG project there should be a strict separation between the API and the implementation of that API. To accomplish this, a basic template for gvSIG projects has been prepared which takes advantage of the Maven capabilities to manage multi-module projects. This template will guide us on how to organize the project, keeping strictly separated the logic of the extension from the user interface, and the API of the logic from its implementation, and the API of the interface from its implementation, in different Eclipse projects and separate jars.

The basic structure of a project will be:

Compared to gvSIG projects prior to the 2.0 version, this project structure would seem rather complex, but we will look into it with more detail.

The first thing to note is that the project is oriented as a multi-module SVN project compared to what we used to see in the development of gvSIG 1.X. On the one hand we have the development of the library and on the other, the extension(s) for gvSIG. This has been organized like this because normally the changes in the logic of our extension usually have a life cycle that is clearly separated from the integration into gvSIG. After development of the extension has been completed, it is easier to do the modifications from one gvSIG version to the next in the parts of the code that contains the integration with gvSIG, while the logic remains unchanged except for some bug corrections. To achieve this independence, the SVN repository is separated into two main groups:

In the library we will find the following:

And finally we come to the separation of some of these modules into API, SPI and implementation. This separation can be found in org.gvsig.example.lib and org.gvsig.example.swing.

Imagine that we are developing a network analysis extension for gvSIG. What projects would we be working with?

In principle, our project would not require special service providers. It would consist of the logic, the user interface, and the actual plugin for gvSIG. We would have the following projects:

Basically we would have these six projects, and each of them would generate its own jar, corresponding to the name of the project. Each of the projects will be will be located in its corresponding folder, and it is important that they have the correct name. This is because when you import these projects into Eclipse, we find that the folder tree is flattened; but thanks to the naming convention, these projects retain their consistency in our workspace.

Although it seems obvious, it should be pointed out which dependencies between those projects are acceptable. The implementation will depend on the API, but not vice versa. Also, our API should be concise and complete. Complete because the client of this API should not need to know the implementation in order to use it, and concise because the details of the implementation do not need to be exposed; the less details are exposed, the easier and safer the maintenance will be.

On the other hand, there is the user interface. This, whether the implementation or its API, should have no dependencies on the implementation of the library, or the logic. It should only depend on its API.

And finally, the test implementation and the extension can only depend on the API of the library and the user interface API.

It should also be noted that pom.xml files are found in each of the different folder. So there is a pom.xml in org.gvsig.example that allows us to interact with all the submodules of our project, and it contains the general configuration of the project. For example, through the pom.xml we can directly build the Eclipse projects for each of our modules. In turn, org.gvsig.example.swing and org.gvsig.example.lib have their own pom.xml files with their specific configuration. Finally, each of the final projects will have their own pom.xml file. Each of these pom.xml will be configured indicating the pom of the higher level folder as the parent pom to inherit the common configurations.

We have mentioned API several times. But what do we mean by API? How do we define it?

The question is not as obvious as it seems. When you ask several developers how they define an API module we can end up with very different answers. So, in gvSIG, how do we define an API? Normally, the API consists of a set of Java interfaces. There may be an abstract class that provides a default implementation for something that should be extended by the API user, but it never contains a class with its implementation. As usual, there are exceptions to this. By their nature, exceptions that trigger this API will be implemented in the API. This set of interfaces, packaged in a project and its jar, is the only dependency that the API user must depend on.

When using swing there will be differences. Swing lacks interfaces to handle graphic components, and therefore when it comes to defining the API of the swing part of our project, instead of using interfaces, we use abstract classes that extend the different swing components, adding abstract methods from our project domain. Usually there are abstract classes that extend JPanel, and these define the user interfaces associated with components of our project.

What does the implementation consist of?

Well, there we have a set of classes that implement the interfaces defined in the API. Normally there will be a manager which will serve as entry point to the functionality of our project and its configuration.

It is helpful to review the tools that org.gvsig.tools provides to manage the separation between API and implementation using the Library, Locators and Manager, and the tools that are available for the management of service providers, so that new projects will not need to reinvent each time how to implement these tools, and to harmonize their use throughout gvSIG.

We must also consider the recommendations when naming the classes and interfaces. The project structure described here is designed to follow a naming system such as described in the document nomenclature for classes and interfaces. So the API interfaces are named using meaningful names from the extension domain, without using any kind of prefix or suffix, while the classes that are found in the implementation project and which implement the API interfaces, are named by adding Default as a prefix to the name of the interface that they implement.

Before moving on to the creation of a gvSIG project according to the structure described above, it is recommended to review the documentation about org.gvsig.tools.service that describes in more detail the classes and interfaces to create, and how they are stored in a Maven subproject.

Creating our project

To work with our project need a gvSIG 2.0 installed. You must also install the Development project wizard addon, available through the addons manager (Tools > Addons manager).

What is going to offer this extension?

Mainly this extension will give us the option Create plugin. Using this utility, will allow the creation of maven projects, following the project structure described above, according to the custom options you choose to work with this installation of gvSIG.

This utility can be found in the menu Tools the option Development:

images/es/menu_gvsig_wizard-es.png

After accessing Create plugin option, the extension will show a wizard. This wizard will guide you to create a template from our maven project associated with this instance of gvSIG. As the most interesting points, note that the wizard will require that you enter the name of our project, group_id (default org.gvsig) and the location to generate the plugin.

You will have also to select the template to use, being able to select between a basic project with spatial support or a project to show fortune cookies. The first one is the recommended one.

If you select the second template, in addition we need indicate the type of plugin to be developed (for details see section FortuneCookie a _ plugin gvSIG). Finally, we will tell to wizard if we want to generate the extension for gvSIG or not.

images/es/create_maven_project-es.png

As a last step in the generation of our plugin, the tool will perform a prepare_workspace to leave our project ready. Perform maven tasks 'configure-eclipse-workspace','maven install' and 'maven eclipse:eclipse'.

images/es/configure_eclipse_workspace-es.png

Once created the project, closing gvSIG, start Eclipse and import the folder we created the project. To work with it, we import the parent project (org.gvsig.<project_name>) as all sub-modules (org.gvsig.<project_name>.lib.api, org.gvsig.<project_name>.lib.impl, org.gvsig.<project_name>.main and others according to the variant chosen).

images/es/eclipse_import-es.png

Once the project has been imported into Eclipse, we'll just create our plugin and boot normally, using the project build.xml file, and using the mvn-install target.

Finally, once developed our plugin, use the Pack plugin option of gvSIG installation. A utility to generate binaries from our plugin and will allow us to distribute it as a separate plugin or included in an existing gvSIG installable.

FortuneCookie, a gvSIG plugin

The FortuneCookie project is a very simple example plugin that aims to serve as a template to be followed by the developer when implementing their own plugins.

But, what advantages gives us the use of the diferents FortuneCookies projects? In principle, the most direct benefit is pretty obvious, since the fact of working on fully implemented a complete project that compiles and runs, can focus more on developing the code than in configuration tasks. And is that all FortuneCookies projects have declared their POM files with all the minimum dependences to run, and to establish relationships between them.

Therefore, to say that we have a project that will provide a number of basic, complete, compilable and run structures from which begin our development.

It presents several implementations that allow the developer show the highlights to be covered by your plugin depending on which option best suits the nature of the project. The variants presented are:

Should you require more information on any of the alternatives mentioned are advised to consult the document org.gvsig.tools.service

Moreover there is the option of GUI providers. This will be the option if, in addition to the above, support is required for the acquisition of user interfaces provided by vendors (currently under construction).


Trabajar con un proyecto

Preparar el espacio de trabajo en eclipse

Attention!

Pendiente

Tareas habituales con maven

Attention!

Pendiente

Versionado y publicación


Instalables en gvSIG

Introduction

Warning

This document is under construction.

Note

The utilities described in this document are designed and tested on a linux system. It is very likely to work on other systems, but it is easy to require some adjustments.

Installing gvSIG is a hybrid mechanism between a native installer, dependent on the platform we are running, and a java installer. The native installer, will install the gvSIG framework, preparing everything necessary in order to start a minimalist installation. The second, the java installer, is responsible for presenting the user the different packages available for installation, and installed.

The whole system is based on plugins installation packages, bundles and how they are installed.

We find:

A distribution of gvSIG is formed by the native installer, and a package set, gvspks, which added to the minimal installation a set of features we want to be in distribution.

They are available to those who need it, the mechanisms for creating gvSIG distributions with a custom packages sets, so that packages can be included as considered appropriate, thus creating distributions gvSIG specific or customized for different sectors.

Packages and packages set

Note

The utilities described in this document are designed and tested on a linux system. It is very likely to work on other systems, but it is easy to require some adjustments.

gvSIG supports several types of packages. These packages can install different types of accessories.

Currently there is only one type of package available, the container of plugins. From now on, herein, when referring to packet will always be talking about a package that installs a plugin.

gvSIG has a plugin that allows us to generate a package of a plug installed in that instance of gvSIG. This is a simple way that a developer can generate plugins packages from the same gvSIG on which it is developing.

The packet generation tool will include all information in the folder where live the plugin and also allow us to select other files inside the gvSIG installation, and include an ant script to be executed as post-installation script.

In addition to their own files that make up the plugin, we provide some basic metadata to identify the package. These are:

package required to operate.

In the plugin directory, there will be a * file * package.info with all this information, as well as a folder * install * the script ant to the post-installation called * install.xml *, and all this is packaged in a zip file with relative paths to the folder where you live in the plugin.

System Message: WARNING/2 (<string>, line 76); backlink

Inline emphasis start-string without end-string.

Keep in mind that this zip file should never contain folder entries, only files. So if you create a package by hand without using the tool provided by gvSIG we tell the command * zip * the appropriate option to not include them.

To create our own packages of our plugins, simply will be compressed in a zip file the folder where the plugin, making sure they exist, the file * package.info *, the * install folder * and the file * install / install.xml * if we need it.

System Message: WARNING/2 (<string>, line 86); backlink

Inline emphasis start-string without end-string.

Once we created our package we can install it using the installer is completed, or we can serve for inclusion in a gvSIG custom installation.

Here is an example of what would contain an install package. Let specifically see the plugin install support for ECW in gvSIG:

$ unzip -l gvSIG-desktop-2.0.0-org.gvsig.raster.ermapper.app-2.0.0-SNAPSHOT-23-devel-lin-x86-j1_5.gvspkg
Archive:  gvSIG-desktop-2.0.0-org.gvsig.raster.ermapper.app-2.0.0-SNAPSHOT-23-devel-lin-x86-j1_5.gvspkg
  Length     Date   Time    Name
 --------    ----   ----    ----
     4092  07-08-11 09:47   org.gvsig.raster.ermapper.app/lib/org.gvsig.raster.ermapper.app-2.0.0-SNAPSHOT.jar
    23391  07-08-11 09:47   org.gvsig.raster.ermapper.app/lib/org.gvsig.raster.ermapper.io-2.0.0-SNAPSHOT.jar
    28206  07-08-11 09:47   org.gvsig.raster.ermapper.app/lib/org.gvsig.jecw-2.0.0-SNAPSHOT.jar
   655809  07-08-11 09:47   org.gvsig.raster.ermapper.app/install/files/native/libNCSUtil.so.0
   430361  07-08-11 09:47   org.gvsig.raster.ermapper.app/install/files/native/libNCSCnet.so.0
    72242  07-08-11 09:47   org.gvsig.raster.ermapper.app/install/files/native/libNCSEcwC.so.0
  6120711  07-08-11 09:47   org.gvsig.raster.ermapper.app/install/files/native/libNCSEcw.so.0
    25851  07-08-11 09:47   org.gvsig.raster.ermapper.app/install/files/native/libjecw2.0.0.so
     1085  07-08-11 09:47   org.gvsig.raster.ermapper.app/install/install.xml
      313  07-08-11 09:47   org.gvsig.raster.ermapper.app/package.info
      363  07-08-11 09:47   org.gvsig.raster.ermapper.app/config.xml
 --------                   -------
  7362929                   12 files
$ 

We observed that we have the file package.info containing the description of the package:

#
#Fri Jul 08 09:47:35 CEST 2011
state=devel
name=Formats: Ecw format support
buildNumber=23
official=true
code=org.gvsig.raster.ermapper.app
operating-system=lin
architecture=x86
java-version=j1_5
gvSIG-version=2.0.0
version=2.0.0-SNAPSHOT
type=plugin
description=Ermapper data provider for gvSIG
model-version=1.0.0

In addition to this there is a folder install with a file Install.xml, which contains the post-installation script of the package and a folder files, a folder with the files that should go elsewhere gvSIG installation of the outside of the folder plugin. The post-install script takes care of copying the files native to where it belongs and in this case set the symlinks to work native libraries correctly installed:

<project name="org.gvsig.plugin1" default="main" basedir=".">
    <target name="main" depends="copy_files, link"/>
    <target name="copy_files">
        <copy todir="${gvsig_dir}">
            <fileset dir="./files" includes="**"/>
        </copy>
    </target>
    <target name="link" depends="checkos" if="linuxos">
        <exec executable="ln" >
            <arg value="-s"/>
            <arg value="${gvsig_dir}/native/libNCSCnet.so.0"/>
            <arg value="${gvsig_dir}/native/libNCSCnet.so"/>
        </exec>
        <exec executable="ln" >
            <arg value="-s"/>
            <arg value="${gvsig_dir}/native/libNCSEcwC.so.0"/>
            <arg value="${gvsig_dir}/native/libNCSEcwC.so"/>
        </exec>
        <exec executable="ln" >
            <arg value="-s"/>
            <arg value="${gvsig_dir}/native/libNCSEcw.so.0"/>
            <arg value="${gvsig_dir}/native/libNCSEcw.so"/>
        </exec>
        <exec executable="ln" >
            <arg value="-s"/>
            <arg value="${gvsig_dir}/native/libNCSUtil.so.0"/>
            <arg value="${gvsig_dir}/native/libNCSUtil.so"/>
        </exec>
    </target>
    <target name="checkos">
      <condition property="linuxos">
           <os family="unix" />
      </condition>
    </target>
</project>

The other files that appear are the plugin files themselves, their jars and resource files that may need such as the config.xml. In this case find:

Each plugin will provide the files needed for their operation.

Añadiendo nuestro paquete al repositorio de gvSIG

Una vez tenemos nuestro paquete, podemos entregarlo a nuestros usuarios o solicitar que sea incluido en el repositorio de paquetes de gvSIG, lo que es altamente recomendable, ya que de esta forma damos acceso a él a cualquier usuario que pueda estar interesado en él.

Para hacerlo tendremos que preparar un fichero índice con la extensión gvspki. Este fichero es en un zip similar al gvspkg pero que solo contendrá el fichero package.info con una ligera modificación. El fichero package.info, además de los datos descritos en el apartado anterior tendrá una entrada download-url, que será la URL desde la que poder descargar el paquete, gvspkg, por lo que antes de crear el fichero gvspki deberemos tener claro dónde vamos a alojar nuestro paquete, y una vez construido el fichero gvspki haremos llegar este a gvSIG para que se incluya en el repositorio.

Estos paquetes que solicitamos que se integren en el repositorio de gvSIG solo tienen que cumplir unas pequeñas reglas, principalmente de nombrado y versionado del paquete, no siendo preciso que sean desarrollos oficiales, siendo así una forma fácil de distribuir nuestros desarrollos entre los usuarios.

Puede encontrar más información sobre cómo puede solicitar incluir su paquete en el repositorio de gvSIG en Añadir un paquete al repositorio de paquetes de gvSIG.

Tal como vimos en el apartado Paquetes y conjuntos de paquetes vamos a ver ahora que es lo que contiene el fichero indice del paquete que añade el soporte para el formato ECW:

$ unzip -l gvSIG-desktop-2.0.0-org.gvsig.raster.ermapper.app-2.0.0-SNAPSHOT-23-devel-lin-x86-j1_5.gvspki
Archive:  gvSIG-desktop-2.0.0-org.gvsig.raster.ermapper.app-2.0.0-SNAPSHOT-23-devel-lin-x86-j1_5.gvspki
  Length     Date   Time    Name
 --------    ----   ----    ----
      505  07-08-11 09:47   org.gvsig.raster.ermapper.app/package.info
 --------                   -------
      505                   1 file
$

Como podemos obserbar unicamente tiene un archivo, y es el package.info. Este archivo cotendra:

#
#Fri Jul 08 09:47:36 CEST 2011
state=devel
name=Formats: Ecw format support
buildNumber=23
official=true
code=org.gvsig.raster.ermapper.app
download-url=http\://downloads.gvsig.org/download/gvSIG-desktop/pool/org.gvsig.raster.ermapper.app/gvSIG-desktop-2.0.0-org.gvsig.raster.ermapper.app-2.0.0-SNAPSHOT-23-devel-lin-x86-j1_5.gvspkg
operating-system=lin
architecture=x86
java-version=j1_5
gvSIG-version=2.0.0
version=2.0.0-SNAPSHOT
type=plugin
description=Ermapper data provider for gvSIG
model-version=1.0.0

Como vemos contiene la misma informacion que el package.info del fichero gvspkg mas una entrada indicando donde se encuentra este, download-url.

Generando nuestro conjunto de paquetes

Además de generar el paquete para nuestro plugin y solicitar que este sea añadido al repositorio de paquetes de gvSIG, puede resultarnos útil generar un conjunto de paquetes, gvspks con los distintos paquetes que estemos interesados en hacer llegar a nuestros usuarios, de forma que podamos dar un juego de funcionalidades personalizado.

Para eso bastara con crear un fichero zip en el que incluyamos los paquetes, gvspkg, o referencias a paquetes, gvspki que nos interese. Además dentro de este fichero zip podemos incluir información sobre qué paquetes queremos que estén marcados como recomendados o a instalar por defecto, cuando el usuario intente utilizarlo para instalarse nuevas funcionalidades desde él.

Para conseguir esto tendremos que crear un fichero de nombre "defaultPackages" en el que indicaremos, el nombre de los paquetes que queremos que sean marcados como paquetes recomendados o por defecto (uno por línea).

Cada línea tendrá el formato:

code[#versión[#build]]

De forma que presentará como paquete recomendado el que tenga el código de la versión y build que hayan sido indicados.

¿Qué queremos decir con paquete recomendado o marcado por defecto ?

Si durante el proceso de instalación de la aplicación se utiliza un gvspks en el que tenemos una entrada "defaultPackages", los paquetes que ahí se indiquen se marcarán como seleccionados de forma automática para que se instalen. Es una forma de ofrecer al usuario una instalación típica de paquetes en función de los paquetes disponibles.

Si, una vez instalada la aplicación, entramos en el instalador de complementos, este nos presentará en un color distinto los paquetes que se indiquen en el fichero "defaultPackages" del gvspks que se esté usando, de forma que el usuario pueda ser consciente de qué paquetes es recomendado que tenga instalados.

Hay que tener en cuenta que los paquetes que formen nuestro conjunto de paquetes pueden ser tanto paquetes en sí mismos como referencias a paquetes. Esto nos brinda la posibilidad de incluir de base una serie de funcionalidades, y referenciar a otras que se encuentren en la web y que se descargarán bajo demanda si el usuario solicita instalarlas.

Generando nuestra distribución de gvSIG

Una vez hemos sido capaces de crear el paquete para nuestro plugin, así como de crear un conjunto de paquetes que nos permita ofrecer a nuestros usuarios un juego de funcionalidades personalizado, nos sería útil empaquetar todo esto en un solo instalable de gvSIG para facilitar la descarga e instalación de nuestra distribución personalizada.

El mecanismo de instalación de gvSIG permite hacer esto. Para ello disponemos de utilidades para incluir un gvspkgs dentro del instalable nativo de gvSIG, de forma que este lo extraiga y utilice automáticamente durante el proceso de instalación, así como que lo deje preparado para ser usado por el instalador de complementos cuando concluya la instalación.

Además de incluir nuestro conjunto de paquetes, también nos permitirá añadir los instalables del jre a utilizar por la aplicación para que el usuario no precise descargarselo, en caso de que no disponga de la versión adecuada de el.

Tip

En algunas distribuciones del plugin org.gvsig.mkmvnproject no se ha empaquetado la herramienta gvspkg, puede descargarla directamente desde la web de gvSIG en la que se generan las distribuciones oficiales de gvSIG-desktop, dentro de la carpeta gvspkg.bin .

Dentro de la carpeta "scripts" del plugin org.gvsig.mkmvnproject, encontraremos:

Tip

Este script esta probado sobre S:O. Ubuntu, no teniendo claro que funcione sobre otra plataforma.

Antes de utilizar esta utilidad copiaremos la carpeta gvspkg.bin a nuestro home con el nombre ".gvspkg.bin", y nos aseguraremos que el script gvspkg está en el path.

Supongamos que tenemos los archivos:

Ejecutaremos el comando:

gvspkg mkinstall gvSIG-desktop-2.0.0-2030-devel-lin-x86-online.bin packages.gvspks

Esto nos creara el fichero gvSIG-desktop-2.0.0-2030-devel-lin-x86-custom.bin partiendo de nuestro instalador nativo e insertando en el nuestro packages.gvspks.

Si además queremos que se incluya el instalador del jre en el paquete, tendremos que conseguir primero el archivo de instalación correspondiente. Podemos descargarlo desde:

https://downloads.gvsig.org/download/gvsig-desktop/runtimes/java1.6/

Allí encontraremos:

- jre-6u26-linux-i586.bin
- jre-6u26-windows-i586-s.exe

Con los instalables del jre de java para windows y linux.

Así para generar nuestro instalable para linux ejecutariamos:

gvspkg mkinstall --jrelin=./jre-6u26-linux-i586.bin --addjrelin gvSIG-desktop-2.0.0-2030-devel-lin-x86-online.bin packages.gvspks

Y nos crearía gvSIG-desktop-2.0.0-2030-devel-lin-x86-custom-withjre.bin con el instalable del jre incluido y nuestro conjunto de paquetes personalizado.

Si quisiésemos generar los binarios para windows ejecutariamos:

gvspkg mkinstall --jrewin=./jre-6u26-windows-i586-s.exe --addjrewin gvSIG-desktop-2.0.0-2030-devel-win-x86-online.bin packages.gvspks

Generándose el fichero gvSIG-desktop-2.0.0-2030-devel-win-x86-custom-withjre.exe .

Warning

Esta pendiente añadir utilidades para cambiar la imagen del asistente de instalación así como el readme.

El asistente para empaquetar plugins

Para crear un paquete que contenga nuestro plugin la aplicacion gvSIG dispone de un asistente. Este asistente se encuentra en el menu Herramientas opcion Desarrollo, y requiere que el plugin ya se encuentre desplegado sobre su misma instancia de gvSIG. Vamos a ver cuales serian los pasos para generar un paquete de forma simple.

  1. Lo primero deberemos haber desplegado nuestro plugin sobre una instancia de gvSIG. Para la prueba vamos a generar un paquete de instalacion del plugin org.gvsig.centerviewpoint.

  2. Con el plugin desplegado ejecutaremos gvSIG y seleccionaremos la opcion de menu "Herramientas -> Debvelopment -> Crear paquete de instalacion de plugin".

    el-asistente-para-empaquetar-plugins-images/opcion-menu-crear-paquete-instalacion.png
  3. Ahora seleccionaremos el plugin org.gvsig.centerviewpoint de la lista de plugins que nos muestra el asistente.

    el-asistente-para-empaquetar-plugins-images/seleccionar-plugin-a-instalar-centerviewtopoint.png

    Seleccion de plugin

    y pulsaremos en siguiente.

  4. Ahora nos preguntara por los datos del paquete, que son los que describimos en el apartado Paquetes y conjuntos de paquetes.

    el-asistente-para-empaquetar-plugins-images/formulario-informacion-paquete-centerviewtopoint.png

    Datos del paquete

    Una vez rellenados los datos del paquete correctamente, pulsaremos en siguiente.

  5. Se nos preguntara si queremos habilitar el modo avanzado. En general contestaremos que no dejando el check sin marcar.

    Tip

    El modo avanzado no sera necesario siemrpe que todos los archivos que precise nuestro plugin para funcionar se encuentren en la propia carpeta del plugin, y mientras no necesitemos ejecutar codigo especifico mediante el script de post-instalacion.

    el-asistente-para-empaquetar-plugins-images/opciones-avanzadas-sin-marcar.png

    No activamos el modo avanzado.

    Le daremos siguiente para continuar con el asistente.

  6. Ahora se nos preguntara por el archivo de salida. Por defecto nos ofrecera un nombre para el paquete siguiendo las reglas de nombrado usadas en gvSIG y ofreciendonos como carpeta donde dejarlo la carpeta install de la instalacion de gvSIG. Asi mismo nos pregunta si queremos crear tambien el archivo indice gvspki. Si no se lo ponemos nos generara el fichero del paquete con el que podremos probar si se instala correctamente nuestro plugin o pasarselo a nuestros usuarios para que lo instalen.

    el-asistente-para-empaquetar-plugins-images/opciones-de-salida-sin-gvspki.png

    Archivos de salida sin indice

    Si queremos generar el fichero indice, gvspki, deberemos tener clara bajo que URL va a ser accesible el paquete, para introducir esta en nuesto indice. Asi marcariamos la opcion Crear indice, y en URL de descarga introduciriamos la url completa de donde descargar el fichero gvspkg que vamos a generar.

    el-asistente-para-empaquetar-plugins-images/opciones-de-salida-con-gvspki.png

    Archivos de salida con indice

    Una vez completado el formulario, daremos a siguiente para que se inicie la generacion de los ficheros del paquete.

En caso de que necesitemos incorporar en nuestro paquete archivos que estan fuera de la carpeta de nuestro plugin, o precisemos ejecutar codigo en el script de postinstalcion, en el momento que se nos presenta la opcion de si queremos habilitar el modo avanzado lo marcaremos.

Imaginemos que queremos generar un paquete para el plugin de GPE que precisa actualizar la libreria que lleva gvSIG de base kxml de la version 2.2.2 a la version 2.2.3. Para esto hariamos:

  1. Seleccionaremos el plugin de GPE

  2. Rellenaremos los datos relativos a este plugin.

  3. Marcariamos el check de habilitar el modo avanzado

    el-asistente-para-empaquetar-plugins-images/opciones-avanzadas-marcada.png

    Activamos el modo avanzado.

  4. Se nos presentara un arbol con la estructura de archivos de la instalacion de gvSIG para que seleccionemos los que precisemos. Iremos al directorio lib y seleccionaremos kxml2-2.2.2.jar

    Y pulsaremos en siguiente.

  5. Nos aparecera un panel con el script de post-instalacion por defecto, que se encarga de copiar los ficheros seleccionados al sitio adecuado.

Warning

TODO Continuar por aqui.

modificar el script para borrar el jar antiguo.

Librerías nativas

Attention!

Pendiente


Trabajar con el núcleo de gvSIG

Introducción

En este apartado se definen los pasos necesarios para poder preparar un espacio de trabajo con el núcleo de gvSIG 2.0, así como compilarlo y generar instalables del mismo.

Note

si vamos a desarrollar un nuevo plugin o librería para gvSIG, es preferible trabajar con un build o instalable, y recurrir a esta opción sólo si no disponemos de binarios o tenemos que hacer alguna modificación sobre los proyectos del propio core.


Compilar gvSIG


Initial configuration
Prerequisites

Before starting the installation process and configuration of all the elements needed to operate gvSIG, it is recommended to review the basic starting points that are needed to make the process of running the application a successful experience.

Once your computer meets these requirements, you can proceed with the installation of Maven and the creation of a workspace for gvSIG, since the other needed elements will be obtained by the built project of the application.

Initial configuration of Maven
Configuration of Maven

Apart from having a JDK installed, there is no need for any special configuration to begin working with Maven on gvSIG, because the gvSIG build project will install everything that is needed, including Maven.

However, if you want to install Maven yourself, you can download it from the project website and install it following the installation instructions. Keep in mind that Maven version 2.2.1 or higher is required for gvSIG.

You may also need to configure Maven to access the Internet through an HTTP proxy; the configuration is shown on the Maven installation page.

If you use the Maven installation included in the build project, you can find this in the Maven subfolder.

Note

Maven tests in gvSIG are done with the version included in the build project; with another Maven version the build of the project may not function properly.

Whether you install it yourself, or use the version provided by the build project, the subdirectory bin will contain the mvn script, that you can use when you are using Linux, Mac or any other Unix version, and the mvn.bat file for if you are using Windows. The most convenient way (to be able to run it from the console) is by adding the script to the run path (usually by adding the directory build/maven/bin to the PATH variable) so that you can run it from anywhere.

Later on we will describe some common tasks that can be used, either from a console or through the launchers from the External Tools menu in Eclipse.

Platform Configuration

gvSIG employs several native libraries, which are needed both for compilation and when running the application. Since they are native, you must use those that correspond to the platform on which you are compiling gvSIG.

A small configuration is needed to indicate the platform details to Maven, so that it can load the corresponding native libraries when compiling gvSIG. To do this, create a file .gvsig.platform.properties in your user's home directory with the following contents:

native_platform=linux
native_distribution=all
native_compiler=gcc4
native_arch=i386
native_libraryType=dynamic
export native_classifier=${native_platform}-${native_distribution}-${native_compiler}-${native_arch}-${native_libraryType}

The first 5 values are the important ones; their meaning is explained in the section on compiling native libraries.

The currently supported values, i.e. for which the native libraries are already compiled and available, are:

platform distribution compiler arch libraryType Comentarios
linux all gcc4 i386 dynamic Versión de 32 bits (equivalente en general a una Ubuntu-10.04)
win nt vs8 i386 dynamic Versión de 32 bits, compatible con windows XP, Vista y 7.
mac 10.5 gcc4 universal dynamic Plataforma todavía no disponible. Está en proceso de preparación y pueden variar alguno de los parámetros de la plataforma.

This configuration allows us to work directly with the configuration of the project that has been prepared to integrate Maven with Eclipse for gvSIG. If we invoke Maven from the command line, we will need to introduce these parameters to Maven in a different way. There are two options:

In addition to the platforms for which compiled native libraries are available, you can compile them by following the steps indicated in the document compilation of native libraries, and configure the parameters of the .gvsig.platform.properties file or the corresponding environment variable.

Write access to the Maven repository of gvSIG

Those who are responsible for publishing binaries, source code or gvSIG project documentation will need to configure Maven to have write access to the server which hosts the gvSIG Maven repository through SCP (SSH).

To do this you must configure the Maven settings.xml file with the necessary information to access the Maven repository of gvSIG. This file is located in the USER_HOME/.m2 /, where USER_HOME is the user's home directory, which depends on the operating system that you are using.

If this is the first time you use Maven 2, you will need to create this folder as well as the settings.xml file manually.

The file needs an entry to configure the access to the gvSIG server, which is indicated with its ID gvsig-repository. Since the access is through SSH, we need to include the username and password:

<?xml version="1.0" encoding="UTF-8"?>

<settings 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/xsd/settings-1.0.0.xsd">

    <servers>
        <server>
            <id>gvsig-repository</id>
            <username>[USUARIO]</username>
            <password>[CLAVE]</password>
            <filePermissions>666</filePermissions>
            <directoryPermissions>777</directoryPermissions>
        </server>
    </servers>
</settings>

Note

It is important to include the permission settings as indicated in the example above, because with every file that is uploaded, the user and group that uploaded it is specified to prevent other users from uploading modifications to the same file. In any case, a script on the OSOR server will update the file permissions on a daily basis.

If you do not want to show the password in the previous file, Maven can encrypt passwords from the latest versions onwards. To do this, follow the steps described in the Maven documentation on Password Encryption

To summarize, the steps are:

  1. Create a master password to encrypt the server passwords with this command:

    mvn --encrypt-master-password <clave-maestra>
    

    This will return the encrypted password, something like:

    {jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}
    
  2. Keep the master password in the file [USER HOME]/.m2/settings-security.xml (create the file if it doesn?t exist yet) with the following content:

    <settingsSecurity>
      <master>[CLAVE MAESTRA ENCRIPTADA]</master>
    </settingsSecurity>
    

    Using the example from the previous step, it would be something like this:

    <settingsSecurity>
      <master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}</master>
    </settingsSecurity>
    
  3. Encrypt the password to access the OSOR server:

    mvn --encrypt-password <clave>
    

    Which will return something like:

    {COQLCE6DU6GtcS5P=}
    
  4. Substitute the open password with the encrypted password in the [USER HOME]/.m2/settings.xml file:

    <server>
      <id>gvsig-repository</id>
      <username>[USUARIO]</username>
      <password>[CLAVE ENCRIPTADA]</password>
    </server>
    

    Following the previous example, it would result in something like this:

    <server>
      <id>gvsig-repository</id>
      <username>USER</username>
      <password>{COQLCE6DU6GtcS5P=}</password>
    </server>
    
How to create an Eclipse workspace for gvSIG

The steps for creating an Eclipse workspace for working with gvSIG are as follows:

  1. Start Eclipse and create a new workspace for gvSIG 2.0.

  2. Set the encoding used in gvSIG (ISO-8859-1):

    Window > Preferences: General > Workspace > Text file encoding = ISO-8859-1
    
  3. Set compatibility with Java 1.5 / 5.0 for all the projects (those which are compatible with Java ME CDC also have compatibility with Java 1.4):

    Window > Preferences > Java > Compiler > Compiler Compliance Level = 1.5 (or 5.0). 
    
  4. In Eclipse, register the subversion repository in which we will be working.

    It is possible to access to the subversion repository in two different ways:

    • Anonymous access with read only permission.
    • Access with read and write permission. For this you need a user in the infrastructure of gvSIG.

    The access URL is: https://devel.gvsig.org/svn/gvsig-desktop.

    Because a default installation of Eclipse does not provide support for subversion, it is necessary to install plugins for doing so:

    Note

    It is important to take note of the subversion plugin's version or configuration, and to ensure that is the same version as the subversion client in all cases: command line, Eclipse, etc. This is because with each new version of subversion the local format of the information changes, and backward compatibility is not maintained.

    In other words, if a subversion 1.6 client is used for doing a checkout or an update, an older version (1.5. 1.4, etc.) will not work correctly if it is used subsequently.

    If internet access is through a proxy, this must first be configured in Eclipse. To do this select the option:

    Window > Preferences > General > Network Connection 
    

    Proxy access to the network can be configured in the preferences window. It is possible to choose either System proxy configuration or to specify a Manual proxy configuration and then manually set the connection values.

    To register the choosen subversion repository, open exploring perspective of the subversion repository. If it is not available, it can be accessed from:

    Window > Open Perspective > Other : SVN Respository Exploring
    

    Once the perspective has been opened, it is possible to add the gvSIG repository from the SVN repositories view.

    From this point onwards project locations within the gvSIG subversion repository will be referred to. The repository has the usual subversion structure:

    • trunk: latest development version.
    • tags: closed versions and builds, for which a tag is generated.
    • branches: development branches.

    From here on, the subversion paths will show [Repository]/[VERSION] rather than indicating the repository, and if trunk, tags/v2_0_0_Build_2007, etc. Keep in mind that at the time of writing, version 2.0 is being developed in branches/v2_0_0_prep branch, which is where projects can currently be downloaded, even though they will in future be moved to the trunk.

  5. Download the build project.

    To do this, one must apply a checkout from the source repository. From the SVN Repository view, navigate to:

    [VERSION] (ej: branches/v2_0_0_prep)
    

    Select the build folder and apply a checkout by clicking on the left button on the folder and selecting the appropriate option. In the checkout dialog, accept the default options and click Finish.

    Once finished, the project will be available in the Java or Resource perspective.

    Alternatively, the following command can be executed from the console:

    svn co https://devel.gvsig.org/svn/gvsig-desktop/branches/v2_0_0_prep/build
    

    As with Eclipse, if internet access is through a proxy, the subversion client must be configured to connect to the server through the proxy. The configuration instructions are available in the FAQ of the official subversion web, or in the section on configuration of servers in the subversion book.

    Once the build project has been downloaded from the console, it can be imported into Eclipse.

  6. Open the Ant view by selecting the following menu option:

    Window > Show view > ant
    
  7. Install the basic configuration of Maven for gvSIG.

    The build project contains the basic Maven configuration for all the gvSIG projects in a general pom.xml, as well as specific configurations for each project type:

    • library: build/libraries-pom/pom.xml
    • native library: build/libraries-jni-pom/pom.xml
    • extension: build/extension-pom/pom.xml

    Initially, and each time that any of these files are changed, these files must be installed in the local repository of Maven. There are two ways of doing this:

    • Eclipse: Add the build.xml file in the build project to the open Ant view. A number of Ant objectives will appear, amongst which is mvn-install. This is launched by double clicking or by selecting the required objective and clicking the icon.

    • Console: from the build folder, launch:

      mvn install
      
  8. Configure Eclipse to correctly load the projects generated from Maven.

    To do this, from the Ant view invoke the objective: mvn-configure-eclipse-workspace. This will automatically create an environment variable in Eclipse, which is used to refer to the jars of the dependences managed through Maven. It will ask for the location of the workspace, which usually will be the default.

    Alternately, from the console it is possible to use Maven as follows:

    mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo
    

    Then close Eclipse and open it again.

  9. Check that the M2_REPO variable is correctly defined in Eclipse. From the menu select:

    Window > Preferences : Java > Build Path > Classpath Variables 
    

    The variable value must be something like (replace [USER_HOME] for the user's folder, according to the Operating System):

    M2_REPO = [USER_HOME]/.m2/repository
    
  10. To the Ant view add the build.xml file from the group of projects that you are going to work on. Groups of Projects will be explained in detail at a later stage but for now think of them as lists of projects (libraries and extensions) which are in the build/projects folder.

    If the intention is to download the projects of a complete gvSIG, add the following file to the Ant view:

    build/projects/gvsig-standard/build.xml
    
  11. Start downloading the projects.

    To do this, from the Ant view invoke the objective: svn.checkout.all. A form opens where it is possible to select:

    • The URL of the subversion server, which depends on whether public access with read only rights, or access with read and write rights (which requires a user name and password) is preferred.
    • The SVNKit version to use. It is necessary to check that this is the same as that of the subversion support plugin installed in Eclipse. As in the previous cases, accessing the Internet through a proxy requires the access for the SVNKIT library to be configured. In fact, this library reads the same configuration as the native client of subversion, whose configuration is described in Download the build project. More information is available in the users guide of SVNKIT
    • User name and password to access subversion, if applicable.
    • Whether to automatically create the Eclipse project configuration once the download is complete. If this option is deactivated, the Eclipse projects have to be generated either from the mvn eclipse option on the External tools menu or from the console with the instruction: mvn -P eclipse-project.

    Alternatively, it is possible to invoke this Ant objective from the console, or to do a checkout of each project, from Eclipse or from the console. In the latter case, it will be also be necessary to generate the Eclipse project configuration.

  12. Import the projects into Eclipse. Once the previous step is complete the projects can be imported into Eclipse by choosing the following menu option:

    File > Import > General > Existing projects into workspace
    

    Click on Select root directory and select the workspace directory. The list showing the projects to import will appear and, after accepting them, Eclipse will proceed to compile the imported projects.

    Note

    when importing the projects, check that the option Copy projects into workspace is deactivated, because the intention is to use the same projects which have been downloaded directly.

  13. The eclipse plugin for maven does not link eclipse projects between them until they are already imported into the eclipse workspace, so we must regenerate the projects eclipse configuration.

    From the Ant view, select the mvn-eclipse-eclipse goal. Once the process has finished, select all projects and refresh them (F5 o press the right button and select the Refresh option).

  14. Finally, the eclipse plugin for maven generates the eclipse plugin configuration only for the java projects, that is, the projects which have java code. As there are some multimodule projects, only the eclipse project configuration of the submodule final children will be generated. As an example, the org.gvsig.annotation project has the following structure:

    org.gvsig.annotation
    ??? org.gvsig.annotation.lib
    ?   ??? org.gvsig.annotation.lib.api
    ?   ??? org.gvsig.annotation.lib.impl
    ??? org.gvsig.annotation.main
    ???? org.gvsig.annotation.swing
        ??? org.gvsig.annotation.swing.api
        ??? org.gvsig.annotation.swing.impl
    

    If we look at the current imported projects, we will find only the following ones:

    • org.gvsig.annotation.lib.api
    • org.gvsig.annotation.lib.impl
    • org.gvsig.annotation.main
    • org.gvsig.annotation.swing.api
    • org.gvsig.annotation.swing.impl

    We need to have, at least, each root parent project to be able to update everything when synchronizing from subversion, as well as allowing us to perform actions to all the submodules of the same project.

    There is only one way that we are aware of to be able to import those root parent projects:

    • Select the eclipse menu: File > New > Project....

    • In the dialog, select the option: General > Project and click Next

    • In the following dialog, fill in the following form fields:

      • Project name: The name of the parent root project to import. Ex: org.gvsig.annotation.
      • Use default location: Select this option.

      Finally click Finish and the project will be available in eclipse. Its not a java project, so we must not edit java files from it, but through the subprojects. Those root projects will be used only to perform maven actions to all the submodules or to synchronize from subversion.

    Those are the projects to import that way:

    • org.gvsig.annotation
    • org.gvsig.annotation.app
    • org.gvsig.app.document.layout.app
    • org.gvsig.app.document.table.app
    • org.gvsig.exportto
    • org.gvsig.exportto.app
    • org.gvsig.geometrymeasurement.app
    • org.gvsig.hyperlink.app
    • org.gvsig.installer
    • org.gvsig.installer.app
    • org.gvsig.newlayer
    • org.gvsig.newlayer.app
    • org.gvsig.personaldb
    • org.gvsig.selectiontools.app
    • org.gvsig.symbology
    • org.gvsig.symbology.app

Note

This final step is certainly cumbersome, but we haven't found a more authomatic way to perform it. We had already tried to commit to subversion the .project files of those root projects but then, in the initial eclipse import of all the gvSIG projects, only the root projects are included. You had to import then each child submodule one by one, which is still worse. The maven plugin for eclipse could be used to solve that problem, but is has other problems still to be solved.

Integración con eclipse

En el momento de preparar esta guía, Eclipse no lleva soporte de forma oficial para maven. Existen algunos plugins disponibles que permiten integrar maven en eclipse, aunque parece que todavía no son completamente funcionales. Uno de ellos (Q4E), de hecho, está en proceso de ser incorporado a eclipse de forma oficial, bajo el nombre Eclipse IAM, pero todavía no ha sido liberado.

Por no ligarnos a un plugin no oficial de eclipse, por ahora se va a emplear una integración básica de eclipse con maven, que permita en cierta forma compartir la configuración de proyecto de maven con eclipse, así como invocar a maven desde el propio eclipse.

Preparar el workspace para trabajar con maven

Note

si nos hemos descargado el workspace siguiendo las instrucciones del documento Cómo montar un workspace con Eclipse (ver documentos relacionados), ya tendremos el workspace preparado.

Para que el eclipse sea capaz de encontrar el repositorio de maven es necesario configurar la variable en el workspace. Esto lo podemos hacer de forma sencilla empleando el plugin eclipse de maven, con el objetivo:

mvn configure eclipse workspace

Al hacerlo desde eclipse, ya tomará por defecto el valor del path del workspace sobre el que estamos trabajando.

Si queremos lanzarlo desde consola, la instrucción es:

mvn eclipse:add-maven-repo -Declipse.workspace=WORKSPACE_PATH

En 'WORKSPACE_PATH' especificaremos la ruta absoluta al workspace.

Generación de proyectos de eclipse desde maven

Note

los proyectos generados desde eclipse con los objetivos create library y create extension ya generan también automáticamente el proyecto de eclipse.

Si tenemos un proyecto configurado con maven, no es necesario crear manualmente el proyecto de eclipse, ya que maven puede generarlo por nosotros. Para ello bastará con usar el siguiente objetivo:

mvn eclipse

Desde consola, la instrucción equivalente es:

mvn -P eclipse-project

Note

La forma habitual de generar un proyecto de eclipse desde maven es emplear la instrucción mvn eclipse:eclipse. Sin embargo, para algunos proyectos, como los que generan varios jars en los que se incluyen clases de tipo Library, el plugin de maven que genera los proyectos de eclipse no es capaz de generar toda la configuración necesaria, por lo que se ha creado un perfil desde el que se invoca al plugin de eclipse y, además, añade el resto de configuración necesaria. Si en algún caso se creara el proyecto de eclipse sin usar el perfil eclipse-project, el único problema es que los tests unitarios que empleen el mecanismo de inicialización automática de librerías no funcionaran si los lanzamos desde eclipse.

Esto generará los archivos de eclipse necesarios, que nos permitirán importar el proyecto desde eclipse, con todas las dependencias, directorios de fuentes, etc. ya definidos.

Si ya existe el proyecto de eclipse, el objetivo anterior no lo sobreescribe, para ello tenemos que emplear antes el objetivo:

mvn eclipse clean

O desde consola:

mvn eclipse:clean

En los proyectos de gvSIG, está configurado de forma que, además de descargar y enlazar las dependencias binarias (jars con clases) en el proyecto de eclipse, maven intentará descargar también los jars con los fuentes y los javadocs correspondientes, enlazándolos a cada jar de binarios. Esto nos permitirá ver fácilmente la documentación y el código fuente de las dependencias de nuestros proyectos.

Por otro lado, si generamos los proyectos de eclipse para un grupo de proyectos, maven nos enlazará las dependencias entre los proyectos del grupo a nivel de proyecto, en vez de a nivel de archivo jar.

Esto permite que los proyectos de eclipse no se suban al repositorio de fuentes de gvSIG, ya que se pueden generar fácilmente para un proyecto o conjunto de proyectos.

Cómo invocar maven desde eclipse

Para facilitar el uso de maven desde eclipse, se han preparado una serie de lanzadores con los objetivos más usados en los proyectos con maven.

Dichos lanzadores están definidos dentro del proyecto build, por lo que una vez incluido este proyecto en nuestro workspace de eclipse, los tendremos disponibles automáticamente.

Para lanzar cualquiera de ellos deberemos tener abierto el proyecto sobre el que queremos trabajar, y seleccionar el lanzador correspondiente desde la opción de Herramientas externas (External Tools).

Errores habituales
Plataformas soportadas
platform distribution compiler arch libraryType Comentarios
linux all gcc4 i386 dynamic Versión de 32 bits (equivalente en general a una Ubuntu-10.04)
win nt vs8 i386 dynamic Versión de 32 bits, compatible con windows XP, Vista y 7.
mac 10.5 gcc4 universal dynamic Plataforma todavía no disponible. Está en proceso de preparación y pueden variar alguno de los parámetros de la plataforma.
Compilar un grupo de proyectos

Maven permite trabajar con lo que llama multimódulos o una estructura multiproyecto. Esto nos permite lanzar una orden de maven sobre un grupo o jerarquía de proyectos, desde una única llamada a éste. Para ello tenemos un pom.xml que hace referencia a un conjunto de proyectos de maven.

La estructura habitual consiste en tener una organización en árbol de proyectos, pero también podemos tener una estructura plana, en el que el proyecto que contiene el pom.xml en el que se hace referencia al resto de proyectos se encuentra a la misma altura que estos.

En gvSIG la estructura de proyectos que hay en el repositorio de fuentes no está pensada para ser descargada tal cuál, sino que se debe descargar proyecto a proyecto, con lo que tenemos una lista de proyectos todos dentro del mismo directorio.

Aunque en un futuro se podría migrar a una estructura multimódulo de proyectos, por ahora la vamos a simular mediante grupos de proyectos dentro del directorio build de gvSIG. Dentro de este, en el subdirectorio projects se han creado una serie de directorios, cada uno de los cuáles hace referencia a un grupo de proyectos:

build
`-projects
  |-gvsig-base
  |-gvsig-cdc-compat
  |-gvsig-coverage
  |-gvsig-coverage-base
  ...

Si accedemos a uno de estos directorios, vemos que contienen un archivo pom.xml, el cuál hace referencia a un conjunto concreto de proyectos. Así, si desde aquí usamos maven, la orden se lanzará automáticamente para cada uno de los proyectos referenciados.

Este mecanismo nos permite, de forma cómoda, realizar operaciones de compilación e instalación sobre un conjunto de proyectos, o incluso generar un build de gvSIG completo.

El criterio para definir los grupos ha sido el de unir proyectos sobre una misma funcionalidad o cuyo desarrollo se realice de forma conjunta. Además, aprovechando que un pom.xml puede hacer referencia, tanto a proyectos sueltos, como a otros conjuntos de proyectos, se ha definido un grupo para la generación de un build completo con la unión de otros grupos.

Por ejemplo, si estamos desarrollando sobre GPE, actualmente está dividido en los siguientes proyectos:

Si queremos compilarlos todos a la vez, bastará con ir al directorio gvsig-gpe y realizar la orden:

mvn compile

Esto realizará la compilación de los distintos proyectos de GPE, uno tras otro. Si, en alguno de ellos, se produce un error de compilación, el proceso se detendrá y no seguirá en los siguientes.

Dentro de cada uno de estos directorios de grupos de proyectos, tenemos también un script de utilidad que nos permite hacer un checkout de forma rápida de los proyectos del grupo. Por ejemplo, si queremos desarrollar sobre GPE, bastará con hacer un checkout inicial del directorio build y, a continuación, desde el subdirectorio projects/gvsig-gpe llamar al script svnco.sh, que se encargará de hacer un checkout de los proyectos de GPE.

Compilar un gvSIG completo

Aprovechando el mecanismo anterior de los grupos de proyectos, se han definido dos grupos que permiten trabajar con todos los proyectos de un build de gvSIG:

A partir de ahora consideraremos que vamos a trabajar con la versión del build estándar.

Para compilar todo gvSIG usaremos maven, bien desde eclipse, bien desde consola. La forma habitual será mediante el objetivo install:

Esto compilará todos los proyectos e instalará todas las extensiones y sus archivos en la ubicación correspondiente.

Arrancar gvSIG

Los builds de gvSIG desde maven están configurados para ser generados en el directorio build/product, en vez de dentro del proyecto de _fwAndami como se hacía con ant.

Podemos lanzar gvSIG de dos formas distintas:

Librerías nativas

Tabla de Contenidos

Introducción

Algunas de las extensiones de gvSIG, necesitan el uso de librerías nativas para su funcionamiento. El problema existente con este tipo de librerías es que es necesario tenerlas compiladas para cada plataforma y sistema donde se quiera hacer uso de gvSIG.

Para facilitar la distribución y construcción de estas librerías se ha integrado con el actual sistema de construcción basado en maven. Para ello se ha añadido funcionalidad a las fases de construcción. Es necesario entender que cuando se trabaja con librerías nativas existen tres partes claramente diferenciadas:

Uso de librerias nativas ya compiladas

Un desarrollador java que trabaje sobre una plataforma para la cual existan librerías nativas ya compiladas no tendrá que preocuparse de hacer nada especial para el uso de estas. Estas nativas aparecen como dependencias de otras librerías java y serán descargadas a $HOME/.m2 cuando hagamos un mvn install del proyecto java que las incluya. Posteriormente, cuando se hace un mvn install -Pinstall-extensions de la extensión que hace uso de las librerías java, los binarios nativos de los cuales se dependa serán instalados en el directorio .depman de nuestro ?home?.

Actualmente para que se reconozca la plataforma en la que estamos se ha de indicar explícitamente.

El proyecto org.gvsig.maven.base contiene un directorio org.gvsig.maven.base.pom con un fichero pom.xml donde podemos cambiar la plataforma, distribución, compilador y arquitectura sobre la que estamos funcionando en caso de que no nos vaya bien la que viene por defecto. Una vez hecho esto deberemos ir al raiz del proyecto y ejecutar mvn install para instalar los cambios en nuestro repositorio local.

Este proyecto puede descargarse de: https://svn.forge.osor.eu/svn/gvsig-tools

Compilación de las Librerías Nativas

Con esta pequeña introducción a la problemática de las librerías nativas a continuación se explica cómo compilar las librerías que actualmente se encuentras migradas a maven.

Requerimientos

Para cada sistema, ya no sólo es necesario tener instalado el JDK y por supuesto maven (aunque se puede hacer uso del maven que se distribuyen dentro del directorio build). Es necesario descargarse los programas necesarios para compilar en cada sistema.

Para todos los sistemas es necesario descargarse e instalar CMake: http://www.cmake.org.

  • Windows:
    • Visual Studio 2005 (vs8)
    • CMake
  • Linux(Debian o Ubuntu):
    • apt-get install build-essential
    • apt-get install cmake
  • Mac:
    • Developer Tools distribuidas en el propio CD de MacOS X.
    • CMake

Es necesario tener un workspace al menos con los siguientes proyectos:

  • build
  • org.gvsig.maven.base
  • libjni-xxxx (todos los que queramos compilar)
Compilar
  • Compilar Java: Es tan sencillo como lanzar la instrucción del directorio de la librería ( o el target ant asociado ). Automáticamente se descargará la librería JNI de la que depende y las librerías externas de las que depende desde el repositorio de maven:

    Linux: mvn install -Dnative-distribution="all"
    Windows y Mac: mvn install 
    
  • Compilar Java + JNI: Al igual que antes se compilará la parte Java y en este caso se compilará también la parte JNI, las dependencias externas se descargarán desde el repositorio de maven:

    Linux: mvn install -Dnative-distribution="all" -Pjni-devel
    Windows y Mac: mvn install -Pjni-devel
    
Consideraciones a tener en cuenta
  • Las librerías nativas necesitan siempre del parámetro -Dnative-distribution={mi distribución linux}. La razón por la que es necesario es que según que distribución para la que se haya compilado puede que requiera unas dependencias externas u otras, o incluso pueden ocurrir problemas de compatibilidad binaria con las librerías del sistema.

  • Si una distribución linux no está soportada o no se han subido al repositorio de maven las dependencias, entonces fallará la búsqueda de dependencias y dará un error, es por tanto responsabilidad de los mantenedores de las librerías subir esas dependencias para las distribuciones oficiales de gvSIG.

  • En Windows, se considera que el compilador por defecto es el Visual Studio 2005 (vs8), por tanto para poder lanzar la compilación es necesario abrir una Consola de Visual Studio 2005" para que se definan correctamente las variables de entorno del compilador.

  • Aunque el sistema se lanza y se maneja con Maven, internamente hace uso de CMake, una herramienta multiplataforma que permite la compilación y generación de proyectos de compilación.

  • Para poder subir ficheros al repositorio hay que tener configurado el fichero settings.xml de nuestro repositorio local ($HOME/.m2) con los valores correctos para el servidor. Un ejemplo de este fichero podría ser el siguiente:

    <?xml version="1.0" encoding="UTF-8"?> 
     <settings 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/xsd/settings-1.0.0.xsd"> 
       <servers>
        <server> 
         <id>gvsig-repository</id> 
         <username>nbrodin</username> 
         <password></password> 
        </server> 
       </servers> 
     </settings>
    
Compilación en linux

Desde una consola del sistema debemos tener definida la variable JAVA_HOME. Para ello escribimos:

export JAVA_HOME=$javasdk

donde $javasdk es nuestra ruta local al JSDK de java. Actualmente la versión utilizada es la 1.6.0

La instrucción de compilación desde dentro del proyecto libjni-xxxx es la siguiente:

mvn install -Dnative-arch=$arch -Dnative-distribution=$distri -Pjni-devel -Dmaven.test.skip

donde $arch puede tomar los valores ?X86_64?, ?i386?, ?universal? y $distri puede ser ?nt?, "all", ?Ubuntu-9.10?, ?10.5?, etc...

El flag -Pjni-devel forzará a compilar el código nativo.

Si el proceso se completa con éxito se generará:

  • Un jar con las clases de java ya compiladas
  • Un jar con los fuentes de java
  • Un jar con los javadocs
  • Un tar.gz con las librerías nativas compiladas

Los jar, tar.gz y fuentes se instalarán en el repositorio local de maven (.m2). Cuando estas dependencias sean necesitadas por una librería o extensión de gvSIG serán copiadas desde ahí.

El nombre del jar tendrá la forma siguiente:

?Estructura de paquete?-?versión?.extensión

Ej: org.gvsig.jgdal-2.0.jar

El nombre de los fuentes será:

?Estructura de paquete?-?versión?-sources.extensión

Ej: org.gvsig.jgdal-2.0-sources.jar

El de los javadoc:

?Estructura de paquete?-?versión?-javadoc.extensión

Ej: org.gvsig.jgdal-2.0-javadoc.jar

Y el de los binarios:

?Estructura de paquete?-?versión?-?operativo?-?distribución?-?compilador?-?plataforma?-dynamic/static.tar.gz

Ej: org.gvsig.jgdal-2.0-linux-all-gcc4-i386-dynamic.tar.gz

Las dependencias en tiempo de compilación con librerías del sistema se resolverán automáticamente si estas están debidamente instaladas. Por ejemplo para linux la compilación de jgdal necesita de la librería gdal instalada y se usará la del repositorio oficial de la distribución que usemos.

Para subir la versión que hemos compilado al repositorio habrá que hacer "deploy" del proyecto usando la siguiente instrucción:

mvn deploy -Dnative-arch=$arch -Dnative-distribution=$distri -Pjni-devel -Dmaven.test.skip

Los parámetros serán los mismos que usamos para hacer "mvn install"

Compilación en windows

Para compilar un proyecto nativo desde una consola en windows deberemos asegurarnos primero de que está definida la ruta al jdk de java en la variable PATH y que la variable JAVA_HOME también está definida.

Al abrir una consola de windows deberemos cargar el entorno de Microsoft Visual Studio. Para eso, habrá que ejecutar desde la consola el fichero llamado vcvars.bat, que está en el directorio bin de VC. La ruta más común para este fichero suele ser:

?C:Archivos de programaMicrosoft Visual Studio 8VCbin?

La compilación se hará con el comando:

mvn install -Pjni-devel -Dmaven.test.skip

Para subir la versión que hemos compilado al repositorio habrá que hacer "deploy" del proyecto usando la siguiente instrucción:

mvn deploy -Pjni-devel -Dmaven.test.skip

Los parámetros serán los mismos que usamos para hacer "mvn install"

Regenerar las dependencias nativas para la ejecución

La dependencias nativas (proyectos libjni-xxxx) son compiladas e instaladas en el repositorio local de maven ($HOME/.m2) usando ?mvn install?, pero no son instaladas para ejecución a no ser que lo invoquemos explícitamente. Las dependencias nativas que se usan en la ejecución estarán en el directorio $HOME/.depman. En caso de linux el directorio lib contendrá las librerías y en caso de windows será el directorio bin. Para que esto suceda se ejecutará la instrucción:

mvn install -Pinstall-extension -Dmaven.test.skip

Esta instrucción se ejecutará dentro de la extensión que tenga dependencias con las librerías nativas, aunque sea de forma indirecta. Hay que tener en cuenta que las extensiones tienen un directorio distribution con un fichero distribution.xml con la información para regenerar las dependencias de las distribución en ejecución.

Dependencias externas (SDKs)
Estructura del SDK

Las librerías que no están instaladas en el sistema necesitan ser resueltas para compilar. Para ello es necesario disponer del SDK de estas dependencias. El SDK de una dependencia contiene:

  • Un directorio bin con las librerías dinámicas y ejecutables que tenga
  • Un directorio data con ficheros de datos
  • Un directorio include con las cabeceras para compilar
  • Un directorio lib con librerías para compilación estática

El sdk estará empaquetado un tar.gz y el nombre tendrá la siguiente estructura:

?nombre de librería?-?version?-?operativo?-?distribución?-?compilador?-?plataforma?-dynamic/static.tar.gz

Ej: gdal-1.7.1-win-nt-vs8-i386-dynamic.tar.gz

A la hora de compilar una librería nativa es necesario que las dependencias estén instaladas en el directorio $HOME/.depman. Cuando se hace un maven install cogerá el tar.gz con el SDK del cual se depende y que está en el repositorio local (.m2) y lo descomprimirá en $HOME/.depman. En caso de que no esté instalado en el repositorio local se lo descargará del repositorio remoto. Este proceso se realizará de forma automática.

Subir SDK al repositorio

Cuando creamos un SDK del cual depende una librería nativa tendremos que subirlo al repositorio una vez montada la estructura que hemos definido en el apartado anterior. Para esto tendremos que empaquetar manualmente los ficheros en un tar.gz.

Una vez tenemos el paquete hecho habrá que subirlo al repositorio usando maven. La instrucción que debemos usar es similar a la siguiente:

mvn deploy:deploy-file
 -Dfile=?C:\gdal-1.7\gdal-1.7.1-win-nt-vs8-i386-dynamic.tar.gz?
 -Durl=scp://shell.forge.osor.eu/home/groups/gvsig-desktop/www/downloads/pub/projects/gvSIG-desktop/maven-repository
 -DrepositoryId=gvsig-repository
 -DgroupId=org.gdal
 -Dversion=1.7.1
 -DartifactId=gdal
 -Dpackaging=tar.gz
 -Dclassifier=win-nt-vs8-i386-dynamic

En este caso se muestran valores de ejemplo para subir el SDK de gdal en su versión 1.7.1 en un windows de 32 bits con compilación con Visual Studio 8. Habría que sustituir estos valores por los correctos para nuestro caso.

El parámetro -DrepositoryId contiene una etiqueta que corresponde con el identificador que debe haber dentro del fichero settings.xml de nuestro directorio .m2. De esta forma podrá conectarse al repositorio por scp validando previamente la cuenta.

Dependencia de proyectos con librerías nativas

Es bastante común hacer uso de dependencias dentro de un proyecto tan grande como es gvSIG. Maven nos ayuda en la tarea de definir esas dependencias. En este apartado se explica como hacer que tu proyecto Java tenga como dependencia una librería nativa.

Únicamente es necesario modificar la sección <dependencies> de tu proyecto Java:

<dependency>
  <groupId>org.gvsig</groupId>
  <artifactId>org.gvsig.jgdal</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
  <groupId>org.gvsig</groupId>
  <artifactId>org.gvsig.jgdal</artifactId>
  <version>2.0</version>
  <classifier>${native-classifier}</classifier>
  <type>tar.gz</type>
</dependency>

El ejemplo anterior lo que nos muestra es que se depende de la librería org.gvsig.jgdal, la primera parte se refiere a la parte Java de jgdal (los .jar), y la segunda parte se refiere a la parte nativa, es decir el conjunto de binarios dependientes de plataforma.

${native-classifier}

El elemento <classifier> de un pom, permite añadir un clasificador a cualquier artefacto maven, de manera que nos permite hacer un tratamiento especial. En el caso de las librerías nativas, el clasificador se ha utilizado para añadir la plataforma, arquitectura, distribución, sistema operativo y tipo de dependencia.

La propiedad ${native-clasifier} se genera a partir de otras propiedades, a continuación se muestra para cada sistema operativo soportado el valor que toma:

  • Linux:

    <native-platform>linux</native-platform>
    <native-distribution>all</native-distribution>
    <native-compiler>gcc4</native-compiler>
    <native-arch>i386</native-arch>
    <native-libraryType>dynamic</native-libraryType>
    
  • Windows:

    <native-platform>win</native-platform>
    <native-distribution>nt</native-distribution>
    <native-compiler>vs8</native-compiler>
    <native-arch>i386</native-arch>
    <native-libraryType>dynamic</native-libraryType>
    
  • MacOSX:

    <native-platform>mac</native-platform>
    <native-distribution>10.5</native-distribution>
    <native-compiler>gcc4</native-compiler>
    <native-arch>universal</native-arch>
    <native-libraryType>dynamic</native-libraryType>
    

La propiedad se genera de la siguiente forma:

<native-classifier>
 ${native-platform}-
 ${native-distribution}-
 ${native-compiler}-
 ${native-arch}-
 ${native-libraryType}
</native-classifier>

Por tanto es fácil cambiar cualquier valor desde la línea de comandos haciendo uso de -Dnative-distribution="valor que quiero que tenga".

<type>tar.gz</type>

Otro elemento que no es habitual en las dependencias de tipo jar, es el elemento <type/>. En este caso, se está usando para que la extensión de la dependencia que busque sea de tipo tar.gz, ya que en este caso al no ser un único fichero, si no un conjunto de binarios o incluso de ficheros necesarios para la compilación de librerías nativas, estos se empaquetan y comprimen en un archivo contenedor (tar.gz).

Destino de los binarios nativos

Al igual que maven tiene un repositorio local donde se descargan los jars de los que se depende, se ha creado un repositorio local donde se descomprimen los binarios nativos:

${user.home}/.depman

Donde en cada sistema operativo toma el valor adecuado. Los proyectos al descomprimirse generan una estructura de directorios similar al de un SDK de librerías nativas multiplataforma:

${user.home}/.depman/
                    |-include      
                        -- Cabeceras de archivos para C/C++
                    |-lib          
                        -- Nativos en linux/mac (.so/.dylib) o 
                           librerías de enlace en windows (.lib).
                    |-bin          
                        -- Nativos en Windows (.dll).
                    |-Frameworks   
                        -- Nativos en Mac (.framework)

Maven cuándo se descarga una dependencia nativa de tipo tar.gz, automáticamente la deposita en el repositorio de maven (${user.home}/.m2) sin descomprimir y a continuación la descomprime en el directorio ${user.home}/.depman. Además ese directorio se añade a los PATHS de ejecución de los Tests unitarios de librerías y proyectos Java, para que si requieren de la librería nativa no existan problemas de ejecución.

Creación/Migración de librerías Nativas a Maven

En este apartado se plantean las bases para la creación o migración de nuevas librerías nativas dentro de gvSIG. Primero se explica la estructura que deben seguir los proyectos para su correcta compilación y generación. A continuación cómo integrar el proyecto en CMake y cómo se debe generar el pom.xml para que todo el sistema compile de manera integrada en el sistema de construcción de gvSIG además de resumir el ciclo de vida de una librería nativa dentro del sistema de construcción de maven.

Estructura del proyecto

Para llevar a cabo un proyecto de una librería nativa, se recomienda una estructura de directorios determinada que facilitará la construcción y organización del proyecto:

librería-jni/
             |-src/
                   |-main/
                   |      |-java
                              -- Ficheros .java
                   |      |-native
                              -- Ficheros .cpp y de cabecera de C++
                   |      |-resources
                              -- Ficheros de recursos a incluir en el .jar
                   |-test/
                          |-java
                              -- Tests unitarios

Seguir esta estructura es importante, tanto para proyectos de maven, como para la compilación de la parte nativa, ya que CMake seguirá esta estructura para buscar los archivos fuente y generar los binarios nativos.

Integración con CMake

Aunque maven es capaz de compilar y administrar dependencias de tipo jar, no es así con las librerías nativas. Existe algún plugin que es capaz de ello, pero no al nivel que se requiere en un proyecto tan grande como gvSIG. Por ello se hace uso de CMake, que es un sistema para la construcción de librerías nativas multiplataforma (no únicamente librerías JNI).

CMake se encarga de generar los ficheros de proyecto y de compilación para cada plataforma y en cada sistema operativo, permitiendo manejar de una forma centralizada varios sistemas e incluso compiladores. Por ejemplo para linux generará los ficheros Makefile necesarios y para Windows generará los ficheros NMakefile o las soluciones de Visual Studio que se tenga instalada en el sistema.

Para facilitar la tarea se han incorporado al directorio build una serie de Macros de CMake que simplifican los ficheros de proyecto.

Para integrar una librería JNI con CMake es necesario crear en el directorio raíz un fichero CMakeLists.txt que tendrá la siguiente estructura:

PROJECT(jgdal)

CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR)

SET(JGDAL_VERSION_MAJOR "2")
SET(JGDAL_VERSION_MINOR "0")
SET(JGDAL_VERSION_PATCH "0")
SET(VERSION "${JGDAL_VERSION_MAJOR}.${JGDAL_VERSION_MINOR}.${JGDAL_VERSION_PATCH}")

SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../build/CMakeModules;${CMAKE_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}")

FIND_PACKAGE(DepMan REQUIRED) 
INCLUDE(GeneralMacros) 

CONFIGURE_DEFAULTS()

IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  SET(CMAKE_INSTALL_PREFIX
    ${DEPMAN_PATH} CACHE PATH "depman path install prefix" FORCE
  )
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)

FIND_PACKAGE(JNI REQUIRED) 
FIND_PACKAGE(GDAL REQUIRED) 

ADD_SUBDIRECTORY(src/main/native)

CONFIGURE_END()

El ejemplo anterior está basado en el de JGDAL y tiene varias instrucciones a tener en cuenta. La instrucción para la busqueda en el sistema de las librerías JNI necesarias para la compilación nativa es:

FIND_PACKAGE(JNI REQUIRED)

Para la búsqueda de otras dependencias que tu proyecto necesite se deberá hacer de una forma similar, por ejemplo en el caso de GDAL se hace:

FIND_PACKAGE(GDAL REQUIRED)

Aunque CMake incorpora una gran cantidad de scripts para la búsqueda de dependencias, si no tiene una, se pueden crear nuevas, como es el caso de GDAL, que se encuentra dentro del directorio CMakeModules ubicado en el directorio build.

Otra instrucción del script a tener en cuenta es la de:

ADD_SUBDIRECTORY(src/main/native)

Esta instrucción indica que se debe buscar archivos CMakeLists.txt en ese subdirectorio para configurar el resto de la compilación.

Hasta ahora sólo hemos configurado el entorno base de CMake, a continuación se muestra el script que debe ir dentro del directorio donde se encuentran los fuentes (.cpp,.c), para realizar la compilación del binario nativo:

SET(LIB_NAME jgdal)

FILE(GLOB SOURCES "*.c*")

include_directories(
    ${CMAKE_SOURCE_DIR}/include
    ${JAVA_INCLUDE_PATH}
    ${JAVA_INCLUDE_PATH2}
    ${GDAL_INCLUDE_DIR}
)

SET(LIBRARIES_OPTIMIZED 
    ${GDAL_LIBRARY}
)

SET(LIBRARIES_DEBUG
    ${GDAL_LIBRARY}
)

SETUP_JNILIB(${LIB_NAME})

En este ejemplo, se están almacenando todos los ficheros .cpp y .c en la variable SOURCES y posteriormente se está configurando el entorno con los directorios de cabecera necesarios. Las variables JAVA_INCLUDE_PATH, JAVA_INCLUDE_PATH2 y GDAL_INCLUDE_DIR se definen al hacer uso de FIND_PACKAGE en el script principal, por lo que son accesibles para su uso en otros scripts. Luego se configuran las librerías de las que se depende, en este caso GDAL_LIBRARY. Finalmente se configura para que se cree una librería JNI.

Se recomienda que si se desea hacer un uso intensivo y avanzado de CMake se lea la documentación del mismo (http://www.cmake.org).

Integración con Maven

Para entender como se integra la construcción de librerías nativas en Maven es necesario entender como lleva a cabo la construcción maven, para ello primero exponemos lo que se denomina ciclo de vida de maven y a continuación mostraremos la configuración inicial.

Ciclo de vida de proyectos maven

Maven realiza ciertas fases denominadas ciclo de vida o lifecycle para llevar a cabo la compilación de los proyectos. En el caso de las librerías nativas, lo que se ha hecho es insertar ciertas acciones durante la ejecución de algunas de esas fases, aprovechando así el sistema de construcción que provee.

Los ciclos y lo que se realiza en cada uno de ellos se menciona a continuación:

  • generate-sources: genera makefiles y busca dependencias nativas (target/target_cmake)
  • compile: make install (target/target_cmake_product)
  • package: genera tar.gz del producto compilado en target/
  • install: instala el tar.gz en .m2/repository
  • deploy: se instala en el repositorio remoto
Ficheros de Configuración

El fichero de configuración pom.xml es similar a cualquier otro proyecto java, pero en este caso se configuran ciertos parámetros necesarios.

La cabecera se debe configurar de la siguiente manera:

<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>
     <groupId>org.gvsig</groupId>
     <artifactId>org.gvsig.jgdal</artifactId>
     <packaging>jar</packaging>
     <version>2.0</version>
     <name>libjni-gdal Library</name>
     <parent>
         <groupId>org.gvsig</groupId>
         <artifactId>gvsig-base-library-jni-pom</artifactId>
         <version>2.0-SNAPSHOT</version>
     </parent>
     <properties>
         <build-dir>${basedir}/../build</build-dir>
     </properties>
     ...

No hay diferencia con otros proyectos, lo único a tener en cuenta es que la definición del elemento padre es: <artifactId>gvsig-base-library-jni-pom</artifactId>

El manejo de dependecias sigue siendo igual que en los proyectos java, aunque en las librerías nativas es habitual encontrarse que se depende de otras librerías nativas, por tanto se han de configurar correctamente, por ejemplo:

<dependencies>
   <dependency>
     <groupId>org.gdal</groupId>
     <artifactId>gdal</artifactId>
     <version>1.6.0</version>
     <classifier>${native-classifier}</classifier>
     <type>tar.gz</type>
   </dependency>
</dependencies>

En algunos casos, nos podemos encontrar que una dependencia se pueda obtener por el sistema de paquetes del sistema (como es el caso de Ubuntu o Debian), por lo que no es necesario añadir la dependencia para ese sistema y sí para el resto, para ello se hace uso de los profiles de maven:

<profiles>
   <profile>
     <id>windows-profile</id>
     <activation>
       <property>
           <name>native-platform</name>
           <value>win</value>
       </property>
     </activation>
     <properties>
       <!-- This hack is necessary to allow correct search in windows -->
       <build-dir>${basedir}\..\build</build-dir>
     </properties>
     <dependencies>
       <dependency>
         <groupId>org.gdal</groupId>
         <artifactId>gdal</artifactId>
         <version>1.6.0</version>
         <classifier>${native-classifier}</classifier>
         <type>tar.gz</type>
       </dependency>
     </dependencies>
   </profile>
   <profile>
     <id>linux-profile</id>
     <activation>
       <property>
           <name>native-platform</name>
           <value>linux</value>
       </property>
     </activation>
   </profile>
   <profile>
     <id>mac-profile</id>
     <activation>
       <property>
           <name>native-platform</name>
           <value>mac</value>
       </property>
     </activation>
     <dependencies>
       <dependency>
         <groupId>org.gdal</groupId>
         <artifactId>gdal</artifactId>
         <version>1.6.0</version>
         <classifier>${native-classifier}</classifier>
         <type>tar.gz</type>
       </dependency>
     </dependencies>
   </profile>
</profiles>

Con esta configuración y al incluir el pom padre específico para librerías jni, se incorporan a las fases del ciclo de vida la generación de los proyectos tipo makefile o NMakefile, la compilación, el empaquetado de los .tar.gz, la instalación en el repositorio de maven y por supuesto la instalación en el repositorio de librerías nativas ${user.home}/.depman y finalmente al hacer un deploy, el despliegue de esa dependencia.

Java ME CDC

Existen una serie de proyectos que mantienen compatibilidad, al menos a nivel de API, con Java ME CDC.

Para compilar (o cualquier otra acción) para Java ME CDC hay que activar un perfil de maven preparado para ello: cdc:

mvn -P cdc clean compile 

Si se cambia entre compilación para Java SE y Java ME CDC, es recomendable limpiar la compilación para que no se empleen classes compiladas para el otro perfil, por eso se ha incluido la llamada al clean antes.


Problemas conocidos
No se encuentra la dependencia jre:javaws:jar:any

Se ha detectado que la versión del jdk 1.5 que se instala desde los repositorios en una Ubuntu de 64 bits (paquete sun-java5-bin) no instala el archivo javaws.jar, lo que provoca un error de dependencias al tratar de compilar el proyecto _fwAndami. Para solucionar esto hay que descargarse la versión del jdk 1.5 de 32 bits y copiar manualmente el jar al directorio correspondiente (${java.home}/lib/javaws.jar).

Este error también puede ocurrir si se está utilizando el OpenJDK, ya que parece ser que esta librería no está incluida. De momento gvSIG no soporta el OpenJDK, así que se puede copiar a mano la librería o bien usar el JVN de Sun.


Trabajando con un proyecto gvSIG

Compilar mi proyecto

Para compilar un proyecto desde maven, basta con invocar el objetivo:

mvn compile

Desde eclipse, se ha creado un lanzador en la opción de External Tools que permite compilar desde maven fácilmente, con el nombre: mvn compile.

Antes de usar este lanzador, deberemos seleccionar o estar editando algun archivo del proyecto que vamos a compilar, ya que se emplea la variable project_loc para invocar a maven sobre un proyecto.

Hay que tener en cuenta que el proyecto de eclipse está configurado de forma que las clases compiladas se generan en el mismo directorio que lo hace maven, así que, por lo general, al invocar este objetivo sobre un proyecto que tengamos abierto en eclipse, ya esté todo compilado y no haga nada.

Además de compilar, si queremos lanzar los tests unitarios de nuestro proyecto desde maven, emplearemos el objetivo:

mvn test

Finalmente, si queremos que el código que compilemos en un proyecto, esté disponible para otros proyectos que dependendan del mismo, deberemos generar el o los archivos .jar correspondientes, e instalarlos en el repositorio local de maven. Para ello emplearemos el objetivo:

mvn install

El objetivo install, además de compilar, lanza los tests unitarios del proyecto. Si queremos hacer la instalación sin lanzarlos, podemos usar el objetivo:

mvn install (no tests)

El equivalente desde consola es:

mvn -Dmaven.test.skip=true install

Los proyectos de gvSIG están configurados para generar, además del archivo .jar con las clases compiladas, otro archivo .jar con los fuentes. Esto nos será útil al enlazar las dependencias en maven y su uso desde los proyectos de eclipse.

Por otro lado, si queremos hacer una instalación y compilación desde cero, podemos usar el objetivo:

mvn clean install
Desplegar mi proyecto

Si nuestro proyecto es una extensión de gvSIG, existe una tarea adicional, además de la compilación y generación de archivos .jar: la instalación de la extensión sobre gvSIG.

Para ello se ha creado el siguiente perfil en maven:

install-extension: copia los archivos .jar generados, junto con el resto de recursos de la extensión (configuración, properties con textos multiidioma, imágenes, etc.) a gvSIG.

Dicho perfil está activado por defecto en los proyectos de tipo extensión, cuando invocamos al objetivo:

mvn install
Publicar mi proyecto

Una vez que hayamos terminado un determinado desarrollo en nuestro proyecto, y queramos que esté disponible para otros proyectos, sin que éstos tengan que descargar el código fuente de nuestro proyecto y compilarlo, podemos publicarlo en el repositorio de maven de gvSIG.

Este paso adicional se realiza a través del objetivo:

mvn deploy

Este objetivo realiza un mvn install y, a continuación, sube los artefactos generados, como el archivo .jar con las clases compiladas, al repositorio de maven.

Note

para que el deploy funcione deberemos tener un usuario con permisos en el proyecto gvSIG, y haber realizado correctamente la configuración definida en el documento Configuración inicial de maven (ver contenido relacionado al final del documento).

Los proyectos de gvSIG están configurados de forma que el repositorio al que se suben los artefactos es el de gvSIG.

Como se comenta en el apartado de compilación, en gvSIG se genera, por defecto, tanto el archivo .jar con las clases compiladas como el archivo .jar con el código fuente, que también se subirá al repositorio.

Además, si estamos publicando una versión con cambios significativos, será conveniente publicar también el javadoc en un archivo .jar. Para ello activaremos el perfil release con el siguiente objetivo desde eclipse:

mvn deploy release

Desde consola, el uso de maven directo es el siguiente:

mvn -P release deploy

TODO

Note

estudiar para el futuro el uso del maven release plugin

Generación de documentación e informes

Maven permite la generación de documentación a partir de los fuentes de un proyecto, como por ejemplo el javadoc.

Para ello existen una serie de plugins especiales de maven para la generación de informes.

Por ejemplo, para generar el javadoc usaremos el plugin correspondiente de la siguiente forma:

mvn javadoc:javadoc

Además de la generación de informes individuales, maven permite la generación de lo que llaman el site. Este consiste en un conjunto de páginas de informes de maven enlazadas, con un menú que nos permite navegar por todos los documentos generados.

De hecho, este mini website generado con maven es lo que emplean muchos de los proyectos Java de apache como website del proyecto.

Para los proyectos de gvSIG, se ha preconfigurado una serie de plugins con las opciones adecuadas del proyecto. Además, existen una serie de páginas que muestran información extraída del archivo pom.xml del proyecto, por lo que será importante completar y mantener actualizada dicha información.

En los proyectos que se generen usando los arquetipos de maven, el archivo pom.xml ya lleva los atributos necesarios predefinidos, a falta de rellenar y completar con valores reales.

Para generar el site invocaremos el objetivo:

mvn site

Esto nos generará la documentación dentro de nuestro proyecto, en la carpeta:

target/site

TODO

Cómo añadir o actualizar una dependencia

Si vamos a añadir o actualizar una dependencia externa en un pom.xml en un proyecto de gvSIG, tendremos que hacer lo siguiente:

Primero, nos asegurarnos que la dependencia y la versión que nos interesa está ya disponible en algunos de los repositorios oficiales de maven. Para ello tenemos dos opciones:

Si hemos encontrado la dependencia deseada, ya podemos modificar el pom.xml, pues ya sabemos que está disponible para todos.

Si no hemos encontrado la dependencia, habría que pedir al proyecto original que suban la dependencia al repositorio oficial de maven, proporcionándoles la información necesaria para ello para que les sea más sencillo:

Así, contribuiremos con la comunidad a facilitar el uso de la librería correspondiente a través de maven. En algún proyecto es posible incluso que nos propongan que nos encarguemos de actualizar nosotros el repositorio de maven con nuevas versiones de una librería.

Si desde el proyecto original no se quiere hacer o se tarda mucho, podemos subirla temporalmente al repositorio maven de gvSIG, quitándola cuando esté disponible en el repositorio oficial.

¿Cómo subir una libraría al repositorio maven de gvSIG?

Lo ideal sería que todas las librerías de las que depende un proyecto de gvSIG tuviesen un repositorio maven para poder descargarlas. Lamentablemente esto siempre no es así y a veces hay que subir una librería al repositorio maven de gvSIG.

En ese caso, para hacer pruebas lo primero que debemos hacer es incluir la dependencia en nuestro repositorio local de maven. Para ello usaremos el siguiente comando:

mvn deploy:deploy-file -Durl=REPO_URL
                   -DrepositoryId=some.id
                   -Dfile=your-artifact-1.0.jar
                   [-DpomFile=your-pom.xml]
                   [-DgroupId=org.some.group]
                   [-DartifactId=your-artifact]
                   [-Dversion=1.0]
                   [-Dpackaging=jar]
                   [-Dclassifier=test]
                   [-DgeneratePom=true]
                   [-DgeneratePom.description="My Project Description"]
                   [-DrepositoryLayout=legacy]
                   [-DuniqueVersion=false]

El comando admite muchas opciones, sobre las cuáles podemos encontrar más documentación en la web del proyecto maven, en el apartado del plugin deploy. Sin embargo, lo más habitual será emplear lo siguiente:

mvn deploy:deploy-file -DgroupId=$LIBRARY_GROUPID
                   -DartifactId=$LIBRARY_ID
                   -Dversion=$LIBRARY_VERSION
                   [-Dclassifier=$LIBRARY_CLASSIFIER]
                   -Dpackaging=jar
                   -Dfile=$LIBRARY_JAR
                   -Durl=$REPOSITORY_URL                  
                   -DrepositoryId=gvsig-repository

Los valores de las variables (empiezan por $) deberemos sustituirlos por:

LIBRARY_GROUPID:
un valor típico suele ser el dominio principal del proyecto. Por ejemplo, para los proyectos gvSIG es org.gvsig, para los proyectos apache org.apache, etc.
LIBRARY_ID:
identificador o nombre de la librería. Suele ser un nombre único o bien un nombre con estilo de paquete java. En gvSIG los proyectos emplean este último formato (ej: org.gvsig.tools.lib).
LIBRARY_VERSION:
versión del jar que vamos a subir.
LIBRARY_CLASSIFIER:
para proyectos que generan varios jars, se emplea este valor para distinguir entre ellos. Un valor típico es tests, para el jar con los tests unitarios del proyecto. Es opcional y no suele ser necesario.
LIBRARY_JAR:
path absoluto al archivo .jar que vamos a subir, o bien relativo desde el directorio donde ejecutamos maven
REPOSITORY_URL:

url del repositorio maven al que vamos a subir. En general usaremos dos opciones:

  • El repositorio local de maven: $USER_HOME/.m2/repository.

    En este caso hay que tener en cuenta que la dependencia sólo estará disponible para nuestro usuario en local. Suele emplearse para pruebas antes de subir la dependencia al repositorio de gvSIG.

  • El repositorio maven de gvSIG: dav:https://devel.gvsig.org/m2repo/j2se

    Una vez subido a este repositorio ya estará disponible para el resto de desarrolladores.

Note

Para que el deploy funcione se ha tenido que configurar previamente el fichero settings.xml tal y como se indica en el documento "Configuración inicial de maven" de la guía del desarrollador, apartado "Acceso de escritura al repositorio maven de gvSIG".

A modo de ejemplo, supongamos que tenemos un jar de la librería JEP en su versión 2.4.0 que queremos incluir como dependencia. La instrucción completa a emplear sería:

mvn deploy:deploy-file -DgroupId=org.nfunk \
               -DartifactId=jep \
               -Dversion=2.4.0 \
               -Dpackaging=jar \
               -Dfile=jep.jar \
               -Durl=dav:https://devel.gvsig.org/m2repo/j2se \
               -DrepositoryId=gvsig-repository

How to create a gvSIG installer with installjammer

A quick howto prepared in the process of creating the gvSIG 2.0 installer using installjammer:

gvSIG install build preparation steps

Prerequisites

You have to install the application used to create gvSIG installers in your computer: InstallJammer.

Go to http://www.installjammer.com and download the last final available version. The last version tested in the project has been the 1.2.15, but it had a bug in the installation of links (needed for native libraries), so the last 1.2 hourly build with that bug solved has been used.

Once installed, get sure the installjammer application (the installjammer executable itself, not a link) is available in your execution PATH.

Install build preparation steps
  1. If necessary, update value of the package.info.state parameter in the paramers section of the pom.xml files of each plugin.

  2. Update your workspace projects and clean, compile and install everything (mvn clean + mvn install). All external projects (org.gvsig.maven.base, org.gvsig.tools, etc.) must have been deployed in their last version previosly.

  3. Launch gvSIG and perform a quick test.

  4. Install the JRE plugin from jre_6_windows_i586 from the addons nanager.

  5. Just in case you have created a previous build and you still have the generated add-on packages, remove everything into your build/product/install folder.

  6. The gvSIG launchers for windows are still not generated automatically, so you should regenerate them with the Launch4J tool. Open the xml files located in build/projects/gvsig-standard/gvsig-standard-installer/src/main/launch4j with the Launch4J utility, update version and build numbers and regenerate the .exe files.

  7. In case there have changes (new files in fwAndami, libCorePlugin or any other change in the online installer content) use the InstallJammer application to check that all the necessary files are included.

  8. Generate the gvSIG installer and all the plugins add-ons: launch the goal mvn-create-installer from the build.xml of the gvsig-standard project available into build/projects/gvsig-standard.

    Once the process is finished, you will have the following artifacts:

    • gvSIG installers in: build/projects/gvsig-standard/gvsig-standard-installer/target/installjammer/output
    • add-on packages in: build/product/install/pool

    If there is an error while the process is generating the installers (at the end of the process), take a look at the InstallJammer configuration maintenance section.

  9. From the command line, define the following environment variables:

    USER=[downloads.gvsig.org user]
    BUILD_NUMBER=2043
    
  10. Upload the installers to downloads.gvsig.org: copy the installers to /srv/download/gvsig-desktop/dists/2.0.0/builds/$BUILD_NUMBER/. Ex:

    ssh $USER@downloads.gvsig.org "cd /srv/download/gvsig-desktop/dists/2.0.0/builds; mkdir $BUILD_NUMBER"
    scp build/projects/gvsig-standard/gvsig-standard-installer/target/installjammer/output/* \
      $USER@downloads.gvsig.org:/srv/download/gvsig-desktop/dists/2.0.0/builds/$BUILD_NUMBER/
    
  11. Generate if needed the add-on packages of plugins not included into the gvsig-standard project group, like:

    • CRS
    • Raster
    • Geoprocessing
    • Thematic Maps
    • Etc...
  12. Upload the add-on packages to /srv/download/gvsig-desktop/pool. Ex:

    tar cvzfC upload.tar.gz build/product/install/ pool
    scp upload.tar.gz $USER@downloads.gvsig.org:/srv/download/gvsig-desktop
    ssh $USER@downloads.gvsig.org "cd /srv/download/gvsig-desktop; tar xvzf upload.tar.gz; rm upload.tar.gz"
    
  13. Create the distribution for the build. Replace STATE and BUILD_NUMBER by the values of the distribution.

    ssh $USER@downloads.gvsig.org "cd /srv/download/gvsig-desktop/dists/2.0.0; ../gvspkg mkdist --state STATE --build BUILD_NUMBER"
    
  14. Install and perform a quick test of the generated installers, downloading all add-ons and checking some basic functionalities (linux, windows, ...).

  15. If everything is OK, commit all changes in the buildNumber.properties files of each project. Else, solve any found problems and return to the first step.

  16. Create a tag of the files included into the install build, with the build number in the tag name. Take into account that some of the project will be located in other svn repositories. You will have to create a tag into each of them, appart from the one in the gvsig-desktop project repository [1].

    To create the tag, if you use the subclipse eclipse plugin, follow those steps (should be very similar if you use subversive instead):

    1. Select in your package explorer, project explorer or navigator, the projects to create the tag with.
    2. Click over them with the right button and select the option Team > Branch/Tag...
    3. In the Copy to URL: field put the URL to the tag to create. Ex: https://devel.gvsig.org/svn/gvsig-desktop/tags/v2_0_0_Build_2043. Check also the Create any intermediary folders that are missing and Preserve folder structure. The last one will put the projects into the tag with the same structure as the main branch (frameworks/_fwandami, libraries/libCompat, etc.).
    4. In the Create copy in the repository from: select the Working copy option. This way the tag will be created from the files you have into your workspace, so the tag won¡t contain any changes commited by other people while you where performing the build process.
    5. In the tag comment, put something about the build being created, like: gvSIG 2.0.0 build 2043.

    Sadly, the subversion server might sometimes cut the connection so the tag process may stop in the middle. In that case, you will have some of the projects already available in the tag.

    As the process follows the order of the projects in your package or project explorer, look in the svn log for the project where the error was produced, deselect the projects (already tagged) in your package/project explorer view listed before that project and start again with the previous steps.

  17. Refresh the plone download page cache:

  18. Create the notice ticket in the gvsig-desktop project tracker.

Note

TODO

  1. Perform a deploy of the projects included into the build, through the mvn-deploy-release (this is the same as the mvn-deploy one, but also generates and uploads the javadocs jar files) command in gvsig-standard.

  2. Only if there are changes in the API or other important changes generate or update the project's maven sites. As the command is still not available in the gvsig-standard ant configuration, you must call it from the command line: mvn site-deploy.

    One way would be to launch the mvn site-deploy goal into the gvsig-standard-project, but the maven site plugin knows about multimodule projects, and it would try to create a main site also for the gvsig-standard-project, which could take forever to finish.

    Another way to do it is to use some script to launch the mvn site-deploy goal for each project. You need to have mvn available into your execution path. As an example, into your workspace folder, launch the following command:

    for i in lib* org* _fwAndami app* ext*; do cd $i; mvn site-deploy; cd ..; done     
    
[1]That last sentence will change when those external projects generate add-on packages by itselfs.
JCRS

The JCRS related projects are not included anymore in the gvsig-standard build process.

As it has few changes and depends on native libraries, the packages for each platform will have to be created when there are changes in the CRS projects.

If you want to compile or create installers of the JCRS plugin, use the gvsig-jcrs group available into build/projects. With that group you will be able to work with all the CRS related projects at once: checking out, compiling, generating package installers, ....

The natives are selected depending on two things:

Taking this into account, how can you get all native dependencies for the supported platforms? There are two ways to do it:

InstallJammer configuration maintenance
Launch installjammer

Once installed, you can open the InstallJammer GUI by running the installjammer executable. As the gvSIG installer configuration uses variables to point to the local paths, you must run installjammer like this:

installjammer -DBaseDir [PATH_TO_GVSIG] \
              -DBaseNativeLibsDir $HOME/.depman \
              -DLini386NativeLibsDir $HOME/.depman/lib \
              -DWini386NativeLibsDir $HOME/.depman/bin \
              -DInstallVersion 2.0.0.2025 \
              -DVersion 2.0.0 \
              --
Deleted or new files and folders

InstallJammer, by default, includes all the new files available in the folders to include in the installation, but fails if any of the previous available files is not available anymore.

That might be useful most of the times, so if you add a file you don't need to update the installjammer configuration. Also if you forgot to install a file or folder, it fails so you can correct it.

But there are times when you want that explicit change:

  • Delete a file or change it with another one with another name (ex: a new library version). If this is the case you must open the InstallJammer gui and remove the old file in the Groups and Files section.
  • There is a new file or folder you don't want to be included by default. For example, when a new plugin is added, as the gvSIG/extensiones is added to the installation with some plugins to be included, the new one would be included too. You must open the InstallJammer gui and uncheck the new file or folder in the Groups and Files section.
Plugins de gvSIG incluidos en el InstallJammer

En el instalable que se genera con el el InstallJammer se deberan incluir los siguientes plugins de gvSIG:

  • org.gvsig.coreplugin
  • org.gvsig.installer.app.extension
Modificación del lanzador de la aplicación para windows

Puede ser necesario modificar de alguna manera el lanzador de la aplicacion para windows gvsig-desktop.exe para lo cual se deben seguir los siguientes pasos:

  1. Descargar la aplicación launch4j de http://launch4j.sourceforge.net/
  2. Descomprimirlo y ejecutarlo.
  3. Abrir el archivo /build/projects/gvsig-standard/gvsig-standard-installer/src/main/launch4j/gvsig.xml
  4. En la pestaña Basic se deben cambiar las rutas absolutas que figuran en los campos Output file, Jar e Icon por las que correspondan con nuestro workspace. Concretamente:
    • Output file debe apuntar a nuestro_workspace/build/product/gvsig-desktop.exe
    • Jar debe apuntar al jar de andami en nuestro_workspace/build/product/lib/org.gvsig.andami-2.0-SNAPSHOT.jar
    • Icon debe apuntar a nuestro_workspace/build/product/gvSIG.ico
  5. En la pestaña Classpath se debe tener seleccionado el checkbox Custom classpath, en el campo Main class debe figurar org.gvsig.andami.Launcher y en el Classpath únicamente el jar de andami ./lib/org.gvsig.andami-2.0-SNAPSHOT.jar
  6. En la pestaña Header en Header type se debe seleccionar la opción GUI.
  7. En la pestaña Single instance no debemos seleccionar nada para que se puedan tener múltiples instancias de la aplicación ejecutándose al mismo tiempo.
  8. En la pestaña Version Info se pueden cambiar los campos File version, Free form, File description, Product version y, de nuevo, Free form pero esta vez de la sección Additional information, por lo que corresponda a la versión y número de build que vamos a generar.
  9. Hacer el resto de modificaciones que necesitemos.
  10. Salvar la configuración.
  11. Generar el ejecutable pulsando el icono con forma de engranaje Build wrapper.
  12. Si todo ha ido bien, este proceso habrá dejado el archivo gvsig-desktop.exe en la ruta que habíamos seleccionado en Output file.
  13. En algún momento de la instalación de la aplicación, se lanza también el instalador de complementos de gvSIG para lo cual generamos otro ejecutable gvsig-package-installer.exe. Para modificar dicho ejecutable podemos repetir estos mismos pasos teniendo en cuenta que:
    • el archivo de configuración que debemos abrir es /build/projects/gvsig-standard/gvsig-standard-installer/src/main/launch4j/gvsig_package_installer.xml y
    • que el Output file debe ser nuestro_workspace/build/product/gvsig-package-installer.exe

Official version publishing of gvSIG

To publish an official version of gvSIG Desktop in www.gvsig.org, the following steps must be followed:

  1. Rename the binaries with the following nomenclature:
  1. Rename source code files (if it's a file) with the following nomenclature:
  1. Upload binaries and source code to OSOR.eu:
  1. Upload the manuals to OSOR.eu:

 

Official version publishing of gvSIG Mobile

To publish an official version of gvSIG Mobile in www.gvsig.org, the following steps must be followed:

  1. Rename the binaries with the following nomenclature:
  1. Rename source code files (if it's a file) with the following nomenclature:

      • gvSIG_Mobile-[gvSIG_Mobile_version]-[Status]-src.[file_extension].
        For example: gvSIG_Mobile-1_0-final-src.zip,  gvSIG_Mobile-0_3-Pilot-src.zip
  2. Upload binaries and source code to OSOR.eu: 
      • In the Forge of the project, being logged, go to Files (for example in gvSIG Mobile: http://forge.osor.eu/frs/?group_id=214)
      • In every project, 2 Packages will be created: one for final versions and another one for versions on development, for example: gvsig-mobile (final ver.), gvsig-mobile (other ver.).
      • In the corresponding Package, the Release must be created. For example:
        • gvSIG Mobile 0.3 Pilot
      • Every file will be uploaded to this release.
  3. Upload the manuals to OSOR.eu:

 


Coding and Development Standards

Coding conventions

Contents

Forewords

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

If you commit code that does not follow these conventions and you are caught, you are responsible for also fixing your own code.

Below is a list of coding conventions that are specific to gvSIG, everything else not specificially mentioned here should follow the official Sun Java Coding Conventions

Why code conventions

As explained in the Sun Java Coding Conventions:

Code conventions are important to programmers for a number of reasons:

How to apply?

Having coding conventions is nice but having a way to ensure they are applied is even better ... :-)

The gvSIG maven configuration has a checkstyle target which performs coding conventions using the Checkstyle tool.

Please run this target before committing any code.

Also the eclipse configuration needed to format the source code taking into account the code conventions defined in the current document will be available in the org.gvsig.maven.base.build project, from the gvsig-tools OSOR project.

If the project you are working with has a prepare-workspace.xml file which you have used to configure your workspace, you will have those files already downloaded and available into the folder:

WORKSPACE/org.gvsig.maven.base.build/eclipse-configs

Otherwise, you may download all the files through the repository URL:

https://devel.gvsig.org/svn/gvsig-tools/org.gvsig.maven.base/trunk/org.gvsig.maven.base/org.gvsig.maven.base.build/src/main/resources/org.gvsig.maven.base.build/eclipse-configs/

To import those configurations perform the following:

  1. Clean up:
    • Go to Window > Preferences > Java > Code Style > Clean Up and click the button Import.
    • In the file system explorer, select the clean_up.xml file.
images/clean_up_optim.png
  1. Code templates:
    • Go to Window > Preferences > Java > Code Style > Code Templates and click the button Import.
    • In the file system explorer, select the code_templates.xml file.
    • Activate the option Automatically add comments for new methods and types.
images/code_templates_optim.png
  1. Formatter:
    • Go to Window > Preferences > Java > Code Style > Formatter and click the button Import.
    • In the file system explorer, select the formatter.xml file.
images/formatter_optim.png
  1. Organize imports:
    • Go to Window > Preferences > Java > Code Style > Organize Imports and click the button Import.
    • In the file system explorer, select the organize_imports.importorder file.
images/organize_imports_optim.png
gvSIG specific coding conventions
Mandatory conventions
  1. Headers

    Look at the Headers document for more information.

  2. Indentations

    4 spaces. NO tabs.

  3. Javadoc

    All API interfaces and classes must be fully documented through javadocs comments at interface/class, method and package level.

    When you inherit or extend from another interface or class which is already documented, and implement or rewrite one of the parent methods, don't write any javadoc comments, as they are also inherited since java 1.4.

  4. Brackets

    All brackets should begin at the end of the line that begins the statement, and end on a new line indented to the beginning of the statement. Example:

    AVOID:

    public class MyClass 
    {
    
        public void someMethod() 
        {
            if (...) { // Do something }
    }
    }
    

    RIGHT:

    public class MyClass {
    
        public void someMethod() {
            if (...) {
              // Do something
            }
        }
    }
    

    Brackets are mandatory even for single line statements:

    if (expression)       // AVOID!
        // some code
    
    if (expression) {     // RIGHT
        // some code
    }
    
  5. Blank Spaces

    Keywords followed by a parenthesis should be separated by a space. Example:

    while (true) {
        // some code
    }
    

    Blank space should appear after commas in argument lists. Binary operators should be separated from their operands by spaces:

    a += c + d;
    a = (a + b) / (c * d);
    
    while (d++ = s++) {
        n++;
    }
    
    printSize("size is " + foo + "\n");
    
  6. Class variables

    Class variables should not have any prefix or suffix related to its data type or scope. Example:

    String nameString;   // AVOID!
    
    String name;         // RIGHT
    
  7. Parameter names

    Method parameters should be prefixed by "the" for differentiating them from inner variables, when there is an inner variable with the same name or use. For example:

    public void someMethod(String theClassName) {
        String className; // inner variable
    }
    
  8. Line length

    Avoid lines longer than 80 characters for Code, comments, ...

  9. Versioning

    All .java files should have a @version tag like the one below into the class javadoc comment:

    @version $Id$
    
  10. Logging

    Do not use System.out to log. Instead, use the SLF4J logging API. For example:

    private static final Logger LOG = 
        LoggerFactory.getLogger(MyClass.class);
    
    public void someMethod() {
        LOG.debug("some debug text");
    }
    

    For more information on SLF4J usage, you can read the Logging document.

  11. Exception handling

    Managing exceptions correctly requires experience. This is not supposed to be a guide on managing exceptions, simply a few best practices.

    • Rule 1: Try to catch exceptions as much as possible and rethrow higher level exceptions (meaning hiding the low level detailed and putting a message that is more related to the function of your code).
    • Rule 2: It is important not to loose the stack trace which contains important information. Use chained exceptions for that.
    • Rule 3: Always log the exception at the higher level (ie. where it is handled and not rethrown).
    • Rule 4: Try to avoid catching Throwable or Exception and catch specific exceptions instead.
    • Rule 5: Create one parent Exception for each API library, so methods of the API that throw any exception use that parent exception or one of the child ones.
    • Rule 6: If you have an exception or an error which can't be handled or resolved by code, throw or rethrow a BaseRuntimeException subclass.

    An example:

    public void getTestClass() {
        try {
            Class responseClass =
                Class.forName("some.package.MyClass");
        } catch (ClassNotFoundException cnfe) {
            String message = "Cannot instantiate test class";
            LOG.error(message, ex);
            throw new ChainedRuntimeException(message, e);
        }
    }
    
  12. Qualified imports

    All import statements should containing the full class name of classes to import and should not use the "*" notation: An example:

    // AVOID!
    import java.util.*;
    import java.net.*;
    
    // RIGHT
    import java.util.Date;
    import java.net.HttpURLConnection;
    
  13. Use interfaces in the declaration of methods and variables.

    By example, if you need a variable x that is a list, declare it as List instead an ArrayList:

    // AVOID!
    ArrayList x = new ArrayList();
    HashMap y = new HashMap();
    
    public HashMap create(ArrayList keys, ArrarList values) {
        ...
    }
    
    // RIGHT
    List x = new ArrayList();
    Map y = new HashMap();
    
    public Map create(List keys, List values) {
        ...
    }
    
  14. API packages

    Usually, API interfaces and classes will belong to the library's main root package. If you create subpackages, use them to group by functionality, not by type.

  15. How to name packages

    All packages must begin with org.gvsig.

    For more information on this convention, you can read the How to name packages document.

Advised conventions
  1. How to name interfaces and classes

Attention!

TODO

For more information on this convention, you can read the How to name interfaces and classes document.

Nomenclature for classes and interfaces

Introduction

This document defines rules for naming classes and interfaces that allow a common style for gvSIG components to be maintained.

The importance of consistency in naming is obvious if one considers a complete Javadoc implementation. From the point of view of the reader, using a variety of naming conventions would create confusion and complicate the understanding of the component.

Criteria to follow
Use of prefixes and suffixes in general

The use of prefixes and/or suffixes in the names of classes and interfaces is usually a means of providing information about their nature and/or task. For example they can be used to denote a pattern, or a role within a pattern (eg the suffix Factory). At other times, it is necessary to use them if the appropriate name has already been assigned. This is the case of the prefixes and suffixes that are described below.

As a general rule:

  • Only use a prefix or suffix when you can't use the simple name (usually because it is being used by another class or interface).
Using the prefix "Abstract"
  • Only to be used for classes, not interfaces.
  • The class must be abstract and implement an interface.
  • Only used when the interface being implemented has the same name.

Example:

public interface List {}
public abstract class AbstractList extends AbstractCollection implements List {}
Using the prefix "I"
  • It is recommended that this prefix not be used.

    Typically, the interfaces are the visible part of a component model. They usually represent entities and concepts from the business or domain and therefore it is recommended that the same names be used as in the business.

Using the prefix "Default"
  • Can't be an abstract class.
  • A default implementation of an interface or an abstract class.
  • The implementation should be sufficient, but not necessarily complete.
  • There may be alternative implementations of this class.

Example:

public interface ListModel {}
public abstract class AbstractListModel implements ListModel, Serializable {}
public class DefaultListModel extends AbstractListModel {}
Using the prefix "Base"
  • Not an abstract class.
  • Provides a "base" implementation of an interface or an abstract class.
  • The class can be instantiated and not used any more, but is designed for the user of the extended component.
  • Do not use this prefix if no interface or parent abstract class exists.

Example:

public abstract class StreamRequestHandler {}
public class BaseHTTPRequestHandler extends StreamRequestHandler {}
Using the suffix "Impl"
  • It is a class instance and therefore can't be abstract
  • It is a complete implementation of an interface or abstract class, generally referred to as the class without the "impl".
  • Other classes should not be extended from it.
  • Do not use this suffix unless the class name conflicts with the name of the interface or abstract class being implemented.
  • If this is the default implementation of part of the API and does not conflict with other parts of the project, the prefix Default is preferred.

Example:

public interface Plane {}
public abstract class AbstractPlane implements Plane {}
 
// Both are correct (but not equal)
public class PlaneImpl implements Plane {} 
public class PlaneImpl extends AbstractPlane {}
Application Conditions

This criterion is applicable to new developments undertaken for gvSIG 2.0 and will be part of the official gvSIG distribution as well as for all developments financed in whole or in part by the CIT.

Names of packages used in gvSIG

Preliminary considerations

Due to the variability and lack of unity in the names of packages used in gvSIG 1.X, it has been decided to standardize these, thereby giving the project an identity that over-rides that of the company doing the development.

Criteria to follow

When creating java packages that will be part of an official gvSIG release, or that will carry the official endorsement of the gvSIG project, the following package is appended:

org.gvsig

No mention is made in the package of the company doing the development.

Normally, the package name org.gvsig is followed by a package name identifying the logical or functional block that it contains.

Application Conditions

These criteria will be applied to new developments to be made to gvSIG 2.0, and will be part of the official gvSIG distribution as well as for all developments financed in whole or in part by the CIT.

Logging

In gvSIG the SLF4J library is used as a logging API.

The Simple Logging Facade SLF4J is a framework that is designed to abstract the underlying logging system. As Log4j is the most popular logging system in use, the framework's API is very similar to simply removing the direct dependence of this system. This framework is therefore an abstraction layer of the logging system and will allow us to change the underlying components without having to undertake major recoding of the application.

Features of SLF4J
// Those lines produce the same results. The second one has parameters that reduce the overhead when debugging is disabled
LOG.debug("The new entry is "+entry+"."); 
LOG.debug("The new entry is {}.", entry);
Using SLF4J in gvSIG

gvSIG 2.0 is ready to work with SLF4J, using LOG4J as implementation, and can be used directly from any gvSIG extension.

To use SLF4J from a Java class just include the following statements:

1.- Import the necessary classes:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

2.- Declare and initialize the Logger:

public class MyClass
{
    private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
    ...

3.- We use the Logger within the code of the class when we want to display a log message, depending on the type: error, warning, information, debug or trace:

LOG.warn(String message);
LOG.warn(String message,Object arg1);
LOG.warn(String message,Object[] arg1);
LOG.warn(String message, Throwable arg1);
LOG.info(String message);
LOG.info(String message,Object arg1);
LOG.info(String message,Object[] arg1);
LOG.info(String message, Throwable arg1);
LOG.error(String message);
LOG.error(String message,Object arg1);
LOG.error(String message,Object[] arg1);
LOG.error(String message, Throwable arg1);
LOG.debug(String message);
LOG.debug(String message,Object arg1);
LOG.debug(String message,Object[] arg1);
LOG.debug(String message, Throwable arg1);
LOG.trace(String message);
LOG.trace(String message,Object arg1);
LOG.trace(String message,Object[] arg1);
LOG.trace(String message, Throwable arg1);

The following methods are provided to check the activation of messages for each level:

LOG.isErrorEnabled();
LOG.isWarnEnabled();
LOG.isInfoEnabled();
LOG.isDebugEnabled();
LOG.isTraceEnabled();

In addition, the messages can also be customized in SLF4J by inserting variables into the String of the log message, as in the following example:

private Integer temperature;

public void setTemperature(Integer temperature) {

    LOG.debug("Setting temperature to {}. Old temperature was {}.", temperature, this.temperature);

    this.temperature = temperature;

    if(temperature.intValue() > 50) {
      LOG.info("Temperature has risen above 50 degrees.");
    }
}

This stops us from having to concatenate Strings, which reduces the cost of using the instructions for logging. This is because, although the log level that we are using is disabled (for example, debug), the method call will be made anyway, including the concatenation of strings to build the message, if any.

However, if the obtaining of any of the parameters to be passed to the message log proves costly, it is convenient to use the consultation methods to avoid such implementation. For example:

private Integer temperature;

public void setTemperature(Integer temperature) {

    LOG.debug("Setting temperature to {}. Old temperature was {}.", temperature, this.temperature);

    this.temperature = temperature;
    addToTemperatureLog(temperature);

    if (LOG.isDebugEnabled()) {
        LOG.debug("The current average temperature is {} Celsius", calculateAverageTemperature());
    }
}

Headers


Migrating Projects to gvSIG 2.0

Introduction

The following sections describe some of the main issues to consider when migrating a project (library or extension) from gvSIG 1.9 to gvSIG 2.0. These instructions will be largely applicable to projects being migrated from earlier versions as well.

Project name

A new project nomenclature should be defined, which should coincide with the main java package of the project, with the base names for jars that are generated or, also, with the artifactID of the maven project.

An example of this nomenclature would be:

extQuickInfo -> org.gvsig.quickinfo

Migrating to maven and the new project structure

gvSIG 2.0 has been migrated from ant to maven as a tool for constructing projects. Therefore, the ant build.xml file should be replaced with a maven pom.xml file.

Documentation on the pom.xml file format, as well as general maven documentation, can be found on the maven project website.

There is also a brief introduction and description of how to use maven in the gvSIG 2.0 development guide.

In addition, maven has a default project structure that allows the most common construction operations to be performed with a minimum of configuration. Adapting the project structure for migrating to the default maven structure is therefore quite convenient.

On the other hand, it is more convenient to create a new project from the maven templates or archetypes, and then to migrate the content from the old to the newly created project, rather than trying to convert the old project directory to the maven format.

These maven project templates (archetypes) allow us to create a simple project with everything needed to start working. There are many archetypes available:

Note

The external multi-module project archetype must still be created and documented.

Package nomenclature

Virtually all the code base of gvSIG projects has been migrated to the package nomenclature of org.gvsig.xxx.

When migrating a project, imports should be updated in the same class. Eclipse provides tools to easily make the necessary changes.

A quick way of doing this, for example, is in the package manager to select all classes in the project, right-click on them and then select Source > Organize Imports.

On the other hand, if the project being migrated belongs to the gvSIG project itself, the packages should be renamed to also begin with org.gvsig.

Logging

The logging API to use in gvSIG 2.0 is the SLF4J library. If the project being migrated is using another logging API, such as Log4J or java.util.logging, then it needs to be replaced with the SLF4J logging API. You can find more information on SLF4J in the section on logging in the development guide

In general, the steps needed to migrate from Log4J to SLF4J are:

1.- Replace the Log4J import classes with those of SLF4J:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// substituting the import of Log4j ...
// import org.apache.log4j.Logger;

2.- Change the Logger definition:

private static final Logger LOG = Logger.getLogger(MyClasser.class);
...

To:

private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
...

3.- Use message parameters where appropriate. For example:

LOG.debug("Point values: X = " + point.getX() + ", Y = " + point.getY());
...

To:

LOG.debug("Point values: X = {}, Y = {}", point.getX(), point.getY());
...

Moving to Java >= 1.5

gvSIG 2.0 supports Java version 1.5 or higher, except in joint projects with gvSIG mobile.

When migrating a project, we need to decide if we want the code to work on gvSIG mobile or not. If so, it is usually not all the code that needs to be compatible, only the library or the library API. It is therefore advisable to have these in a project separate from the rest and then to validate, unless the project compiles to Java ME CDC.

If the project does not need to be compatible with gvSIG mobile, or a part thereof, it is compiled with Java 1.5 or higher.

Due to the compilation with Java 1.5, it is advisable to remove the warnings that could appear in the code in Eclipse, such as the use of the classes of collections without the use of generics.

Dependencies

Dependencies in gvSIG 2.0 projects are managed from maven.

In addition to this change, there are a number of developments that affect how dependencies are defined in gvSIG:

Note

Every time dependencies are modified in the pom.xml file, the eclipse project has to be regenerated because the eclipse project configuration needs to be updated with said dependencies.

You can find more information about the management of dependencies in the section How to add or update a dependency in the gvSIG 2.0. development guide.

Persistence

In gvSIG object persistence is used, amongst other things, to save the project, symbols, etc.

In gvSIG 2.0 a new API and persistence implementation has been developed. It is compatible with Java ME CDC for use in the gvSIG Mobile project and completely replaces the previous API.

Therefore, we have to migrate all uses of persistence in our project so that they use the new API, which is available in the org.gvsig.tools.persistence package of the org.gvsig.tools project.

For more information about using the new persistence API, you can consult the persistence development guide.

Based on experience gained from migrating projects to date, we recommend that when migrating a project you don't rely on persistence as implemented with the old API, as it is often closely linked to the conditions leading to the earlier persistence, assumed a lot more work, besides making assumptions about the flow of persistence.

Instead we recommend that the migration of persistence be addressed as if it were being implemented for the first time, looking only at the class to be persisted, and which of its attributes to persist.

With the new API it is much easier to persist objects, since most of the time the attributes of the classes can be persisted directly, without having to manage their conversion between object and String.

Cloning objects

In versions prior to gvSIG 2.0, a common practice when implementing object cloning was to use persistence. An object was persisted and then 'unpersisted' to obtain a copy.

However, in gvSIG 2.0 this method will probably not work, as the new persistence API takes control of object references to avoid duplicating objects already loaded on the system, and so you may not get the desired results.

To implement object cloning a new API has been defined in org.gvsig.tools, as well as a development guide that shows how to implement and use cloning.

Initialisation of Libraries

There is often the need for some kind of initialisation when loading library projects. Up until now, every project has carried out this initialization on their own using different mechanisms.

To standardise and unify the operation of all projects, a library initialization mechanism has been defined in gvSIG 2.0, for which there is a short development guide showing how to use it in our projects.

Extension points

Extension points have undergone two major changes in gvSIG 2.0:

You can find more information in the developer documentation on extension points.


Fmap

Introduction

The old libFMap project was divided into a number of subprojects which provided the core functionality. These projects, in turn, generated various artefacts or .jar files, which also affect the dependencies that we will include in our projects.

The main projects that have emerged from the former FMap are:

The following section discusses some of the major changes in functionality.

Geometries

In gvSIG 2.0 a separate project for geometry libraries has been constructed. It has evolved from what was in previous libraries and provides a separation between the API, implementation and operations on geometries.

There is development documentation available on the library, where we can see major changes at the API level, and a description of the model geometry that defines the library.

One of the major changes is that classes such as FShape have disappeared, and will be substituted by the interfaces available in the geometry library, such as Geometry and GeometryManager.

For example, where constant shape types were used to define the FShape class, there are now two options:

In any case, if we choose the latter option, then we have a table showing the equivalents between the types of shapes and types of geometries of the new library:

FShape Geometry.TYPES
NULL NULL
POINT POINT
LINE CURVE
POLYGON SURFACE
TEXT TEXT
MULTI GEOMETRY
MULTIPOINT MULTIPOINT
CIRCLE CIRCLE
ARC ARC
ELLIPSE ELLIPSE
Z (*)

(*) In the gvSIG 2.0 geometry library, any geometry may be 2D, 3D, 2DM, etc. This feature is managed through the subtype of a geometry (see Geometry.SUBTYPES for predefined subtypes), so there is no equivalent for this constant in Geometry.TYPES.

Data access

One of the main changes in the development of gvSIG 2.0 has been the replacement of all previous data access methods with a new API and implementation, namely the DAL (Data Access Library).

This API combines access to both tabular and geometric data, in addition to defining a common core API between vector and raster data.

For more information about using the API, as well as the development of data providers, consult the DAL development guide.

Mapcontext, symbology and labelling

All code related to Mapcontext, symbology and labelling has been moved to a separate project: org.gvsig.fmap.mapcontext (libFMap_mapcontext). Those parts relating directly to mapcontext, the viewport, layers, etc. have not changed much since the previous version, except for changes required to conform to the rest of gvSIG 2.0.

The main change has been to extract the symbology and labelling API, as this API and the rest of mapcontext are a joint project between gvSIG desktop and gvSIG mobile.

The implementation of symbology and labelling now has its own project: org.gvsig.symbology. This is the implementation that is used in gvSIG desktop; gvSIG mobile has developed its own implementation.

Therefore, when a project is migrated to gvSIG 2.0 it will be affected mainly by:

At the moment the development guide doesn't have any documentation available on this development.

Mapcontrol

A new project has been created where all the code related to MapControl is located: org.gvsig.fmap.control (libFMap_controls). This project also contains other graphical controls that depend on the other FMAP APIs, such as DAL.

For example, swing components, used from the gvSIG document table, have been created to display Feature tables. But now it is very easy to create applications outside of gvSIG, or to include other use cases that aren't from the document table, that show Feature data in tabular form.

Apart from the general changes to packages, and the adaptation to the other changes, this project has a few changes affecting the API. Some examples are:

appgvSIG

TODO

Changes to the project API and documents:

Installer

TODO

Recommendations


FAQs

Where is MapControl's addMapTool method?

Version 1.9 had an addMapTool method in the MapControl class but Version 2.0 doesn't.

Where can it be found?

The addMapTool method has simply been renamed addBehavior.

What is equivalent to the FieldDescription class in version 2.0?

In version 1.9 the FieldDescription class was used to query the attributes of a field in a table.

How is this done now?

In version 2.0 all data access has changed. To query the attributes that describe a field in a table you have to make use of the FeatureAttributeDescriptor class.

A vector layer has a FeatureStore, which in turn has a defaultFeatureType, that defines the structure of the feature by means of the FeatureAttributeDescriptor.

What has happened to FLyrVect's getRecordset and getSource methods?

The getSource and getRecordset methods were used to access a layer's data.

What is used now?

In version 2.0 the vector layers have a getFeatureStore method that returns a FeatureStore and provides access to both spatial and alphanumeric data.

If you just want to get all the layer's features you can invoke the getFeatureSet method of FeatureStore.

Can't locate the View class?

Some parts of my Extension were cast to the View class in order to access the view window.

Where is this class now?

The View class has been renamed and should not be used for casting. If you do need it, it will probably be sufficient to cast the IView interface.

Where can I find the ViewPort's getAdjustedExtent method?

How can I find the extent of the view port?

There is no longer a getAdjustedExtent method.

There has been a systematic elimination of all the methods that worked with an Extent. These have been replaced by methods for managing an Envelope. Operations on the gvSIG extent treated it as a 2D rectangle, which, with the emergence of more complex geometries, is no longer correct.

The methods that used to work on an Extent now work with an Envelope, and so have been renamed.

The getAdjustedExtent method has now become getAdjustedEnvelope.

How can I convert a geometry to JTS?

I have code that works with geometries that follow the JTS model.

How can I convert a gvSIG Geometry to JTS format?

You can do this by invoking:

Geometry geom;
com.vividsolutions.jts.geom.Geometry jtsGeom;

jtsGeom = (com.vividsolutions.jts.geom.Geometry) geom.invokeOperation(ToJTS.CODE, null);
Can't find getModel in the View class?

I have a variable of type View and would like to access the getModel method. Where I can find it in 2.0?

The code in 1.x was something like:

IWindow window;
MapContext mapa = ((View) window).getModel().getMapContext()

The code in 2.0 is:

IWindow window;
MapContext mapa = ((IView) window).getViewDocument().getMapContext();
How do I get an extension point?

To get an extension point:

The code in 1.x was something like this:

ExtensionPoint pe;
String name;
pe = (ExtensionPoint) ExtensionPointsSingleton.getInstance().get(name);

In 2.0 the code is:

ExtensionPoint pe;
String name;
pe = ToolsLocator.getExtensionPointManager().get(name);
The createLayer method of the LayerFactory class is deprecated. How do I create a raster layer?

The createLayer method of the LayerFactory class is deprecated. How do I create a raster layer?

The code in 1.x was something like this:

String filename;
BaseView view;
FLayer newLayer = LayerFactory.createLayer(filename, "gvSIG Image Driver",new File(filename), view.getProjection());

In 2.0 the code is:

String filename;
IView view;
DataStoreParameters parameters = DALLocator.getDataManager().createStoreParameters(RasterStoreProvider.NAME);
parameters.setDynValue("filename", filename);
parameters.setDynValue("srs", view.getViewDocument().getMapContext().getProjection());
FLayer newLayer = MapContextLocator.getMapContextManager().createLayer(filename, parameters);

Annexures

Migration to the OSOR subversion repository

The gvSIG subversion repository was moved from its own server at the gvsig.org domain to a server hosted in OSOR during the week of April 12th 2010.

The easiest way is to do a checkout of the project again in a new workspace. However, if we have changes to upload, another option is to change the reference to the subversion server in our own workspace.

At first, we have two options for this:

All of this, project by project. If we have a unix shell (we are on linux, mac, windows with the cygnus utilities, etc.) we can use the following instructions (including to create a script) to migrate a complete workspace of the gvSIG core:

# Andami
svn switch --relocate \
    https://gvsig.org/svn/gvSIG/branches/v2_0_0_prep/frameworks/_fwAndami \
    https://svn.forge.osor.eu/svn/gvsig-desktop/branches/v2_0_0_prep/frameworks/_fwAndami \
    _fwAndami

# Root projects
for project in build binaries org.gvsig.core.maven.dependencies; 
do svn switch --relocate https://gvsig.org/svn/gvSIG/branches/v2_0_0_prep/${project} \
    https://svn.forge.osor.eu/svn/gvsig-desktop/branches/v2_0_0_prep/${project} \
    ${project}; 
done

# Applications
for project in app*; 
do svn switch --relocate https://gvsig.org/svn/gvSIG/branches/v2_0_0_prep/applications/${project} \
    https://svn.forge.osor.eu/svn/gvsig-desktop/branches/v2_0_0_prep/applications/${project} \
    ${project}; 
done

# Libraries
for project in lib*; 
do svn switch --relocate https://gvsig.org/svn/gvSIG/branches/v2_0_0_prep/libraries/${project} \
    https://svn.forge.osor.eu/svn/gvsig-desktop/branches/v2_0_0_prep/libraries/${project} \
    ${project}; 
done

# Extensions
for project in ext* org.gvsig.symbology; 
do svn switch --relocate https://gvsig.org/svn/gvSIG/branches/v2_0_0_prep/extensions/${project} \
    https://svn.forge.osor.eu/svn/gvsig-desktop/branches/v2_0_0_prep/extensions/${project} \
    ${project}; 
done

Developing gvSIG 1.10+ projects with an eye on gvSIG 2.0

The differences between versions 1.X and 2.X are very important in some areas of the application. There are important changes relating to:

In the light of these changes, there is no simple answer to the question What needs to be taken into account when initiating a development in the 1.X line and then later migrating to the 2 line?

The first issue that arises is that compatibility can't be maintained. Upon further reflection, there are some recommendations that can be followed, some more difficult than others. Some of them are listed here and developers will have to decide on their applicability to their projects:

In general it is a good idea to read the sections on Creating a gvSIG project and Migrating projects to gvSIG 2.0 in the gvSIG 2.0 developers guide.


FAQs

Error al ejecutar mvn -P create-installer install

Al ejecutar la creación de un instalador, ya sea mediante la opción mvn create installer o mediante un comando similar a este desde la consola:

mvn -P create-installer install

es habitual encontrarse con un error que termina con líneas como estas:

[artifact:mvn] [INFO] Creating package of the package info:
[artifact:mvn] [INFO] org.gvsig.installer.lib.impl.DefaultPackageInfo@11e8050 (
[artifact:mvn]        code: org.gvsig.oracle
[artifact:mvn]        name: 
[artifact:mvn]        description: 
[artifact:mvn]        gvSIG-version: 
[artifact:mvn]        version: 0.0.1-0
[artifact:mvn]        buildNumber: 0
[artifact:mvn]        operating-system: all
[artifact:mvn]        architecture: all
[artifact:mvn]        java-version: j1_5
[artifact:mvn]        download-url: 
[artifact:mvn]        state: devel
[artifact:mvn]        official: false
[artifact:mvn]        type: unknow
[artifact:mvn]        model-version: 1.0.1
[artifact:mvn]        owner: 
[artifact:mvn]        owner-url: 
[artifact:mvn]        sources-url: 
[artifact:mvn]        dependencies: 
[artifact:mvn]        web-url: 
[artifact:mvn]        categories: [])
[artifact:mvn] [INFO] ------------------------------------------------------------------------
[artifact:mvn] [ERROR] FATAL ERROR
[artifact:mvn] [INFO] ------------------------------------------------------------------------
[artifact:mvn] [INFO] null
[artifact:mvn] [INFO] ------------------------------------------------------------------------
[artifact:mvn] [INFO] Trace
[artifact:mvn] java.lang.NullPointerException
[artifact:mvn]        at java.util.Hashtable.put(Hashtable.java:394)
[artifact:mvn]        at java.util.Properties.setProperty(Properties.java:143)
[artifact:mvn]        at org.gvsig.installer.lib.impl.info.InstallerInfoFileWriter.write(InstallerInfoFileWriter.java:101)
[artifact:mvn]        at org.gvsig.installer.lib.impl.info.InstallerInfoFileWriter.write(InstallerInfoFileWriter.java:74)
[artifact:mvn]        at org.gvsig.installer.lib.impl.info.InstallerInfoFileWriter.write(InstallerInfoFileWriter.java:59)
[artifact:mvn]        at org.gvsig.installer.lib.impl.DefaultInstallerProviderServices.writePackageInfoFile(DefaultInstallerProviderServices.java:148)
[artifact:mvn]        at org.gvsig.installer.lib.impl.DefaultInstallerProviderServices.writePackageInfoForIndex(DefaultInstallerProviderServices.java:136)
[artifact:mvn]        at org.gvsig.installer.lib.impl.creation.DefaultMakePluginPackageService.writePackageInfoForIndex(DefaultMakePluginPackageService.java:221)
[artifact:mvn]        at org.gvsig.installer.maven.GeneratePluginPackageIndexMojo.createPackage(GeneratePluginPackageIndexMojo.java:83)
[artifact:mvn]        at org.gvsig.installer.maven.AbstractGeneratePackageMojo.execute(AbstractGeneratePackageMojo.java:167)
[artifact:mvn]        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
[artifact:mvn]        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
[artifact:mvn]        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
[artifact:mvn]        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
[artifact:mvn]        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
[artifact:mvn]        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
[artifact:mvn]        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
[artifact:mvn]        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
[artifact:mvn]        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
[artifact:mvn]        at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
[artifact:mvn]        at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
[artifact:mvn]        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[artifact:mvn]        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[artifact:mvn]        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[artifact:mvn]        at java.lang.reflect.Method.invoke(Method.java:597)
[artifact:mvn]        at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
[artifact:mvn]        at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
[artifact:mvn]        at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
[artifact:mvn]        at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
[artifact:mvn] [INFO] ------------------------------------------------------------------------
[artifact:mvn] [INFO] Total time: 11 seconds
[artifact:mvn] [INFO] Finished at: Fri May 11 15:34:48 CEST 2012
[artifact:mvn] [INFO] Final Memory: 57M/137M
[artifact:mvn] [INFO] ------------------------------------------------------------------------

BUILD FAILED
C:\dev\ew\gv2\build\ant-tasks\maven-goals.xml:35: The following error occurred while executing this line:
C:\dev\ew\gv2\build\ant-tasks\ant-tasks-config.xml:117: Java returned: 1

Esto suele ocurrir porque no se ha incluído una referencia al archivo package.info en distribution.xml. La solución consiste en añadir un párrafo similar a este en dicho archivo:

<assembly>
  ...
  <files>
  ...
      <file>
          <source>package.info</source>
          <outputDirectory>${extension.install.dir.name}
          </outputDirectory>
      </file>
  ...
  </files>    
  ...
</assembly>

Eclipse señala errores de dependencias tras montar el workspace completo

Tras seguir los pasos descritos en el documento Cómo montar un workspace de gvSIG para Eclipse para montar un workspace completo de gvSIG, puede ocurrir que Eclipse nos señale mediante iconos de error algún problema de dependencias entre los diferentes proyectos. Esto ocurre aunque los scripts de ANT (mvn-eclipse-eclipse, mvn-install, etc) funcionan correctamente.

La causa podría ser un problema de comunicación entre Maven y Eclipse, que impide actualizar correctamente las dependencias de los proyectos en Eclipse.

El método conocido para solucionar esto consiste en comprobar en la pestaña Problems, qué proyectos tienen ese problema y usar el método mvn eclipse individualmente sobre cada uno de ellos, hasta eliminar todos los mensajes de error.

Tras montar el workspace de gvSIG al intentar ejecutar gvSIG no encuentra el jar de andami.

Tras montar el workspace de gvSIG tal como se indica en el documento Cómo montar un workspace de gvSIG para Eclipse, si intentamos ejecutar gvSIG desde el launcher de Eclipse, nos presenta un error diciendo que no puede encontrar el fichero ".../build/product/lib/...andami...jar" .

Si el proceso de descarga del workspace de gvSIG a terminado de forma satisfactoria esto puede deberse a que en el fichero $HOME/.m2/settings.xml esta especificada la ruta en la que hay que desplegar los plugins de gvSIG a una carpeta distinta a la de build/product de dentro del workspace de gvSIG. Esto es facil que ocurra si antes de montar el worlspace de gvSIG hemos estado trabajando con una instalacion de gvSIG generando plugins con el asistente para la generacion de plugins, en cuyo caso tendremos en el settings.xml la ruta a esa instalacion.

Para solucionarlo podremos hacer dos cosas:

Si vamos a estar trabajando tanto con el workspace de gvSIG como con el de algun otro plugin que estemos desarrollando sera recomendable la ultima opcion.