1

I am trying to write an OSMOSIS extension that makes use of GeoTools and reads a GeoTiff Image.

I've written a minimal working example of what it does:

package that.is.my.test;

import java.io.File;
import java.io.IOException;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.opengis.coverage.grid.GridEnvelope;

public class ExampleClass {
    public static void main(String[] args) {
        new ExampleClass();
    }

    public ExampleClass() {
        try {
            File file = new File("<GEOTIFFFILE>");
            GeoTiffReader reader = new GeoTiffReader(file);
            GridCoverage2D coverage = (GridCoverage2D) reader.read(null);
            GridEnvelope gridBounds = coverage.getGridGeometry().getGridRange();
            System.out.println("grid bounds: " + gridBounds);

            Envelope2D worldBounds = coverage.getEnvelope2D();
            System.out.println("world bounds: " + worldBounds);

            int numBands = coverage.getNumSampleDimensions();
            System.out.println("num bands: " + numBands);

            System.out.println("Goodbye.");
        } catch (IllegalArgumentException | IOException e) {
            e.printStackTrace();
        }
    }
}

Note: This is a minimal example class, but the code in the OSMOSIS plugin doesn't do anything else yet.

I can run this example class from NetBeans, and it works fine. I can package it into a runnable jar, and that also works fine.

The OSMOSIS plugin cannot be run from NetBeans, as it is to be compiled into a jar and then be called by OSMOSIS itself. But when I do that, the line starting with GridCoverage2D gives me an IllegalArgumentException with the message ImageRead: No OperationDescriptor is registered in the current operation registry under this name..

When I let both classes print out a complete JAI Registry list, I can see that in the OSMOSIS case, ImageRead, ImageWrite and a few others are simply missing.

I can simply not understand how this can happen! When I look into the jars, the file META-INF\services\javax.imageio.spi.ImageReaderSpi exists in both of them, with exactly the same content.

This is my POM.xml from the plugin, the Example class has the same dependencies and repos and build directives:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>hello.OSMOSIS</groupId>
    <artifactId>my-osmosis-plugin</artifactId>
    <version>1.0-SNAPSHOT${jarWarning}</version>
    <packaging>jar</packaging>
    <name>OSMOSIS TEST plugin</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <osmosisScope>provided</osmosisScope> <!-- configure this by using the profiles, this is fallback only. -->
        <geotools.version>12-RC1</geotools.version>
    </properties>
    <!-- We define two different profiles: 
        debugWithNetbeans includes all the OSMOSIS jars into the plugin, 
            so that we can test-run the plugin with Netbeans (or anything else). 
            Note: This does not work yet...
        pluginProductions doesn't include the OSMOSIS sources, because later on 
            the plugin will be called BY osmosis and will not need the jars anymore. 
    DO NOT FORGET to set this correctly :-) -->
    <profiles>
        <profile>
            <id>debugWithNetbeans</id>
            <properties>
                <osmosisScope>compile</osmosisScope>
                <jarWarning>-DEBUG-BUILD</jarWarning>
            </properties>
        </profile>
        <profile>
            <id>pluginProduction</id>
            <properties>
                <osmosisScope>provided</osmosisScope>
                <jarWarning></jarWarning>
            </properties>
        </profile>
    </profiles>
    <repositories>
        <repository>
            <id>osgeo</id>
            <name>Open Source Geospatial Foundation Repository</name>
            <url>http://download.osgeo.org/webdav/geotools/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.openstreetmap.osmosis</groupId>
            <artifactId>osmosis-core</artifactId>
            <version>0.43-RELEASE</version>
            <scope>${osmosisScope}</scope>
        </dependency>
        <dependency>
            <groupId>org.openstreetmap.osmosis</groupId>
            <artifactId>osmosis-xml</artifactId>
            <version>0.43.1</version>
            <scope>${osmosisScope}</scope>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geotiff</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-epsg-hsql</artifactId>
            <version>${geotools.version}</version>                 
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.3.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>hello.OSMOSIS.DoNothingBecauseImAPluginOnly</Main-Class>
                                        <Implementation-Vendor>Blapfi</Implementation-Vendor>
                                        <Implementation-Vendor-Id>huiuiui</Implementation-Vendor-Id>
                                        <Implementation-Version>bapfi</Implementation-Version>
                                    </manifestEntries>
                                </transformer>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Perhaps someone can give me a hint on what I am doing wrong? Would be very great. :-)

Kurtibert
  • 466
  • 3
  • 13

1 Answers1

0

I perhaps found an explanation right now: The JAI registry seems to be initialized when the JAI jar – or a jar that contains it – gets added to the classpath. Sadly, the jars in OSMOSIS' plugins directory never get added to any classpath but read by OSMOSIS itself.

So, my solution is to build the plugin as a jar, bundled with a lib folder that contains all the dependencies, and a README that instructs the user to add /plugins/lib/* to the classpath of OSMOSIS.

In osmosis.bat this can be done by changing -cp "%PLEXUS_CP%" to -cp "%PLEXUS_CP%";plugins/lib/*. In the linux versions, you have to use a : instead of ;, I think (https://stackoverflow.com/a/219801/4249849).

Edit1: This only works, if your current working directory is osmosis/bin. If you want to use it from everywhere (path), you have to add pushdand popdcommands (Windows).

Community
  • 1
  • 1
Kurtibert
  • 466
  • 3
  • 13