src/main/java/org/codehaus/plexus/archiver/jar/JarArchiver.java
private void createIndexList( ZipArchiveOutputStream zOut )
        throws IOException, ArchiverException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // encoding must be UTF8 as specified in the specs.
        PrintWriter writer = new PrintWriter( new OutputStreamWriter( baos, "UTF8" ) );

        // version-info blankline
        writer.println( "JarIndex-Version: 1.0" );
        writer.println();

        // header newline
        writer.println( getDestFile().getName() );

        // filter out META-INF if it doesn't contain anything other than the index and manifest.
        // this is what sun.misc.JarIndex does, guess we ought to be consistent.
        Set<String> filteredDirs = new HashSet<String>( addedDirs.keySet() );
        // our added dirs always have a trailing slash
        if ( filteredDirs.contains( META_INF_NAME + '/' ) )
        {
            boolean add = false;
            for ( String entry : entries.keySet() )
            {
                if ( entry.startsWith( META_INF_NAME + '/' ) && !entry.equals( INDEX_NAME ) && !entry.equals(
                    MANIFEST_NAME ) )
                {
                    add = true;
                    break;
                }
            }
            if ( !add )
            {
                filteredDirs.remove( META_INF_NAME + '/' );
            }
        }
        writeIndexLikeList( new ArrayList<String>( filteredDirs ), rootEntries, writer );
        writer.println();

        if ( indexJars != null )
        {
            java.util.jar.Manifest mf = createManifest();
            String classpath = mf.getMainAttributes().getValue( ManifestConstants.ATTRIBUTE_CLASSPATH );
            String[] cpEntries = null;
            if ( classpath != null )
            {
                StringTokenizer tok = new StringTokenizer( classpath, " " );
                cpEntries = new String[tok.countTokens()];
                int c = 0;
                while ( tok.hasMoreTokens() )
                {
                    cpEntries[c++] = tok.nextToken();
                }
            }

            for ( String indexJar : indexJars )
            {
                String name = findJarName( indexJar, cpEntries );
                if ( name != null )
                {
                    ArrayList<String> dirs = new ArrayList<String>();
                    ArrayList<String> files = new ArrayList<String>();
                    grabFilesAndDirs( indexJar, dirs, files );
                    if ( dirs.size() + files.size() > 0 )
                    {
                        writer.println( name );
                        writeIndexLikeList( dirs, files, writer );
                        writer.println();
                    }
                }
            }
        }

        writer.flush();

        ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );

        super.zipFile( bais, zOut, INDEX_NAME, System.currentTimeMillis(), null, DEFAULT_FILE_MODE, null );
    }
private void createIndexList( ZipArchiveOutputStream zOut )
        throws IOException, ArchiverException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // encoding must be UTF8 as specified in the specs.
        PrintWriter writer = new PrintWriter( new OutputStreamWriter( baos, "UTF8" ) );

        // version-info blankline
        writer.println( "JarIndex-Version: 1.0" );
        writer.println();

        // header newline
        writer.println( getDestFile().getName() );

        // filter out META-INF if it doesn't contain anything other than the index and manifest.
        // this is what sun.misc.JarIndex does, guess we ought to be consistent.
        Set<String> filteredDirs = new HashSet<String>( addedDirs.keySet() );
        // our added dirs always have a trailing slash
        if ( filteredDirs.contains( META_INF_NAME + '/' ) )
        {
            boolean add = false;
            for ( String entry : entries.keySet() )
            {
                if ( entry.startsWith( META_INF_NAME + '/' ) && !entry.equals( INDEX_NAME ) && !entry.equals(
                    MANIFEST_NAME ) )
                {
                    add = true;
                    break;
                }
            }
            if ( !add )
            {
                filteredDirs.remove( META_INF_NAME + '/' );
            }
        }
        writeIndexLikeList( new ArrayList<String>( filteredDirs ), rootEntries, writer );
        writer.println();

        if ( indexJars != null )
        {
            java.util.jar.Manifest mf = createManifest();
            String classpath = mf.getMainAttributes().getValue( ManifestConstants.ATTRIBUTE_CLASSPATH );
            String[] cpEntries = null;
            if ( classpath != null )
            {
                StringTokenizer tok = new StringTokenizer( classpath, " " );
                cpEntries = new String[tok.countTokens()];
                int c = 0;
                while ( tok.hasMoreTokens() )
                {
                    cpEntries[c++] = tok.nextToken();
                }
            }

            for ( String indexJar : indexJars )
            {
                String name = findJarName( indexJar, cpEntries );
                if ( name != null )
                {
                    ArrayList<String> dirs = new ArrayList<String>();
                    ArrayList<String> files = new ArrayList<String>();
                    grabFilesAndDirs( indexJar, dirs, files );
                    if ( dirs.size() + files.size() > 0 )
                    {
                        writer.println( name );
                        writeIndexLikeList( dirs, files, writer );
                        writer.println();
                    }
                }
            }
        }

        writer.flush();

        ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );

        super.zipFile( bais, zOut, INDEX_NAME, System.currentTimeMillis(), null, DEFAULT_FILE_MODE, null );
    }
Create the index list to speed up classloading.
This is a JDK 1.3+ specific feature and is enabled by default. See
<a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index">
the JAR index specification</a> for more details.

@param zOut the zip stream representing the jar being built.
@throws IOException thrown if there is an error while creating the
index and adding it to the zip stream.
@throws org.codehaus.plexus.archiver.ArchiverException
.