pax_global_header00006660000000000000000000000064116344553260014523gustar00rootroot0000000000000052 comment=9cc94673f4fe365d1558bc153ab29409d46f9188 maven-shared-jar-1.1/000077500000000000000000000000001163445532600145105ustar00rootroot00000000000000maven-shared-jar-1.1/pom.xml000066400000000000000000000101731163445532600160270ustar00rootroot00000000000000 4.0.0 org.apache.maven.shared maven-shared-components 15 maven-shared-jar 1.1 Maven JAR Utilities Utilities that help identify the contents of a JAR, including Java class analysis and Maven metadata analysis. scm:svn:http://svn.apache.org/repos/asf/maven/shared/tags/maven-shared-jar-1.1 scm:svn:https://svn.apache.org/repos/asf/maven/shared/tags/maven-shared-jar-1.1 http://svn.apache.org/viewvc/maven/shared/tags/maven-shared-jar-1.1 jira http://jira.codehaus.org/browse/MSHARED/component/13279 2.0.7 org.apache.maven maven-model ${mavenVersion} org.apache.maven maven-artifact ${mavenVersion} org.codehaus.plexus plexus-digest 1.0 org.apache.bcel bcel 5.2 commons-collections commons-collections 3.1 org.codehaus.plexus plexus-maven-plugin 1.3.5 descriptor maven-javadoc-plugin 2.2 ${basedir}/src/main/javadoc/overview.html todo a TODO: plexus.requirement f Plexus Requirement: plexus.component t Plexus Component: maven-shared-jar-1.1/src/000077500000000000000000000000001163445532600152775ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/000077500000000000000000000000001163445532600162235ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/000077500000000000000000000000001163445532600171445ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/000077500000000000000000000000001163445532600177335ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/000077500000000000000000000000001163445532600211545ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/000077500000000000000000000000001163445532600222625ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/000077500000000000000000000000001163445532600235305ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/000077500000000000000000000000001163445532600243045ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/JarAnalyzer.java000066400000000000000000000163621163445532600274010ustar00rootroot00000000000000package org.apache.maven.shared.jar; /* * 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. */ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipException; /** * Open a JAR file to be analyzed. Note that once created, the {@link #closeQuietly()} method should be called to * release the associated file handle. *

* Typical usage: *

 *  JarAnalyzer jar = new JarAnalyzer( jarFile );
 * 

* try * { * // do some analysis, such as: * jarClasses = jarClassAnalyzer.analyze( jar ); * } * finally * { * jar.closeQuietly(); * } *

* // use jar.getJarData() in some way, or the data returned by the JAR analyzer. jar itself can no longer be used. *

*

* Note: that the actual data is separated from this class by design to minimise the chance of forgetting to close the * JAR file. The {@link org.apache.maven.shared.jar.JarData} class exposed, as well as any data returned by actual * analyzers that use this class, can be used safely once this class is out of scope. * * @see org.apache.maven.shared.jar.identification.JarIdentificationAnalysis#analyze(JarAnalyzer) * @see org.apache.maven.shared.jar.classes.JarClassesAnalysis#analyze(JarAnalyzer) */ public class JarAnalyzer { /** * Pattern to filter JAR entries for class files. * * @todo why are inner classes and other potentially valid classes omitted? (It flukes it by finding everything after $) */ private static final Pattern CLASS_FILTER = Pattern.compile( "[A-Za-z0-9]*\\.class$" ); /** * Pattern to filter JAR entries for Maven POM files. */ private static final Pattern MAVEN_POM_FILTER = Pattern.compile( "META-INF/maven/.*/pom\\.xml$" ); /** * Pattern to filter JAR entries for text files that may contain a version. */ private static final Pattern VERSION_FILTER = Pattern.compile( "[Vv][Ee][Rr][Ss][Ii][Oo][Nn]" ); /** * The associated JAR file. */ private final JarFile jarFile; /** * Contains information about the data collected so far. */ private final JarData jarData; /** * Constructor. Opens the JAR file, so should be matched by a call to {@link #closeQuietly()}. * * @param file the JAR file to open * @throws java.io.IOException if there is a problem opening the JAR file, or reading the manifest. The JAR file will be closed if this occurs. */ public JarAnalyzer( File file ) throws IOException { try { this.jarFile = new JarFile( file ); } catch ( ZipException e ) { ZipException ioe = new ZipException( "Failed to open file " + file + " : " + e.getMessage() ); ioe.initCause( e ); throw ioe; } // Obtain entries list. List entries = Collections.list( jarFile.entries() ); // Sorting of list is done by name to ensure a bytecode hash is always consistent. Collections.sort( entries, new Comparator() { public int compare( Object o1, Object o2 ) { JarEntry entry1 = (JarEntry) o1; JarEntry entry2 = (JarEntry) o2; return entry1.getName().compareTo( entry2.getName() ); } } ); Manifest manifest; try { manifest = jarFile.getManifest(); } catch ( IOException e ) { closeQuietly(); throw e; } this.jarData = new JarData( file, manifest, entries ); } /** * Get the data for an individual entry in the JAR. The caller should closeQuietly the input stream, and should not retain * the stream as the JAR file may be closed elsewhere. * * @param entry the JAR entry to read from * @return the input stream of the individual JAR entry. * @throws java.io.IOException if there is a problem opening the individual entry */ public InputStream getEntryInputStream( JarEntry entry ) throws IOException { return jarFile.getInputStream( entry ); } /** * Close the associated JAR file, ignoring any errors that may occur. */ public void closeQuietly() { try { jarFile.close(); } catch ( IOException e ) { // not much we can do about it but ignore it } } /** * Filter a list of JAR entries against the pattern. * * @param pattern the pattern to filter against * @return the list of files found, in {@link java.util.jar.JarEntry} elements */ public List filterEntries( Pattern pattern ) { List ret = new ArrayList(); Iterator it = getEntries().iterator(); while ( it.hasNext() ) { JarEntry entry = (JarEntry) it.next(); Matcher mat = pattern.matcher( entry.getName() ); if ( mat.find() ) { ret.add( entry ); } } return ret; } /** * Get all the classes in the JAR. * * @return the list of files found, in {@link java.util.jar.JarEntry} elements */ public List getClassEntries() { return filterEntries( CLASS_FILTER ); } /** * Get all the Maven POM entries in the JAR. * * @return the list of files found, in {@link java.util.jar.JarEntry} elements */ public List getMavenPomEntries() { return filterEntries( MAVEN_POM_FILTER ); } /** * Get all the version text files in the JAR. * * @return the list of files found, in {@link java.util.jar.JarEntry} elements */ public List getVersionEntries() { return filterEntries( VERSION_FILTER ); } /** * Get all the contained files in the JAR. * * @return the list of files found, in {@link java.util.jar.JarEntry} elements */ public List getEntries() { return jarData.getEntries(); } /** * Get the file that was opened by this analyzer. * * @return the JAR file reference */ public File getFile() { return jarData.getFile(); } public JarData getJarData() { return jarData; } } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/JarData.java000066400000000000000000000101561163445532600264600ustar00rootroot00000000000000package org.apache.maven.shared.jar; /* * 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. */ import org.apache.maven.shared.jar.classes.JarClasses; import org.apache.maven.shared.jar.identification.JarIdentification; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.util.Collections; import java.util.List; import java.util.jar.Attributes; import java.util.jar.Manifest; /** * Class that contains details of a single JAR file and it's entries. */ public final class JarData { /** * The JAR file. */ private final File file; /** * Whether the JAR file is sealed. */ private final boolean sealed; /** * The hashcode for the entire file's contents. */ private String fileHash; /** * The hashcode for the file's class data contents. */ private String bytecodeHash; /** * The JAR's manifest. */ private final Manifest manifest; /** * Information about the JAR's classes. */ private JarClasses jarClasses; /** * The JAR entries. */ private final List entries; /** * Information about the JAR's identifying features. */ private JarIdentification jarIdentification; /** * Constructor. * * @param file the JAR file * @param manifest the JAR manifest * @param entries the JAR entries */ public JarData( File file, Manifest manifest, List entries ) { this.file = file; this.manifest = manifest; this.entries = Collections.unmodifiableList( entries ); boolean sealed = false; if ( this.manifest != null ) { String sval = this.manifest.getMainAttributes().getValue( Attributes.Name.SEALED ); if ( StringUtils.isNotEmpty( sval ) ) { sealed = "true".equalsIgnoreCase( sval.trim() ); } } this.sealed = sealed; } public List getEntries() { return entries; } public Manifest getManifest() { return manifest; } public File getFile() { return file; } public boolean isSealed() { return sealed; } public void setFileHash( String fileHash ) { this.fileHash = fileHash; } public String getFileHash() { return fileHash; } public void setBytecodeHash( String bytecodeHash ) { this.bytecodeHash = bytecodeHash; } public String getBytecodeHash() { return bytecodeHash; } public boolean isDebugPresent() { return jarClasses.isDebugPresent(); } public void setJarClasses( JarClasses jarClasses ) { this.jarClasses = jarClasses; } public int getNumEntries() { return entries.size(); } public int getNumClasses() { return jarClasses.getClassNames().size(); } public int getNumPackages() { return jarClasses.getPackages().size(); } public String getJdkRevision() { return jarClasses.getJdkRevision(); } public void setJarIdentification( JarIdentification jarIdentification ) { this.jarIdentification = jarIdentification; } public JarIdentification getJarIdentification() { return jarIdentification; } public JarClasses getJarClasses() { return jarClasses; } } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/classes/000077500000000000000000000000001163445532600257415ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/classes/ImportVisitor.java000066400000000000000000000125201163445532600314360ustar00rootroot00000000000000package org.apache.maven.shared.jar.classes; /* * 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. */ import org.apache.bcel.classfile.ConstantClass; import org.apache.bcel.classfile.ConstantUtf8; import org.apache.bcel.classfile.EmptyVisitor; import org.apache.bcel.classfile.JavaClass; import org.apache.commons.collections.list.SetUniqueList; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Implementation of a BCEL class visitor that analyzes a class and collects imports. */ public class ImportVisitor extends EmptyVisitor { /** * The list of imports discovered. */ private List imports; /** * The Java class that is being analyzed. */ private JavaClass javaClass; /** * Pattern to detect if the import is qualified and allows retrieval of the actual import name from the string via the group 1. */ private static final Pattern QUALIFIED_IMPORT_PATTERN = Pattern.compile( "L([a-zA-Z][a-zA-Z0-9\\.]+);" ); /** * Pattern that checks whether a string is valid UTF-8. Imports that are not are ignored. */ private static final Pattern VALID_UTF8_PATTERN = Pattern.compile( "^[\\(\\)\\[A-Za-z0-9;/]+$" ); /** * Create an Import visitor. * * @param javaClass the javaclass to work from */ public ImportVisitor( JavaClass javaClass ) { this.javaClass = javaClass; // Create a list that is guaranteed to be unique while retaining it's list qualities (LinkedHashSet does not // expose the list interface even if natural ordering is retained) this.imports = SetUniqueList.decorate( new ArrayList() ); } /** * Get the list of discovered imports. * * @return Returns the imports. */ public List getImports() { return imports; } /** * Find any formally declared import in the Constant Pool. * * @see org.apache.bcel.classfile.EmptyVisitor#visitConstantClass(org.apache.bcel.classfile.ConstantClass) */ public void visitConstantClass( ConstantClass constantClass ) { String name = constantClass.getBytes( javaClass.getConstantPool() ); // only strings with '/' character are to be considered. if ( name.indexOf( '/' ) == -1 ) { return; } name = name.replace( '/', '.' ); if ( name.endsWith( ".class" ) ) { name = name.substring( 0, name.length() - 6 ); } Matcher mat = QUALIFIED_IMPORT_PATTERN.matcher( name ); if ( mat.find() ) { this.imports.add( mat.group( 1 ) ); } else { this.imports.add( name ); } } /** * Find any package class Strings in the UTF8 String Pool. * * @see org.apache.bcel.classfile.EmptyVisitor#visitConstantUtf8(org.apache.bcel.classfile.ConstantUtf8) */ public void visitConstantUtf8( ConstantUtf8 constantUtf8 ) { String ret = constantUtf8.getBytes().trim(); // empty strings are not class names. if ( ret.length() <= 0 ) { return; } // Only valid characters please. if ( !VALID_UTF8_PATTERN.matcher( ret ).matches() ) { return; } // only strings with '/' character are to be considered. if ( ret.indexOf( '/' ) == -1 ) { return; } // Strings that start with '/' are bad too // Seen when Pool has regex patterns. if ( ret.charAt( 0 ) == '/' ) { return; } // Make string more class-like. ret = ret.replace( '/', '.' ); // Double ".." indicates a bad class fail-fast. // Seen when ConstantUTF8 Pool has regex patterns. if ( ret.indexOf( ".." ) != -1 ) { return; } Matcher mat = QUALIFIED_IMPORT_PATTERN.matcher( ret ); char prefix = ret.charAt( 0 ); if ( prefix == '(' ) { // A Method Declaration. // Loop for each Qualified Class found. while ( mat.find() ) { this.imports.add( mat.group( 1 ) ); } } else { // A Variable Declaration. if ( mat.find() ) { // Add a UTF8 Qualified Class reference. this.imports.add( mat.group( 1 ) ); } else { // Add a simple Class reference. this.imports.add( ret ); } } } } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/classes/JarClasses.java000066400000000000000000000102001163445532600306270ustar00rootroot00000000000000package org.apache.maven.shared.jar.classes; /* * 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. */ import org.apache.commons.collections.list.SetUniqueList; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Gathered facts about the classes within a JAR file. * * @see org.apache.maven.shared.jar.classes.JarClassesAnalysis#analyze(org.apache.maven.shared.jar.JarAnalyzer) */ public class JarClasses { /** * The list of imports in the classes in the JAR. */ private List imports; /** * A list of packages represented by classes in the JAR. */ private List packages; /** * A list of the classes that in the JAR. */ private List classNames; /** * A list of methods within the classes in the JAR. */ private List methods; /** * Whether the JAR contains any code with debug information. If there is a mix of debug and release code, this will * still be true. */ private boolean isDebugPresent; /** * The highest JVM revision available in any class files. While the JAR may work on earlier JVMs if particular * classes are not used, this is the minimum JVM that guarantees compatibility. */ private String jdkRevision; /** * Constructor to create an empty instance. */ public JarClasses() { // Unique list decorators are used to ensure natural ordering is retained, the list interface is availble, and // that duplicates are not entered. imports = SetUniqueList.decorate( new ArrayList() ); packages = SetUniqueList.decorate( new ArrayList() ); classNames = SetUniqueList.decorate( new ArrayList() ); methods = SetUniqueList.decorate( new ArrayList() ); } /** * Add a discovered class to the record. * * @param name the name of the class */ public void addClassName( String name ) { this.classNames.add( name ); } /** * Add a discovered package to the record. * * @param name the name of the package */ public void addPackage( String name ) { this.packages.add( name ); } /** * Add a discovered method to the record. * * @param name the name of the method */ public void addMethod( String name ) { this.methods.add( name ); } /** * Add a list of discovered imports to the record. * * @param imports the imports to add. Each item should be a String to avoid down the line ClassCastExceptions. */ public void addImports( List imports ) { this.imports.addAll( imports ); } public List getImports() { return Collections.unmodifiableList( imports ); } public List getClassNames() { return Collections.unmodifiableList( classNames ); } public List getPackages() { return Collections.unmodifiableList( packages ); } public boolean isDebugPresent() { return isDebugPresent; } public void setDebugPresent( boolean hasDebugSymbols ) { this.isDebugPresent = hasDebugSymbols; } public String getJdkRevision() { return jdkRevision; } public void setJdkRevision( String jdkRevision ) { this.jdkRevision = jdkRevision; } public List getMethods() { return Collections.unmodifiableList( methods ); } } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/classes/JarClassesAnalysis.java000066400000000000000000000155721163445532600323540ustar00rootroot00000000000000package org.apache.maven.shared.jar.classes; /* * 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. */ import org.apache.bcel.classfile.ClassFormatException; import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.DescendingVisitor; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.LineNumberTable; import org.apache.bcel.classfile.Method; import org.apache.maven.shared.jar.JarAnalyzer; import org.codehaus.plexus.logging.AbstractLogEnabled; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.jar.JarEntry; /** * Analyze the classes in a JAR file. This class is thread safe and immutable as it retains no state. *

* Note that you must first create an instance of {@link org.apache.maven.shared.jar.JarAnalyzer} - see its Javadoc for * a typical use. * * @plexus.component role="org.apache.maven.shared.jar.classes.JarClassesAnalysis" role-hint="default" * @see #analyze(org.apache.maven.shared.jar.JarAnalyzer) */ public class JarClassesAnalysis extends AbstractLogEnabled { private static final double JAVA_1_6_CLASS_VERSION = 50.0; private static final double JAVA_1_5_CLASS_VERSION = 49.0; private static final double JAVA_1_4_CLASS_VERSION = 47.0; private static final double JAVA_1_3_CLASS_VERSION = 46.0; private static final double JAVA_1_2_CLASS_VERSION = 45.65536; private static final double JAVA_1_1_CLASS_VERSION = 45.3; /** * Analyze a JAR and find any classes and their details. Note that if the provided JAR analyzer has previously * analyzed the JAR, the cached results will be returned. You must obtain a new JAR analyzer to the re-read the * contents of the file. * * @param jarAnalyzer the JAR to analyze. This must not yet have been closed. * @return the details of the classes found */ public JarClasses analyze( JarAnalyzer jarAnalyzer ) { JarClasses classes = jarAnalyzer.getJarData().getJarClasses(); if ( classes == null ) { String jarfilename = jarAnalyzer.getFile().getAbsolutePath(); classes = new JarClasses(); List classList = jarAnalyzer.getClassEntries(); classes.setDebugPresent( false ); double maxVersion = 0.0; Iterator it = classList.iterator(); while ( it.hasNext() ) { JarEntry entry = (JarEntry) it.next(); String classname = entry.getName(); try { ClassParser classParser = new ClassParser( jarfilename, classname ); JavaClass javaClass = classParser.parse(); String classSignature = javaClass.getClassName(); if ( !classes.isDebugPresent() ) { if ( hasDebugSymbols( javaClass ) ) { classes.setDebugPresent( true ); } } double classVersion = javaClass.getMajor(); if ( javaClass.getMinor() > 0 ) { classVersion = classVersion + 1 / (double) javaClass.getMinor(); } if ( classVersion > maxVersion ) { maxVersion = classVersion; } Method[] methods = javaClass.getMethods(); for ( int i = 0; i < methods.length; i++ ) { classes.addMethod( classSignature + "." + methods[i].getName() + methods[i].getSignature() ); } String classPackageName = javaClass.getPackageName(); classes.addClassName( classSignature ); classes.addPackage( classPackageName ); ImportVisitor importVisitor = new ImportVisitor( javaClass ); DescendingVisitor descVisitor = new DescendingVisitor( javaClass, importVisitor ); javaClass.accept( descVisitor ); classes.addImports( importVisitor.getImports() ); } catch ( ClassFormatException e ) { getLogger().warn( "Unable to process class " + classname + " in JarAnalyzer File " + jarfilename, e ); } catch ( IOException e ) { getLogger().warn( "Unable to process JarAnalyzer File " + jarfilename, e ); } } // TODO: check these since they are > instead of >= if ( maxVersion >= JAVA_1_6_CLASS_VERSION ) { classes.setJdkRevision( "1.6" ); } else if ( maxVersion >= JAVA_1_5_CLASS_VERSION ) { classes.setJdkRevision( "1.5" ); } else if ( maxVersion > JAVA_1_4_CLASS_VERSION ) { classes.setJdkRevision( "1.4" ); } else if ( maxVersion > JAVA_1_3_CLASS_VERSION ) { classes.setJdkRevision( "1.3" ); } else if ( maxVersion > JAVA_1_2_CLASS_VERSION ) { classes.setJdkRevision( "1.2" ); } else if ( maxVersion > JAVA_1_1_CLASS_VERSION ) { classes.setJdkRevision( "1.1" ); } else if ( maxVersion > 0 ) { classes.setJdkRevision( "1.0" ); } jarAnalyzer.getJarData().setJarClasses( classes ); } return classes; } private boolean hasDebugSymbols( JavaClass javaClass ) { boolean ret = false; Method[] methods = javaClass.getMethods(); for ( int i = 0; i < methods.length; i++ ) { LineNumberTable linenumbers = methods[i].getLineNumberTable(); if ( linenumbers != null && linenumbers.getLength() > 0 ) { ret = true; break; } } return ret; } } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/000077500000000000000000000000001163445532600272755ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/JarIdentification.java000066400000000000000000000143331163445532600335320ustar00rootroot00000000000000package org.apache.maven.shared.jar.identification; /* * 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. */ import java.util.ArrayList; import java.util.List; /** * Gathered Maven information about the JAR file. Stores both assumed/validated values and potential values. * * @see org.apache.maven.shared.jar.identification.JarIdentificationAnalysis#analyze(org.apache.maven.shared.jar.JarAnalyzer) */ public class JarIdentification { /** * The group ID derived or guessed from the list of potentials of the JAR. */ private String groupId; /** * The artifact ID derived or guessed from the list of potentials of the JAR. */ private String artifactId; /** * The version derived or guessed from the list of potentials of the JAR. */ private String version; /** * The project name derived or guessed from the list of potentials of the JAR. */ private String name; /** * The vendor (organization name) derived or guessed from the list of potentials of the JAR. */ private String vendor; /** * The list of possible group IDs discovered. */ private List potentialGroupIds = new ArrayList(); /** * The list of possible artifact IDs discovered. */ private List potentialArtifactIds = new ArrayList(); /** * The list of possible versions discovered. */ private List potentialVersions = new ArrayList(); /** * The list of possible artifact names discovered. */ private List potentialNames = new ArrayList(); /** * The list of possible vendors discovered. */ private List potentialVendors = new ArrayList(); /** * Add a validated group ID. * * @param groupId the group ID discovered */ public void addAndSetGroupId( String groupId ) { if ( groupId != null ) { this.groupId = groupId; } addGroupId( groupId ); } /** * Add a potential group ID. * * @param groupId the group ID discovered */ public void addGroupId( String groupId ) { addUnique( potentialGroupIds, groupId ); } /** * Add a validated artifact ID. * * @param artifactId the artifact ID discovered */ public void addAndSetArtifactId( String artifactId ) { if ( artifactId != null ) { this.artifactId = artifactId; } addArtifactId( artifactId ); } /** * Add a potential artifact ID. * * @param artifactId the artifact ID discovered */ public void addArtifactId( String artifactId ) { addUnique( potentialArtifactIds, artifactId ); } /** * Add a validated version. * * @param version the version discovered */ public void addAndSetVersion( String version ) { if ( version != null ) { this.version = version; } addVersion( version ); } /** * Add a potential version. * * @param version the version discovered */ public void addVersion( String version ) { addUnique( potentialVersions, version ); } /** * Add a validated vendor name. * * @param name the vendor name discovered */ public void addAndSetVendor( String name ) { if ( name != null ) { vendor = name; } addVendor( name ); } /** * Add a potential vendor name. * * @param name the vendor name discovered */ public void addVendor( String name ) { addUnique( potentialVendors, name ); } /** * Add a validated artifact name. * * @param name the artifact name discovered */ public void addAndSetName( String name ) { if ( name != null ) { this.name = name; } addName( name ); } /** * Add a potential artifact name. * * @param name the artifact name discovered */ public void addName( String name ) { addUnique( potentialNames, name ); } private static void addUnique( List list, String value ) { if ( value != null ) { if ( !list.contains( value ) ) { list.add( value ); } } } public String getArtifactId() { return artifactId; } public void setArtifactId( String artifactId ) { this.artifactId = artifactId; } public String getGroupId() { return groupId; } public void setGroupId( String groupId ) { this.groupId = groupId; } public String getName() { return name; } public void setName( String name ) { this.name = name; } public String getVendor() { return vendor; } public void setVendor( String vendor ) { this.vendor = vendor; } public String getVersion() { return version; } public void setVersion( String version ) { this.version = version; } public List getPotentialVersions() { return potentialVersions; } public List getPotentialNames() { return potentialNames; } public List getPotentialGroupIds() { return potentialGroupIds; } public List getPotentialArtifactIds() { return potentialArtifactIds; } public List getPotentialVendors() { return potentialVendors; } } JarIdentificationAnalysis.java000066400000000000000000000121751163445532600351610ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identificationpackage org.apache.maven.shared.jar.identification; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.codehaus.plexus.util.StringUtils; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * Analyze the JAR file to identify Maven artifact metadata. This class is thread safe and immutable as long as all * provided exposers are, as it retains no state. *

* If using Plexus, the class will use all available exposers in the container. *

* If not using Plexus, the exposers must be set using {@link #setExposers(java.util.List)} before calling * {@link #analyze(org.apache.maven.shared.jar.JarAnalyzer)} *

* Note that you must first create an instance of {@link org.apache.maven.shared.jar.JarAnalyzer} - see its Javadoc for * a typical use. * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationAnalysis" role-hint="default" */ public class JarIdentificationAnalysis { /** * The Maven information exposers to use during identification. * * @plexus.requirement role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" */ private List exposers; /** * Analyze a JAR and find any associated Maven metadata. Note that if the provided JAR analyzer has previously * analyzed the JAR, the cached results will be returned. You must obtain a new JAR analyzer to the re-read the * contents of the file. * * @param jarAnalyzer the JAR to analyze. This must not yet have been closed. * @return the Maven metadata discovered */ public JarIdentification analyze( JarAnalyzer jarAnalyzer ) { JarIdentification taxon = jarAnalyzer.getJarData().getJarIdentification(); if ( taxon != null ) { return taxon; } taxon = new JarIdentification(); for ( Iterator i = exposers.iterator(); i.hasNext(); ) { JarIdentificationExposer exposer = (JarIdentificationExposer) i.next(); exposer.expose( taxon, jarAnalyzer ); } normalize( taxon ); jarAnalyzer.getJarData().setJarIdentification( taxon ); return taxon; } private void normalize( JarIdentification taxon ) { if ( StringUtils.isEmpty( taxon.getGroupId() ) ) { taxon.setGroupId( pickSmallest( taxon.getPotentialGroupIds() ) ); } if ( StringUtils.isEmpty( taxon.getArtifactId() ) ) { taxon.setArtifactId( pickLargest( taxon.getPotentialArtifactIds() ) ); } if ( StringUtils.isEmpty( taxon.getVersion() ) ) { taxon.setVersion( pickSmallest( taxon.getPotentialVersions() ) ); } if ( StringUtils.isEmpty( taxon.getName() ) ) { taxon.setName( pickLargest( taxon.getPotentialNames() ) ); } if ( StringUtils.isEmpty( taxon.getVendor() ) ) { taxon.setVendor( pickLargest( taxon.getPotentialVendors() ) ); } } private String pickSmallest( List list ) { String smallest = null; if ( !list.isEmpty() ) { int size = Integer.MAX_VALUE; Iterator it = list.iterator(); while ( it.hasNext() ) { String val = (String) it.next(); if ( StringUtils.isNotEmpty( val ) ) { if ( val.length() < size ) { smallest = val; size = val.length(); } } } } return smallest; } private String pickLargest( List list ) { String largest = null; if ( !list.isEmpty() ) { int size = Integer.MIN_VALUE; Iterator it = list.iterator(); while ( it.hasNext() ) { String val = (String) it.next(); if ( StringUtils.isNotEmpty( val ) ) { if ( val.length() > size ) { largest = val; size = val.length(); } } } } return largest; } public void setExposers( List exposers ) { this.exposers = Collections.unmodifiableList( exposers ); } } JarIdentificationExposer.java000066400000000000000000000031601163445532600350150ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identificationpackage org.apache.maven.shared.jar.identification; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; /** * Expose information from a JAR during the identification process. Implementations should be made to be thread safe. * * @see org.apache.maven.shared.jar.identification.JarIdentificationAnalysis */ public interface JarIdentificationExposer { /** * Expose metadata during the identification process. * * @param identification the identification record to populate with the exposed metadata * @param jarAnalyzer the JAR to obtain the information from. Should be treated as read only, with the exception * of caching the metadata if it would be identical when run over the same file again. */ void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ); } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposers/000077500000000000000000000000001163445532600311455ustar00rootroot00000000000000EmbeddedMavenModelExposer.java000066400000000000000000000072001163445532600367370ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.model.Model; import org.apache.maven.model.Organization; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import java.util.jar.JarEntry; /** * Exposer that examines a JAR file for any embedded Maven metadata for identification. * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="embeddedMavenModel" */ public class EmbeddedMavenModelExposer extends AbstractLogEnabled implements JarIdentificationExposer { public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { List entries = jarAnalyzer.getMavenPomEntries(); if ( entries.isEmpty() ) { return; } if ( entries.size() > 1 ) { getLogger().warn( "More than one Maven model entry was found in the JAR, using only the first of: " + entries ); } JarEntry pom = (JarEntry) entries.get( 0 ); MavenXpp3Reader pomreader = new MavenXpp3Reader(); InputStream is = null; try { is = jarAnalyzer.getEntryInputStream( pom ); InputStreamReader isreader = new InputStreamReader( is ); Model model = pomreader.read( isreader ); identification.addAndSetGroupId( model.getGroupId() ); identification.addAndSetArtifactId( model.getArtifactId() ); identification.addAndSetVersion( model.getVersion() ); identification.addAndSetName( model.getName() ); // TODO: suboptimal - we are reproducing Maven's built in default if ( model.getName() == null ) { identification.addAndSetName( model.getArtifactId() ); } Organization org = model.getOrganization(); if ( org != null ) { identification.addAndSetVendor( org.getName() ); } } catch ( IOException e ) { getLogger().error( "Unable to read model " + pom.getName() + " in " + jarAnalyzer.getFile() + ".", e ); } catch ( XmlPullParserException e ) { getLogger().error( "Unable to parse model " + pom.getName() + " in " + jarAnalyzer.getFile() + ".", e ); } finally { IOUtil.close( is ); } } } FilenameExposer.java000066400000000000000000000043561163445532600350270ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import org.codehaus.plexus.util.FileUtils; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Exposer that examines a JAR file to derive Maven metadata from the pattern of the JAR's filename. * Will match the format artifactId-version.jar. * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="filename" */ public class FilenameExposer implements JarIdentificationExposer { private static final Pattern VERSION_PATTERN = Pattern.compile( "-[0-9]" ); public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { String filename = FileUtils.removeExtension( jarAnalyzer.getFile().getName() ); Matcher mat = VERSION_PATTERN.matcher( filename ); if ( mat.find() ) { String prefix = filename.substring( 0, mat.start() ); identification.addArtifactId( prefix ); identification.addName( prefix ); identification.addVersion( filename.substring( mat.end() - 1 ) ); } else { identification.addArtifactId( filename ); identification.addName( filename ); } } } JarClassesExposer.java000066400000000000000000000044721163445532600353400ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.classes.JarClasses; import org.apache.maven.shared.jar.classes.JarClassesAnalysis; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import java.util.Iterator; /** * Exposer that examines a JAR file to derive Maven metadata from the classes in a JAR. It will currently identify * potential group IDs from the class packages. *

* Note: if not being used from Plexus, the {@link #setAnalyzer(org.apache.maven.shared.jar.classes.JarClassesAnalysis)} * method must be called to avoid a NullPointerException during the expose method. * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="jarClasses" */ public class JarClassesExposer implements JarIdentificationExposer { /** * @plexus.requirement */ private JarClassesAnalysis analyzer; public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { JarClasses jarclasses = analyzer.analyze( jarAnalyzer ); Iterator it = jarclasses.getPackages().iterator(); while ( it.hasNext() ) { String packagename = (String) it.next(); identification.addGroupId( packagename ); } } public void setAnalyzer( JarClassesAnalysis analyzer ) { this.analyzer = analyzer; } } ManifestExposer.java000066400000000000000000000055351163445532600350550ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import java.util.Iterator; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.Manifest; /** * Exposer that examines a JAR's manifest to derive Maven metadata. * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="manifest" */ public class ManifestExposer implements JarIdentificationExposer { public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { Manifest manifest = jarAnalyzer.getJarData().getManifest(); if ( manifest != null ) { addManifestAttributeValues( manifest.getMainAttributes(), identification ); Map entries = manifest.getEntries(); Iterator itentries = entries.entrySet().iterator(); while ( itentries.hasNext() ) { Map.Entry entry = (Map.Entry) itentries.next(); Attributes attribs = (Attributes) entry.getValue(); addManifestAttributeValues( attribs, identification ); } } } private void addManifestAttributeValues( Attributes attribs, JarIdentification identification ) { identification.addName( attribs.getValue( Attributes.Name.IMPLEMENTATION_TITLE ) ); identification.addVersion( attribs.getValue( Attributes.Name.IMPLEMENTATION_VERSION ) ); identification.addVendor( attribs.getValue( Attributes.Name.IMPLEMENTATION_VENDOR ) ); identification.addName( attribs.getValue( Attributes.Name.SPECIFICATION_TITLE ) ); identification.addVersion( attribs.getValue( Attributes.Name.SPECIFICATION_VERSION ) ); identification.addVendor( attribs.getValue( Attributes.Name.SPECIFICATION_VENDOR ) ); identification.addGroupId( attribs.getValue( Attributes.Name.EXTENSION_NAME ) ); } } RepositorySearchExposer.java000066400000000000000000000102721163445532600366060ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.artifact.Artifact; import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import org.apache.maven.shared.jar.identification.hash.JarHashAnalyzer; import org.apache.maven.shared.jar.identification.repository.RepositoryHashSearch; import org.codehaus.plexus.logging.AbstractLogEnabled; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Exposer that examines a Maven repository for identical files to the JAR being analyzed. It will look for both * identical files, and files with identical classes. *

* Note: if not using Plexus, you must call the following methods to be able to expose any data from the class: * {@link #setBytecodeHashAnalyzer(org.apache.maven.shared.jar.identification.hash.JarHashAnalyzer)}, * {@link #setFileHashAnalyzer(org.apache.maven.shared.jar.identification.hash.JarHashAnalyzer)}, * {@link #setRepositoryHashSearch(org.apache.maven.shared.jar.identification.repository.RepositoryHashSearch)} * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="repositorySearch" */ public class RepositorySearchExposer extends AbstractLogEnabled implements JarIdentificationExposer { /** * The repository searcher to use. * * @plexus.requirement * @todo this currently only provides for the 'empty' repository search, which isn't very useful */ private RepositoryHashSearch repositoryHashSearch; /** * The hash analyzer for the entire file. * * @plexus.requirement role-hint="file" */ private JarHashAnalyzer fileHashAnalyzer; /** * The hash analyzer for the file's bytecode. * * @plexus.requirement role-hint="bytecode" */ private JarHashAnalyzer bytecodeHashAnalyzer; public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { List repohits = new ArrayList(); String hash = fileHashAnalyzer.computeHash( jarAnalyzer ); if ( hash != null ) { repohits.addAll( repositoryHashSearch.searchFileHash( hash ) ); } String bytecodehash = bytecodeHashAnalyzer.computeHash( jarAnalyzer ); if ( bytecodehash != null ) { repohits.addAll( repositoryHashSearch.searchBytecodeHash( bytecodehash ) ); } if ( !repohits.isEmpty() ) { // Found hits in the repository. Iterator it = repohits.iterator(); while ( it.hasNext() ) { Artifact artifact = (Artifact) it.next(); identification.addAndSetGroupId( artifact.getGroupId() ); identification.addAndSetArtifactId( artifact.getArtifactId() ); identification.addAndSetVersion( artifact.getVersion() ); } } } public void setRepositoryHashSearch( RepositoryHashSearch repo ) { this.repositoryHashSearch = repo; } public void setFileHashAnalyzer( JarHashAnalyzer fileHashAnalyzer ) { this.fileHashAnalyzer = fileHashAnalyzer; } public void setBytecodeHashAnalyzer( JarHashAnalyzer bytecodeHashAnalyzer ) { this.bytecodeHashAnalyzer = bytecodeHashAnalyzer; } } StaticMainOutputExposer.java000066400000000000000000000042051163445532600365550ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * Exposer that examines a a JAR for classes that have Version in the name and calls their * main method if it exists to obtain the version. * * @todo not currently implemented * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="staticMainOutput" */ public class StaticMainOutputExposer implements JarIdentificationExposer { public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { List staticMains = findStaticMainVersions(); if ( !staticMains.isEmpty() ) { Iterator itvers = staticMains.iterator(); while ( itvers.hasNext() ) { String ver = (String) itvers.next(); identification.addVersion( ver ); } } } private List findStaticMainVersions() { // TODO: Execute the static main methods of classes with 'Version' in their name. return Collections.EMPTY_LIST; } } TextFileExposer.java000066400000000000000000000072051163445532600350270ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.jar.JarEntry; /** * Exposer that examines a a JAR for files that contain the text version (case-insensitive) and * adds the contents as potential version(s). * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="textFile" */ public class TextFileExposer extends AbstractLogEnabled implements JarIdentificationExposer { public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { List textFiles = findTextFileVersions( jarAnalyzer ); if ( !textFiles.isEmpty() ) { Iterator ithits = textFiles.iterator(); while ( ithits.hasNext() ) { String ver = (String) ithits.next(); identification.addVersion( ver ); } } } private List findTextFileVersions( JarAnalyzer jarAnalyzer ) { List textVersions = new ArrayList(); List hits = jarAnalyzer.getVersionEntries(); Iterator it = hits.iterator(); while ( it.hasNext() ) { JarEntry entry = (JarEntry) it.next(); // skip this entry if it's a class file. if ( !entry.getName().endsWith( ".class" ) ) //$NON-NLS-1$ { getLogger().debug( "Version Hit: " + entry.getName() ); InputStream is = null; try { is = jarAnalyzer.getEntryInputStream( entry ); BufferedReader br = new BufferedReader( new InputStreamReader( is ) ); String line = br.readLine(); // TODO: check for key=value pair. // TODO: maybe even for groupId entries. getLogger().debug( line ); if ( StringUtils.isNotEmpty( line ) ) { textVersions.add( line ); } } catch ( IOException e ) { getLogger().warn( "Unable to read line from " + entry.getName(), e ); } finally { IOUtil.close( is ); } } } return textVersions; } } TimestampExposer.java000066400000000000000000000052361163445532600352500ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.commons.collections.Bag; import org.apache.commons.collections.bag.HashBag; import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import org.apache.maven.shared.jar.identification.JarIdentificationExposer; import org.codehaus.plexus.util.StringUtils; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.jar.JarEntry; /** * Exposer that examines a a JAR and uses the most recent timestamp as a potential version. * * @plexus.component role="org.apache.maven.shared.jar.identification.JarIdentificationExposer" role-hint="timestamp" */ public class TimestampExposer implements JarIdentificationExposer { public void expose( JarIdentification identification, JarAnalyzer jarAnalyzer ) { List entries = jarAnalyzer.getEntries(); SimpleDateFormat tsformat = new SimpleDateFormat( "yyyyMMdd", Locale.US ); //$NON-NLS-1$ Bag timestamps = new HashBag(); Iterator it = entries.iterator(); while ( it.hasNext() ) { JarEntry entry = (JarEntry) it.next(); long time = entry.getTime(); String timestamp = tsformat.format( new Date( time ) ); timestamps.add( timestamp ); } it = timestamps.iterator(); String ts = ""; int tsmax = 0; while ( it.hasNext() ) { String timestamp = (String) it.next(); int count = timestamps.getCount( timestamp ); if ( count > tsmax ) { ts = timestamp; tsmax = count; } } if ( StringUtils.isNotEmpty( ts ) ) { identification.addVersion( ts ); } } } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/hash/000077500000000000000000000000001163445532600302205ustar00rootroot00000000000000JarBytecodeHashAnalyzer.java000066400000000000000000000064771163445532600355270ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/hashpackage org.apache.maven.shared.jar.identification.hash; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.JarData; import org.codehaus.plexus.digest.DigesterException; import org.codehaus.plexus.digest.StreamingDigester; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.util.IOUtil; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.jar.JarEntry; /** * Analyzer that calculates the hash code for the entire file. Can be used to detect an exact copy of the file's class * data. Useful to see thru a recompile, recompression, or timestamp change. *

* If you are not using Plexus, you must call {@link #setDigester(org.codehaus.plexus.digest.StreamingDigester)} before use * * @plexus.component role="org.apache.maven.shared.jar.identification.hash.JarHashAnalyzer" role-hint="bytecode" */ public class JarBytecodeHashAnalyzer extends AbstractLogEnabled implements JarHashAnalyzer { /** * The streaming digester to use for computing the hash. Under Plexus, the default is SHA-1. * * @plexus.requirement role-hint="sha1" */ private StreamingDigester digester; public String computeHash( JarAnalyzer jarAnalyzer ) { JarData jarData = jarAnalyzer.getJarData(); String result = jarData.getBytecodeHash(); if ( result == null ) { Iterator it = jarAnalyzer.getClassEntries().iterator(); try { digester.reset(); while ( it.hasNext() ) { JarEntry entry = (JarEntry) it.next(); computeEntryBytecodeHash( jarAnalyzer.getEntryInputStream( entry ) ); } result = digester.calc(); jarData.setBytecodeHash( result ); } catch ( DigesterException e ) { getLogger().warn( "Unable to calculate the hashcode.", e ); } catch ( IOException e ) { getLogger().warn( "Unable to calculate the hashcode.", e ); } } return result; } private void computeEntryBytecodeHash( InputStream is ) throws IOException, DigesterException { try { digester.update( is ); } finally { IOUtil.close( is ); } } public void setDigester( StreamingDigester digester ) { this.digester = digester; } } JarFileHashAnalyzer.java000066400000000000000000000045241163445532600346370ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/hashpackage org.apache.maven.shared.jar.identification.hash; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.JarData; import org.codehaus.plexus.digest.Digester; import org.codehaus.plexus.digest.DigesterException; import org.codehaus.plexus.logging.AbstractLogEnabled; /** * Analyzer that calculates the hash code for the entire file. Can be used to detect an exact copy of the file. *

* If you are not using Plexus, you must call {@link #setDigester(org.codehaus.plexus.digest.Digester)} before use * * @plexus.component role="org.apache.maven.shared.jar.identification.hash.JarHashAnalyzer" role-hint="file" */ public class JarFileHashAnalyzer extends AbstractLogEnabled implements JarHashAnalyzer { /** * The digester to use for computing the hash. Under Plexus, the default is SHA-1. * * @plexus.requirement role-hint="sha1" */ private Digester digester; public String computeHash( JarAnalyzer jarAnalyzer ) { JarData jarData = jarAnalyzer.getJarData(); String result = jarData.getFileHash(); if ( result == null ) { try { result = digester.calc( jarData.getFile() ); jarData.setFileHash( result ); } catch ( DigesterException e ) { getLogger().warn( "Unable to calculate the hashcode.", e ); } } return result; } public void setDigester( Digester digester ) { this.digester = digester; } } JarHashAnalyzer.java000066400000000000000000000025751163445532600340430ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/hashpackage org.apache.maven.shared.jar.identification.hash; /* * 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. */ import org.apache.maven.shared.jar.JarAnalyzer; /** * Classes that can calculate various hash signatures for a JAR file to later uniquely identify them. */ public interface JarHashAnalyzer { /** * Compute the hash for the JAR. The hashcode will then be cached in the JAR data class for later use. * * @param jarAnalyzer the JAR analyzer to use to obtain the entries to hash * @return the hash, or null if not able to be computed due to an exception. */ String computeHash( JarAnalyzer jarAnalyzer ); } maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/repository/000077500000000000000000000000001163445532600315145ustar00rootroot00000000000000EmptyRepositoryHashSearch.java000066400000000000000000000032051163445532600374300ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/repositorypackage org.apache.maven.shared.jar.identification.repository; /* * 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. */ import java.util.Collections; import java.util.List; /** * Empty repository hash search. Always returns an empty list. *

* Used for local only implementation of a RepositoryHashSearch. It is expected for the users of this library to provide * an implementation of a {@link org.apache.maven.shared.jar.identification.repository.RepositoryHashSearch} against a * real repository. * * @plexus.component role="org.apache.maven.shared.jar.identification.repository.RepositoryHashSearch" role-hint="empty" */ public class EmptyRepositoryHashSearch implements RepositoryHashSearch { public List searchBytecodeHash( String hash ) { return Collections.EMPTY_LIST; } public List searchFileHash( String hash ) { return Collections.EMPTY_LIST; } } RepositoryHashSearch.java000066400000000000000000000031441163445532600364130ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/java/org/apache/maven/shared/jar/identification/repositorypackage org.apache.maven.shared.jar.identification.repository; /* * 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. */ import java.util.List; /** * Interface for Repository Hash Searches. */ public interface RepositoryHashSearch { /** * Search the repository for artifacts matching the given hash code when consider the entire contents of the file. * * @param hash the hash code to use * @return a list of {@link org.apache.maven.artifact.Artifact} instances that matched */ List searchFileHash( String hash ); /** * Search the repository for artifacts matching the given hash code when consider the bytecode of the classes in the * file. * * @param hash the hash code to use * @return a list of {@link org.apache.maven.artifact.Artifact} instances that matched */ List searchBytecodeHash( String hash ); } maven-shared-jar-1.1/src/main/javadoc/000077500000000000000000000000001163445532600176325ustar00rootroot00000000000000maven-shared-jar-1.1/src/main/javadoc/overview.html000066400000000000000000000074311163445532600223730ustar00rootroot00000000000000 Maven Shared Components: Jar Analyzer

Maven Shared Components: Jar Analyzer

The Maven Jar Analyzer components can be used to gather various pieces of information about a given JAR file. Currently, the following operations are supported:

Maven Artifact Identification

To determine the Maven artifact metadata for a particular JAR, the {@link org.apache.maven.shared.jar.identification.JarIdentificationAnalysis} class is used. The class can be obtained through Plexus, or created standalone (in which case, see the class Javadoc for information on proper wiring).

Note that to use the class, you must first obtain a {@link org.apache.maven.shared.jar.JarAnalyzer} instance as instructed in its Javadoc.

The resulting information will be populated in the returned {@link org.apache.maven.shared.jar.identification.JarIdentification} class.

Example usage:

        JarAnalyzer jar = new JarAnalyzer( jarFile );
        JarIdenfitication jarIdenfitication;
        try
        {
            // instance must have been previously obtained through Plexus or created as instructed in its Javadoc
            jarIdenfitication = jarIdenfiticationAnalyzer.analyze( jar );
        }
        finally
        {
            jar.closeQuietly();
        }

        // continue to use jarIdenfitication or jar.getJarData()
    

Java Class Analysis

To determine the Java class metadata for a particular JAR, the {@link org.apache.maven.shared.jar.classes.JarClassesAnalysis} class is used. The class can be obtained through Plexus, or created standalone (in which case, see the class Javadoc for information on proper wiring).

Note that to use the class, you must first obtain a {@link org.apache.maven.shared.jar.JarAnalyzer} instance as instructed in its Javadoc.

The resulting information will be populated in the returned {@link org.apache.maven.shared.jar.classes.JarClasses} class.

Example usage:

        JarAnalyzer jar = new JarAnalyzer( jarFile );
        JarClasses jarClasses;
        try
        {
            // instance must have been previously obtained through Plexus or created as instructed in its Javadoc
            jarClasses = jarClassAnalyzer.analyze( jar );
        }
        finally
        {
            jar.closeQuietly();
        }

        // continue to use jarClasses or jar.getJarData()
    

maven-shared-jar-1.1/src/site/000077500000000000000000000000001163445532600162435ustar00rootroot00000000000000maven-shared-jar-1.1/src/site/apt/000077500000000000000000000000001163445532600170275ustar00rootroot00000000000000maven-shared-jar-1.1/src/site/apt/index.apt000066400000000000000000000005161163445532600206460ustar00rootroot00000000000000 ----- Introduction ----- Brett Porter ----- 2 July 2007 ----- Maven JAR Utilities Utilities that help identify the contents of a JAR, including Java class analysis and Maven metadata analysis. * Using the Utilities Instructions on how to use the utilities can be found in the {{{apidocs/index.html} Javadoc Overview}}. maven-shared-jar-1.1/src/site/site.xml000066400000000000000000000022371163445532600177350ustar00rootroot00000000000000 maven-shared-jar-1.1/src/test/000077500000000000000000000000001163445532600162565ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/000077500000000000000000000000001163445532600171775ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/000077500000000000000000000000001163445532600177665ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/000077500000000000000000000000001163445532600212075ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/000077500000000000000000000000001163445532600223155ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/000077500000000000000000000000001163445532600235635ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/000077500000000000000000000000001163445532600243375ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/AbstractJarAnalyzerTestCase.java000066400000000000000000000051141163445532600325450ustar00rootroot00000000000000package org.apache.maven.shared.jar; /* * 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. */ import junit.framework.AssertionFailedError; import org.codehaus.plexus.PlexusTestCase; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Abstract JarAnalyzer TestCase */ public abstract class AbstractJarAnalyzerTestCase extends PlexusTestCase { public File getSampleJar( String filename ) throws MalformedURLException, UnsupportedEncodingException { String path = getClass().getResource( "/jars/" + filename ).getPath(); // URLDecoder.decode necessary for JDK 1.5+, where spaces are escaped to %20 return new File( URLDecoder.decode( path, "UTF-8" ) ); } public void assertNotContainsRegex( String msg, String regex, Collection coll ) { List failures = new ArrayList(); Pattern pat = Pattern.compile( regex ); Iterator it = coll.iterator(); while ( it.hasNext() ) { String value = (String) it.next(); Matcher mat = pat.matcher( value ); if ( mat.find() ) { failures.add( value ); } } if ( !failures.isEmpty() ) { StringBuffer sb = new StringBuffer(); sb.append( msg ).append( " collection has illegal regex \"" ).append( regex ).append( "\"" ); it = failures.iterator(); while ( it.hasNext() ) { sb.append( "\n - \"" ).append( it.next() ).append( "\"" ); } throw new AssertionFailedError( sb.toString() ); } } } maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/JarAnalyzerTest.java000066400000000000000000000055231163445532600302710ustar00rootroot00000000000000package org.apache.maven.shared.jar; import java.io.File; import java.io.IOException; import java.util.zip.ZipException; /* * 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. */ /** * Tests for the JarAnalyzer class. */ public class JarAnalyzerTest extends AbstractJarAnalyzerTestCase { private JarAnalyzer jarAnalyzer; protected void tearDown() throws Exception { super.tearDown(); if ( jarAnalyzer != null ) { jarAnalyzer.closeQuietly(); } } private JarData getJarData( String filename ) throws Exception { jarAnalyzer = getJarAnalyzer( filename ); return jarAnalyzer.getJarData(); } private JarAnalyzer getJarAnalyzer( String filename ) throws IOException { return new JarAnalyzer( getSampleJar( filename ) ); } public void testSealed() throws Exception { JarData jarData = getJarData( "evil-sealed-regex-1.0.jar" ); assertTrue( jarData.isSealed() ); } public void testNotSealed() throws Exception { JarData jarData = getJarData( "codec.jar" ); assertFalse( jarData.isSealed() ); } public void testMissingFile() throws Exception { try { jarAnalyzer = new JarAnalyzer( new File( "foo-bar-this-should-not-exist.jar" ) ); fail( "Should not have succeeded to get the missing JAR" ); } catch ( IOException e ) { assertTrue( true ); } } public void testInvalidJarFile() throws Exception { try { getJarAnalyzer( "invalid.jar" ); fail( "Should not have succeeded to get the invalid JAR" ); } catch ( ZipException e ) { assertTrue( true ); } } public void testCloseTwice() throws Exception { JarAnalyzer jarAnalyzer = getJarAnalyzer( "codec.jar" ); // no exception should be thrown jarAnalyzer.closeQuietly(); jarAnalyzer.closeQuietly(); assertTrue( true ); } } maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/classes/000077500000000000000000000000001163445532600257745ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/classes/ImportVisitorTest.java000066400000000000000000000062131163445532600323330ustar00rootroot00000000000000package org.apache.maven.shared.jar.classes; /* * 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. */ import org.apache.bcel.classfile.ClassFormatException; import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.DescendingVisitor; import org.apache.bcel.classfile.JavaClass; import org.apache.maven.shared.jar.AbstractJarAnalyzerTestCase; import java.io.File; import java.io.IOException; import java.util.List; /** * Import Visitor Test */ public class ImportVisitorTest extends AbstractJarAnalyzerTestCase { public void testImportsJxr() throws ClassFormatException, IOException { File jxrjar = getSampleJar( "jxr.jar" ); String classname = "org/apache/maven/jxr/DirectoryIndexer.class"; ClassParser classParser = new ClassParser( jxrjar.getAbsolutePath(), classname ); JavaClass javaClass = classParser.parse(); ImportVisitor importVisitor = new ImportVisitor( javaClass ); DescendingVisitor descVisitor = new DescendingVisitor( javaClass, importVisitor ); javaClass.accept( descVisitor ); List imports = importVisitor.getImports(); assertNotNull( "Import List", imports ); assertNotContainsRegex( "Import List", "[\\[\\)\\(\\;]", imports ); assertTrue( "imports", imports.contains( "org.apache.maven.jxr.pacman.PackageType" ) ); assertTrue( "imports", imports.contains( "org.codehaus.plexus.util.IOUtil" ) ); assertTrue( "imports", imports.contains( "org.apache.oro.text.perl.Perl5Util" ) ); } public void testImportsAnt() throws ClassFormatException, IOException { File jxrjar = getSampleJar( "ant.jar" ); String classname = "org/apache/tools/ant/Target.class"; ClassParser classParser = new ClassParser( jxrjar.getAbsolutePath(), classname ); JavaClass javaClass = classParser.parse(); ImportVisitor importVisitor = new ImportVisitor( javaClass ); DescendingVisitor descVisitor = new DescendingVisitor( javaClass, importVisitor ); javaClass.accept( descVisitor ); List imports = importVisitor.getImports(); assertNotNull( "Import List", imports ); assertNotContainsRegex( "Import List", "[\\[\\)\\(\\;]", imports ); assertTrue( "imports", imports.contains( "org.apache.tools.ant.Location" ) ); assertTrue( "imports", imports.contains( "org.apache.tools.ant.Task" ) ); } } maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/classes/JarClassesAnalyzerTest.java000066400000000000000000000132371163445532600332450ustar00rootroot00000000000000package org.apache.maven.shared.jar.classes; /* * 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. */ import org.apache.maven.shared.jar.AbstractJarAnalyzerTestCase; import org.apache.maven.shared.jar.JarAnalyzer; import java.io.File; /** * JarAnalyzer Classes Test Case */ public class JarClassesAnalyzerTest extends AbstractJarAnalyzerTestCase { private JarClassesAnalysis analyzer; public void setUp() throws Exception { super.setUp(); analyzer = (JarClassesAnalysis) lookup( JarClassesAnalysis.class.getName() ); } public void testAnalyzeJXR() throws Exception { JarClasses jclass = getJarClasses( "jxr.jar" ); assertFalse( "classes.imports.length > 0", jclass.getImports().isEmpty() ); assertFalse( "classes.packages.length > 0", jclass.getPackages().isEmpty() ); assertFalse( "classes.methods.length > 0", jclass.getMethods().isEmpty() ); assertNotContainsRegex( "Import List", "[\\[\\)\\(\\;]", jclass.getImports() ); // TODO: test for classes, methods, etc. assertTrue( "classes.imports", jclass.getImports().contains( "org.apache.maven.jxr.JXR" ) ); assertTrue( "classes.imports", jclass.getImports().contains( "org.apache.oro.text.perl.Perl5Util" ) ); assertTrue( "classes.imports", jclass.getImports().contains( "org.codehaus.plexus.util.IOUtil" ) ); assertTrue( "classes.packages", jclass.getPackages().contains( "org.apache.maven.jxr.pacman" ) ); } public void testAnalyzeANT() throws Exception { JarClasses jclass = getJarClasses( "ant.jar" ); assertFalse( "classes.imports.length > 0", jclass.getImports().isEmpty() ); assertFalse( "classes.packages.length > 0", jclass.getPackages().isEmpty() ); assertFalse( "classes.methods.length > 0", jclass.getMethods().isEmpty() ); assertNotContainsRegex( "Import List", "[\\[\\)\\(\\;]", jclass.getImports() ); assertTrue( "classes.imports", jclass.getImports().contains( "java.util.zip.GZIPInputStream" ) ); assertTrue( "classes.imports", jclass.getImports().contains( "org.apache.tools.ant.XmlLogger$TimedElement" ) ); assertTrue( "classes.imports", jclass.getImports().contains( "org.apache.tools.mail.MailMessage" ) ); assertTrue( "classes.packages", jclass.getPackages().contains( "org.apache.tools.ant" ) ); assertTrue( "classes.packages", jclass.getPackages().contains( "org.apache.tools.bzip2" ) ); } public void testAnalyzeJarWithInvalidClassFile() throws Exception { JarClasses jclass = getJarClasses( "invalid-class-file.jar" ); // Doesn't fail, as exceptions are ignored. assertTrue( jclass.getClassNames().isEmpty() ); assertTrue( jclass.getPackages().isEmpty() ); assertTrue( jclass.getImports().isEmpty() ); assertNull( jclass.getJdkRevision() ); assertTrue( jclass.getMethods().isEmpty() ); } public void testAnalyzeJarWithDebug() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.4-debug.jar" ); assertTrue( "has debug", jclass.isDebugPresent() ); } public void testAnalyzeJarWithoutDebug() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.4.jar" ); assertFalse( "no debug present", jclass.isDebugPresent() ); } public void testAnalyzeJarVersion16() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.6.jar" ); assertEquals( "jdkrevision", "1.6", jclass.getJdkRevision() ); } public void testAnalyzeJarVersion15() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.5.jar" ); assertEquals( "jdkrevision", "1.5", jclass.getJdkRevision() ); } public void testAnalyzeJarVersion14() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.4.jar" ); assertEquals( "jdkrevision", "1.4", jclass.getJdkRevision() ); } public void testAnalyzeJarVersion13() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.3.jar" ); assertEquals( "jdkrevision", "1.3", jclass.getJdkRevision() ); } public void testAnalyzeJarVersion12() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.2.jar" ); assertEquals( "jdkrevision", "1.2", jclass.getJdkRevision() ); } public void testAnalyzeJarVersion11() throws Exception { JarClasses jclass = getJarClasses( "helloworld-1.1.jar" ); assertEquals( "jdkrevision", "1.1", jclass.getJdkRevision() ); } private JarClasses getJarClasses( String filename ) throws Exception { File file = getSampleJar( filename ); JarClasses jclass = analyzer.analyze( new JarAnalyzer( file ) ); assertNotNull( "JarClasses", jclass ); return jclass; } } maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/identification/000077500000000000000000000000001163445532600273305ustar00rootroot00000000000000JarIdentificationAnalyzerTest.java000066400000000000000000000074721163445532600360620ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/identificationpackage org.apache.maven.shared.jar.identification; /* * 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. */ import org.apache.maven.shared.jar.AbstractJarAnalyzerTestCase; import org.apache.maven.shared.jar.JarAnalyzer; import java.io.File; /** * JarAnalyzer Taxon Analyzer Test Case * * @todo test the exposers individually instead of in aggregate here (and test the normalize, etc. methods here instead with controlled exposers) */ public class JarIdentificationAnalyzerTest extends AbstractJarAnalyzerTestCase { private JarIdentification getJarTaxon( String filename ) throws Exception { File jarfile = getSampleJar( filename ); JarIdentificationAnalysis analyzer = (JarIdentificationAnalysis) lookup( JarIdentificationAnalysis.class.getName() ); JarIdentification taxon = analyzer.analyze( new JarAnalyzer( jarfile ) ); assertNotNull( "JarIdentification", taxon ); return taxon; } public void testTaxonAnalyzerWithJXR() throws Exception { JarIdentification taxon = getJarTaxon( "jxr.jar" ); assertEquals( "identification.groupId", "org.apache.maven", taxon.getGroupId() ); assertEquals( "identification.artifactId", "maven-jxr", taxon.getArtifactId() ); assertEquals( "identification.version", "1.1-SNAPSHOT", taxon.getVersion() ); assertEquals( "identification.name", "Maven JXR", taxon.getName() ); assertEquals( "identification.vendor", "Apache Software Foundation", taxon.getVendor() ); // TODO assert potentials too } /** * Tests JarAnalyzer with No embedded pom, and no useful manifest.mf information. * * @throws Exception failures */ public void testTaxonAnalyzerWithCODEC() throws Exception { JarIdentification taxon = getJarTaxon( "codec.jar" ); assertEquals( "identification.groupId", "org.apache.commons.codec", taxon.getGroupId() ); assertEquals( "identification.artifactId", "codec", taxon.getArtifactId() ); // TODO fix assertion // assertEquals( "identification.version", "codec_release_1_0_0_interim_20030519095102_build", identification.getVersion() ); assertEquals( "identification.version", "20030519", taxon.getVersion() ); assertEquals( "identification.name", "codec", taxon.getName() ); assertNull( "identification.vendor", taxon.getVendor() ); // TODO assert potentials too } public void testTaxonAnalyzerWithANT() throws Exception { JarIdentification taxon = getJarTaxon( "ant.jar" ); assertEquals( "identification.groupId", "org.apache.tools.ant", taxon.getGroupId() ); assertEquals( "identification.artifactId", "ant", taxon.getArtifactId() ); assertEquals( "identification.version", "1.6.5", taxon.getVersion() ); // TODO fix assertion // assertEquals( "identification.name", "Apache Ant", identification.getName() ); assertEquals( "identification.vendor", "Apache Software Foundation", taxon.getVendor() ); // TODO assert potentials too } } maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/identification/exposers/000077500000000000000000000000001163445532600312005ustar00rootroot00000000000000EmbeddedMavenModelExposerTest.java000066400000000000000000000047211163445532600376370ustar00rootroot00000000000000maven-shared-jar-1.1/src/test/java/org/apache/maven/shared/jar/identification/exposerspackage org.apache.maven.shared.jar.identification.exposers; /* * 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. */ import org.apache.maven.shared.jar.AbstractJarAnalyzerTestCase; import org.apache.maven.shared.jar.JarAnalyzer; import org.apache.maven.shared.jar.identification.JarIdentification; import java.io.File; /** * Test Case for Embedded Maven Model Taxon Data. */ public class EmbeddedMavenModelExposerTest extends AbstractJarAnalyzerTestCase { public void testExposerWithJXR() throws Exception { File file = getSampleJar( "jxr.jar" ); JarIdentification identification = new JarIdentification(); EmbeddedMavenModelExposer exposer = new EmbeddedMavenModelExposer(); exposer.expose( identification, new JarAnalyzer( file ) ); assertFalse( "exposer.groupIds", identification.getPotentialGroupIds().isEmpty() ); assertFalse( "exposer.artifactIds", identification.getPotentialArtifactIds().isEmpty() ); assertFalse( "exposer.versions", identification.getPotentialVersions().isEmpty() ); // TODO test others } public void testExposerWithANT() throws Exception { File file = getSampleJar( "ant.jar" ); JarIdentification identification = new JarIdentification(); EmbeddedMavenModelExposer exposer = new EmbeddedMavenModelExposer(); exposer.expose( identification, new JarAnalyzer( file ) ); assertTrue( "exposer.groupIds", identification.getPotentialGroupIds().isEmpty() ); assertTrue( "exposer.artifactIds", identification.getPotentialArtifactIds().isEmpty() ); assertTrue( "exposer.versions", identification.getPotentialVersions().isEmpty() ); // TODO test others } }