All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.felix.bundleplugin.VerifyBundlePlugin Maven / Gradle / Ivy

/*
 * 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.felix.bundleplugin;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Formatter;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.regex.Pattern;

import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.manifest.Parser;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

/**
 * Verifies OSGi bundle metadata contains valid entries.
 *
 * Supported checks in the current version:
 * 
    *
  • All packages declared in the Export-Package header are really included in the bundle.
  • *
*/ @Mojo( name = "verify", threadSafe = true, defaultPhase = LifecyclePhase.VERIFY ) public final class VerifyBundlePlugin extends AbstractMojo { private static final String EXPORT_PACKAGE = "Export-Package"; private Pattern skipDirs = Pattern.compile( "(META|OSGI)-INF(.*)" ); @Component private MavenProject project; /** * Flag to easily skip execution. */ @Parameter( property = "skip", defaultValue = "false" ) protected boolean skip; /** * Whether to fail on errors. */ @Parameter( property = "failOnError", defaultValue = "true" ) protected boolean failOnError; @Override public void execute() throws MojoExecutionException, MojoFailureException { if ( skip ) { getLog().info( "Skipping Verify execution" ); return; } Set packagesNotFound = checkPackages(); if ( !packagesNotFound.isEmpty() ) { Formatter formatter = new Formatter(); formatter.format( "Current bundle %s exports packages that do not exist:%n", project.getArtifact().getFile() ); for ( String packageNotFound : packagesNotFound ) { formatter.format( " * %s%n", packageNotFound ); } formatter.format( "Please review the instruction in the `configuration/instructions` element of the `maven-bundle-plugin`%n" ); formatter.format( "For more details, see http://bnd.bndtools.org/heads/export_package.html" ); String message = formatter.toString(); formatter.close(); if ( failOnError ) { throw new MojoFailureException( message ); } else { getLog().warn( message ); } } } private Set checkPackages() throws MojoExecutionException { Set packagesNotFound = new TreeSet(); File bundle = project.getArtifact().getFile(); JarInputStream input = null; try { input = new JarInputStream( new FileInputStream( bundle ) ); Manifest manifest = input.getManifest(); Attributes mainAttributes = manifest.getMainAttributes(); String exportPackage = mainAttributes.getValue( EXPORT_PACKAGE ); if ( exportPackage == null || exportPackage.isEmpty() ) { getLog().warn( "Bundle manifest file does not contain valid 'Export-Package' OSGi entry, it will be ignored" ); return packagesNotFound; } // use a technique similar to the Sieve of Eratosthenes: // create a set with all exported packages Clause[] clauses = Parser.parseHeader( exportPackage ); for ( Clause clause : clauses ) { packagesNotFound.add( clause.getName() ); } // then, for each package found in the bundle, drop it from the set JarEntry jarEntry = null; while ( ( jarEntry = input.getNextJarEntry() ) != null ) { String entryName = jarEntry.getName(); if ( jarEntry.isDirectory() && !skipDirs.matcher( entryName ).matches() ) { if ( File.separatorChar == entryName.charAt( entryName.length() - 1 ) ) { entryName = entryName.substring( 0, entryName.length() - 1 ); } String currentPackage = entryName.replace( File.separatorChar, '.' ); packagesNotFound.remove( currentPackage ); } } // if there is a package not found in the set, it is a misconfigured package return packagesNotFound; } catch ( IOException ioe ) { throw new MojoExecutionException( "An error occurred while reading manifest file " + bundle, ioe ); } finally { if ( input != null ) { try { input.close(); } catch ( IOException e ) { // close it quietly } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy