/* ========================================================================== * Copyright 2003-2004 Mevenide Team * * Licensed 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.codehaus.mojo.nbm; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.StringTokenizer; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.codehaus.plexus.util.StringUtils; /** * Tag examines the manifest of a jar file and retrieves netbeans specific information. * @author <a href="mailto:mkleint@codehaus.org">Milos Kleint</a> * */ public class ExamineManifest { private Log logger; private File jarFile; private File manifestFile; private boolean netbeansModule; private boolean osgiBundle; private boolean localized; private String specVersion; private String implVersion; private String module; private String moduleDeps; private String locBundle; private String classpath; private boolean publicPackages; private boolean populateDependencies = false; private List<String> dependencyTokens = Collections.<String>emptyList(); private boolean friendPackages = false; private List<String> friends = Collections.<String>emptyList(); private List<String> packages = Collections.<String>emptyList(); ExamineManifest( Log logger ) { this.logger = logger; } public void checkFile() throws MojoExecutionException { resetExamination(); Manifest mf = null; if ( jarFile != null ) { JarFile jar = null; try { jar = new JarFile( jarFile ); mf = jar.getManifest(); } catch ( Exception exc ) { throw new MojoExecutionException( "Could not open " + jarFile + ": " + exc.getMessage(), exc ); } finally { if ( jar != null ) { try { jar.close(); } catch ( IOException io ) { throw new MojoExecutionException( io.getMessage(), io ); } } } } else if ( manifestFile != null ) { InputStream stream = null; try { stream = new FileInputStream( manifestFile ); mf = new Manifest( stream ); } catch ( Exception exc ) { throw new MojoExecutionException( exc.getMessage(), exc ); } finally { if ( stream != null ) { try { stream.close(); } catch ( IOException io ) { throw new MojoExecutionException( io.getMessage(), io ); } } } } if ( mf != null ) { processManifest( mf ); } else { //MNBMODULE-22 File source = manifestFile; if ( source == null ) { source = jarFile; } if ( source == null ) { logger.debug( "No manifest to examine" ); } else { logger.debug( "Cannot find manifest entries in " + source.getAbsolutePath() ); } } } void resetExamination() { setNetbeansModule( false ); setLocalized( false ); setSpecVersion( null ); setImplVersion( null ); setModule( null ); setModuleDeps( null ); setLocBundle( null ); setPublicPackages( false ); setClasspath( "" ); } void processManifest( Manifest mf ) { Attributes attrs = mf.getMainAttributes(); setModule( attrs.getValue( "OpenIDE-Module" ) ); setNetbeansModule( getModule() != null ); if ( isNetbeansModule() ) { setLocBundle( attrs.getValue( "OpenIDE-Module-Localizing-Bundle" ) ); setLocalized( (getLocBundle() == null ? false : true) ); setSpecVersion( attrs.getValue( "OpenIDE-Module-Specification-Version" ) ); setImplVersion( attrs.getValue( "OpenIDE-Module-Implementation-Version" ) ); setModuleDeps( attrs.getValue( "OpenIDE-Module-Module-Dependencies" ) ); String cp = attrs.getValue( Attributes.Name.CLASS_PATH ); setClasspath( cp == null ? "" : cp ); String value = attrs.getValue( "OpenIDE-Module-Public-Packages" ); String frList = attrs.getValue( "OpenIDE-Module-Friends" ); if (value == null || value.trim().equals( "-" ) ) { setPublicPackages( false ); } else { if ( frList != null ) { setPublicPackages( false ); String[] friendList = StringUtils.stripAll( StringUtils.split( frList, ",") ); setFriends( Arrays.asList( friendList ) ); } else { setPublicPackages( true ); } String[] packageList = StringUtils.stripAll( StringUtils.split( value, ",") ); setPackages( Arrays.asList( packageList ) ); } if ( isPopulateDependencies() ) { String deps = attrs.getValue( "OpenIDE-Module-Module-Dependencies" ); if ( deps != null ) { StringTokenizer tokens = new StringTokenizer( deps, "," ); List<String> depList = new ArrayList<String>(); while ( tokens.hasMoreTokens() ) { String tok = tokens.nextToken(); //we are just interested in specification and loose dependencies. int spec = tok.indexOf( '>' ); if ( spec > 0 || (tok.indexOf( '=' ) == -1 && spec == -1) ) { if ( spec > 0 ) { tok = tok.substring( 0, spec ); } int slash = tok.indexOf( '/' ); if ( slash > 0 ) { tok = tok.substring( 0, slash ); } depList.add( tok.trim() ); } } setDependencyTokens( depList ); } } } else { //check osgi headers first, let nb stuff override it, making nb default String bndName = attrs.getValue("Bundle-SymbolicName"); if (bndName != null) { setOsgiBundle(true); setModule( bndName./*MNBMODULE-125*/replaceFirst(" *;.+", "")./*MNBMODULE-96*/replace('-', '_') ); setSpecVersion( attrs.getValue("Bundle-Version") ); String exp = attrs.getValue("Export-Package"); setPublicPackages(exp != null); } else { // for non-netbeans, non-osgi jars. setSpecVersion(attrs.getValue("Specification-Version")); setImplVersion(attrs.getValue("Implementation-Version")); setModule(attrs.getValue("Package")); setPublicPackages(false); setClasspath(""); /* if (module != null) { // now we have the package to make it a module definition, add the version there.. module = module + "/1"; } */ if (getModule() == null) { // do we want to do that? setModule(attrs.getValue("Extension-Name")); } } } } /** * Getter for property jarFile. * @return Value of property jarFile. */ public java.io.File getJarFile() { return jarFile; } /** * The jar file to examine. It is exclusive with manifestFile. */ public void setJarFile( java.io.File jarFileLoc ) { jarFile = jarFileLoc; } /** Getter for property manifestFile. * @return Value of property manifestFile. * */ public File getManifestFile() { return manifestFile; } /** * Manifest file to be examined. It is exclusing with jarFile. */ public void setManifestFile( File manifestFileLoc ) { manifestFile = manifestFileLoc; } /** * Either call {@link #setJarFile} or {@link #setManifestFile} as appropriate. * @param artifactFileLoc a JAR or folder */ public void setArtifactFile( File artifactFileLoc ) { if ( artifactFileLoc.isFile() ) { setJarFile( artifactFileLoc ); } else if ( artifactFileLoc.isDirectory() ) { File mani = new File( artifactFileLoc, "META-INF/MANIFEST.MF" ); if ( mani.isFile() ) { setManifestFile( mani ); } // else e.g. jarprj/target/classes has no manifest, so nothing to examine } else { throw new IllegalArgumentException( artifactFileLoc.getAbsolutePath() ); } } public void setClasspath( String path ) { classpath = path; } public String getClasspath() { return classpath; } public boolean isNetbeansModule() { return netbeansModule; } public void setNetbeansModule( boolean netbeansModule ) { this.netbeansModule = netbeansModule; } public boolean isLocalized() { return localized; } public void setLocalized( boolean localized ) { this.localized = localized; } public String getSpecVersion() { return specVersion; } public void setSpecVersion( String specVersion ) { this.specVersion = specVersion; } public String getImplVersion() { return implVersion; } public void setImplVersion( String implVersion ) { this.implVersion = implVersion; } /** * Code name base of the module only. * Does not include any release version. */ public String getModule() { return module != null ? module.replaceFirst( "/\\d+$", "" ) : module; } /** * Full name of module: code name base, then optionally slash and major release version. */ public String getModuleWithRelease() { return module; } public void setModule( String module ) { this.module = module; } public String getModuleDeps() { return moduleDeps; } public void setModuleDeps( String moduleDeps ) { this.moduleDeps = moduleDeps; } public String getLocBundle() { return locBundle; } public void setLocBundle( String locBundle ) { this.locBundle = locBundle; } /** * returns true if there are defined public packages and there is no friend * declaration. * @return */ public boolean hasPublicPackages() { return publicPackages; } public void setPublicPackages( boolean publicPackages ) { this.publicPackages = publicPackages; } public boolean isPopulateDependencies() { return populateDependencies; } public void setPopulateDependencies( boolean populateDependencies ) { this.populateDependencies = populateDependencies; } public List<String> getDependencyTokens() { return dependencyTokens; } public void setDependencyTokens( List<String> dependencyTokens ) { this.dependencyTokens = dependencyTokens; } /** * returns true if both public packages and friend list are declared. * @return */ public boolean hasFriendPackages() { return friendPackages; } private void setFriends( List<String> fr ) { friendPackages = true; friends = fr; } public List<String> getFriends() { return friends; } private void setPackages( List<String> pack ) { packages = pack; } /** * list of package statements from OpenIDE-Module-Public-Packages. * All items end with .* * * @return */ public List<String> getPackages() { return packages; } public boolean isOsgiBundle() { return osgiBundle; } public void setOsgiBundle(boolean osgiBundle) { this.osgiBundle = osgiBundle; } }