Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #402: Provide bnd plugin to generate package imports based on imports in UIMA descriptors #403

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ issuesFixed
.idea
*.iml
.tycho-consumer-pom.xml
dependency-reduced-pom.xml
2 changes: 1 addition & 1 deletion PearPackagingMavenPlugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

<artifactId>PearPackagingMavenPlugin</artifactId>
<packaging>maven-plugin</packaging>
<name>Apache UIMA Maven: ${project.artifactId}</name>
<name>Apache UIMA Tools: ${project.artifactId}</name>
<description>This is a maven plugin that produces a pear artifact.</description>
<url>${uimaWebsiteUrl}</url>

Expand Down
1 change: 1 addition & 0 deletions aggregate-uimaj/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<module>../PearPackagingMavenPlugin</module>
<module>../jcasgen-maven-plugin</module>
<module>../uimaj-v3migration-jcas</module>
<module>../uima-bnd-plugin</module>

<module>../uimafit-core</module>
<module>../uimafit-junit</module>
Expand Down
2 changes: 1 addition & 1 deletion jcasgen-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<artifactId>jcasgen-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

<name>Apache UIMA Maven: ${project.artifactId}</name>
<name>Apache UIMA Tools: ${project.artifactId}</name>
<description>A Maven Plugin for using JCasGen to generate Java classes from
XML type system descriptions</description>

Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
<exclude>jcasgen-maven-plugin/**</exclude>
<exclude>uimaj-adapter-*/**</exclude>
<exclude>uimaj-bom/**</exclude>
<exclude>uima-bnd-plugin/**</exclude>
<exclude>uimaj-component-test-util/**</exclude>
<exclude>uimaj-core/**</exclude>
<exclude>uimaj-cpe/**</exclude>
Expand Down
97 changes: 97 additions & 0 deletions uima-bnd-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.apache.uima</groupId>
<artifactId>uimaj-parent</artifactId>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../uimaj-parent/pom.xml</relativePath>
</parent>

<artifactId>uima-bnd-plugin</artifactId>

<name>Apache UIMA Tools: UIMA Plugin for BND</name>

<dependencies>
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimaj-core</artifactId>
<version>${project.version}</version>
</dependency>

<!--
bndlib is provided at runtime (it neither needs to be considered by the
maven-shade-plugin nor as transitive dependency by Maven)
-->
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<!-- Use a shade plugin in order to append META-INF/service SPI resources into target artifact -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
</transformers>
<!-- exclude provided dependencies -->
<artifactSet>
<excludes>
<!-- Don't include anything from bndlib (as this is always
part of the classpath) -->
<exclude>biz.aQute.bnd:bndlib</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>org.osgi</artifact>
<!-- exclude everything which is already included in bndlib -->
<excludes>
<exclude>org/osgi/resource</exclude>
<exclude>org/osgi/service/component/annotations</exclude>
<exclude>org/osgi/service/metatype/annotations</exclude>
<exclude>org/osgi/service/repository</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.uima.tools.bnd;

import static java.util.Collections.emptyList;

import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.uima.UIMAFramework;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.resource.metadata.FsIndexCollection;
import org.apache.uima.resource.metadata.Import;
import org.apache.uima.resource.metadata.TypePriorities;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
import org.apache.uima.util.XMLParser;
import org.apache.uima.util.XMLizable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import aQute.bnd.annotation.plugin.BndPlugin;
import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Resource;
import aQute.bnd.service.AnalyzerPlugin;

@BndPlugin(name = "UIMA")
public class UimaBndPlugin
implements AnalyzerPlugin
{

private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private static final Pattern XML_FILE = Pattern.compile(".*\\.xml");
private static final Pattern QN = Pattern
.compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");

private final static XMLParser PARSER = UIMAFramework.getXMLParser();

@Override
public boolean analyzeJar(Analyzer analyzer) throws Exception
{
var jar = analyzer.getJar();
var resources = jar.getResources();

var importsProcessed = 0;
if (resources != null) {
for (var entry : resources.entrySet()) {
var path = entry.getKey();
var resource = entry.getValue();

try {
if (XML_FILE.matcher(path).matches()) {
importsProcessed += analyzeXmlFile(analyzer, path, resource);
}
}
catch (Exception e) {
analyzer.error("Unexpected exception in processing resource (%s): %s", path, e);
}
}
}

LOG.info("UIMA bnd plugin processed {} imports", importsProcessed);

return false;
}

private int analyzeXmlFile(Analyzer analyzer, String path, Resource resource) throws Exception
{
var desc = readUimaDescriptor(resource);
if (desc == null) {
return 0;
}

LOG.debug("Found {}: {}", desc.getClass().getSimpleName(), path);
var imports = getImportsFromDescriptor(desc);

var importsProcessed = 0;
for (var imp : imports) {
if (imp.getName() != null) {
handleImportByName(analyzer, path, imp);
importsProcessed++;
continue;
}

if (imp.getLocation() != null) {
handleImportByLocation(imp);
continue;
}

LOG.warn(
"Found UIMA type system import without name and location - ignoring, please fix your type system description");
}

return importsProcessed;
}

private void handleImportByLocation(Import imp)
{
LOG.warn(
"Found UIMA type system import by location: {} - ignoring, please only use import-by-name",
imp.getLocation());
}

private void handleImportByName(Analyzer analyzer, String path, Import imp)
{
var tsdPackage = imp.getName();
int lastSeparatorPosition = tsdPackage.lastIndexOf('.');
if (lastSeparatorPosition >= 0) {
// Cut the name of the XML file and keep only the package
tsdPackage = tsdPackage.substring(0, lastSeparatorPosition);
}

LOG.debug("Found UIMA type system import by name: {}", tsdPackage);

var pack = analyzer.getPackageRef(tsdPackage);
if (!QN.matcher(pack.getFQN()).matches()) {
analyzer.warning("Type system import does not seem to refer to a package (%s): %s",
path, pack);
}

if (!analyzer.getReferred().containsKey(pack)) {
var attrs = new Attrs();
analyzer.getReferred().put(pack, attrs);
}
}

private List<Import> getImportsFromDescriptor(XMLizable desc)
{
if (desc instanceof TypeSystemDescription tsd) {
return asList(tsd.getImports());
}

if (desc instanceof TypePriorities prio) {
return asList(prio.getImports());
}

if (desc instanceof FsIndexCollection idxc) {
return asList(idxc.getImports());
}

if (desc instanceof AnalysisEngineDescription aed) {
var imports = new ArrayList<Import>();
imports.addAll(
getImportsFromDescriptor(aed.getAnalysisEngineMetaData().getTypeSystem()));
imports.addAll(
getImportsFromDescriptor(aed.getAnalysisEngineMetaData().getTypePriorities()));
imports.addAll(getImportsFromDescriptor(
aed.getAnalysisEngineMetaData().getFsIndexCollection()));
return imports;
}

return emptyList();
}

private XMLizable readUimaDescriptor(Resource resource) throws Exception
{
try (var in = resource.openInputStream()) {
return PARSER.parse(new XMLInputSource(in));
}
catch (InvalidXMLException e) {
// Probably not a type system description - ignore
}

return null;
}

private static <T> List<T> asList(T[] aList)
{
if (aList == null) {
return emptyList();
}

return Arrays.asList(aList);
}
}
10 changes: 2 additions & 8 deletions uimaj-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,12 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.apache.uima</groupId>
<artifactId>parent-pom</artifactId>
<relativePath />
<version>18-SNAPSHOT</version>
</parent>

<groupId>org.apache.uima</groupId>
<artifactId>uimaj-bom</artifactId>
<version>3.6.0-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Apache UIMA Base: ${project.artifactId}</name>
<name>Apache UIMA - BOM</name>

<dependencyManagement>
<dependencies>
Expand Down
2 changes: 2 additions & 0 deletions uimaj-documentation/src/docs/asciidoc/tools.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ include::tools/tools.caseditor.adoc[leveloffset=+1]

include::tools/tools.jcasgen.adoc[leveloffset=+1]

include::tools/tools.bnd.adoc[leveloffset=+1]

include::tools/tools.pear.packager.adoc[leveloffset=+1]

include::tools/tools.pear.packager.maven.adoc[leveloffset=+1]
Expand Down
Loading