public void execute()

in nbm-maven-plugin/src/main/java/org/apache/netbeans/nbm/CreateClusterAppMojo.java [195:732]


    public void execute()
            throws MojoExecutionException, MojoFailureException
    {

        File nbmBuildDirFile = new File( outputDirectory, brandingToken );
        if ( !nbmBuildDirFile.exists() )
        {
            nbmBuildDirFile.mkdirs();
        }

        if ( "nbm-application".equals( project.getPackaging() ) )
        {
            Project antProject = registerNbmAntTasks();

            Set<String> wrappedBundleCNBs = new HashSet<>( 100 );
            Map<String, Set<String>> clusterDependencies = new HashMap<>();
            Map<String, Set<String>> clusterModules = new HashMap<>();

            //verify integrity
            Set<String> modulesCNBs = new HashSet<>( SET_INITIAL_SIZE );
            Set<String> dependencyCNBs = new HashSet<>( SET_INITIAL_SIZE );
            Map<String, Set<String>> dependencyCNBBacktraces = new HashMap<>( MAP_INITIALSIZE );
            Set<String> requireTokens = new HashSet<>( MAP_INITIALSIZE );
            Map<String, Set<String>> requireTokensBacktraces = new HashMap<>( MAP_INITIALSIZE );
            Set<String> provideTokens = new HashSet<>( MAP_INITIALSIZE );
            Set<String> osgiImports = new HashSet<>( MAP_INITIALSIZE );
            Map<String, Set<String>> osgiImportsBacktraces = new HashMap<>( MAP_INITIALSIZE );
            Set<String> osgiExports = new HashSet<>( MAP_INITIALSIZE );
            //a way to deal with nb module declaring xxx.** (subpackages) declaration that is consumed by osgi imports
            Set<String> osgiExportsSubs = new HashSet<>( MAP_INITIALSIZE );

            List<BundleTuple> bundles = new ArrayList<>();

            @SuppressWarnings( "unchecked" )
            Set<Artifact> artifacts = project.getArtifacts();
            for ( Artifact art : artifacts )
            {
                ArtifactResult res
                                       = turnJarToNbmFile( art, artifactFactory, artifactResolver, project,
                                                           session.getLocalRepository() );
                if ( res.hasConvertedArtifact() )
                {
                    art = res.getConvertedArtifact();
                }

                if ( art.getType().equals( "nbm-file" ) )
                {
                    try
                    {
                        JarFile jf = new JarFile( art.getFile() );
                        try
                        {
                            String clusterName = findCluster( jf );
                            ClusterTuple cluster = processCluster( clusterName, nbmBuildDirFile, art );

                            getLog().debug( "Copying " + art.getId() + " to cluster " + clusterName );
                            Enumeration<JarEntry> enu = jf.entries();

                            // we need to trigger this ant task to generate the update_tracking file.
                            MakeListOfNBM makeTask = (MakeListOfNBM) antProject.createTask( "genlist" );
                            antProject.setNewProperty( "module.name", art.getFile().getName() ); // TODO
                            antProject.setProperty( "cluster.dir", clusterName );
                            FileSet set = makeTask.createFileSet();
                            set.setDir( cluster.location );
                            makeTask.setOutputfiledir( cluster.location );
                            String[] executables = null;
                            File classpathRoot = null;
                            String classPath = null;
                            while ( enu.hasMoreElements() )
                            {
                                JarEntry ent = enu.nextElement();
                                String name = ent.getName();
                                //MNBMODULE-176
                                if ( name.equals( "Info/executables.list" ) )
                                {
                                    if ( cluster.newer )
                                    {
                                        InputStream is = jf.getInputStream( ent );
                                        executables = StringUtils.split( IOUtil.toString( is, "UTF-8" ), "\n" );
                                    }
                                }
                                else if ( name.startsWith( "netbeans/" ) )
                                { // ignore everything else.
                                    String path = clusterName + name.substring( "netbeans".length() );
                                    boolean ispack200 = path.endsWith( ".jar.pack.gz" );
                                    if ( ispack200 )
                                    {
                                        path = path.replace( ".jar.pack.gz", ".jar" );
                                    }
                                    File fl = new File( nbmBuildDirFile, path.replace( "/", File.separator ) );
                                    String part = name.substring( "netbeans/".length() );
                                    if ( ispack200 )
                                    {
                                        part = part.replace( ".jar.pack.gz", ".jar" );
                                    }
                                    if ( cluster.newer )
                                    {
                                        if ( ent.isDirectory() )
                                        {
                                            fl.mkdirs();
                                        }
                                        else if ( path.endsWith( ".external" ) ) // MNBMODULE-138
                                        {
                                            InputStream is = jf.getInputStream( ent );
                                            try
                                            {
                                                externalDownload( new File( fl.getParentFile(),
                                                                            fl.getName().replaceFirst( "[.]external$",
                                                                                                       "" ) ), is );
                                            }
                                            finally
                                            {
                                                is.close();
                                            }
                                            //MNBMODULE-192
                                            set.appendIncludes( new String[]
                                            {
                                                name.substring( "netbeans/".length(), name.length() - ".external".
                                                                length() )
                                            } );
                                        }
                                        else
                                        {
                                            set.appendIncludes( new String[]
                                            {
                                                part
                                            } );

                                            fl.getParentFile().mkdirs();
                                            fl.createNewFile();
                                            BufferedOutputStream outstream = null;
                                            try
                                            {
                                                outstream = new BufferedOutputStream( new FileOutputStream( fl ) );
                                                InputStream instream = jf.getInputStream( ent );
                                                if ( ispack200 )
                                                {
                                                    try ( JarOutputStream jos = new JarOutputStream( outstream ) )
                                                    {
                                                    Pack200.Unpacker unp = Pack200.newUnpacker();
                                                    GZIPInputStream gzip = new GZIPInputStream( instream );
                                                    unp.unpack( gzip, jos );
                                                    }
                                                    catch ( LinkageError cnfe )
                                                    {
                                                        throw new BuildException( "Using jdk 14 and later prevents "
                                                                + "reading of NBM created with pack200" );
                                                    }                                                  
                                                }
                                                else
                                                {
                                                    IOUtil.copy( instream, outstream );
                                                }
                                            }
                                            finally
                                            {
                                                IOUtil.close( outstream );
                                            }
                                        }
                                    }

                                    // TODO examine netbeans/config/Modules to see if the module is autoload/eager
                                    // in verifyIntegrity these could be handled more gracefully than regular modules.
                                    // eager is simpler, does not need to have module dependencies satisfied.
                                    // autoload needs checking if any of the other modules declares a dependency on it.
                                    // if not, also safe to ignore?
                                    // now figure which one of the jars is the module jar..
                                    if ( part.matches( "(modules|core|lib)/[^/]+[.]jar" ) )
                                    {
                                        ExamineManifest ex = new ExamineManifest( getLog() );
                                        ex.setJarFile( fl );
                                        ex.setPopulateDependencies( true );
                                        ex.checkFile();
                                        if ( ex.isNetBeansModule() )
                                        {
                                            makeTask.setModule( part );
                                            addToMap( clusterDependencies, clusterName, ex.getDependencyTokens() );
                                            addToMap( clusterModules, clusterName, Collections.singletonList( ex.
                                                      getModule() ) );
                                            if ( ex.getClasspath().length() > 0 )
                                            { //MNBMODULE-220
                                                try 
                                                {
                                                    classPath = URLDecoder.decode( ex.getClasspath(), "UTF-8" );
                                                } 
                                                catch ( UnsupportedEncodingException exception ) 
                                                {
                                                    throw new IllegalStateException( exception );
                                                }
                                                classpathRoot = fl.getParentFile();
                                            }
                                        }
                                        if ( verifyIntegrity )
                                        {
                                            dependencyCNBs.addAll( ex.getDependencyTokens() );
                                            modulesCNBs.add( ex.getModule() );
                                            for ( String d : ex.getDependencyTokens() )
                                            {
                                                addToMap( dependencyCNBBacktraces, d, Collections.singletonList( ex.
                                                          getModule() ) );
                                            }
                                            if ( ex.isNetBeansModule() )
                                            {
                                                requireTokens.addAll( ex.getNetBeansRequiresTokens() );
                                                for ( String r : ex.getNetBeansRequiresTokens() )
                                                {
                                                    addToMap( requireTokensBacktraces, r, Collections.singletonList( ex.
                                                              getModule() ) );
                                                }
                                                provideTokens.addAll( ex.getNetBeansProvidesTokens() );
                                                for ( String pack : ex.getPackages() )
                                                {
                                                    if ( pack.endsWith( ".**" ) )
                                                    {
                                                        //what to do with subpackages?
                                                        pack = pack.substring( 0, pack.length() - ".**".length() );
                                                        osgiExportsSubs.add( pack );
                                                    }
                                                    else if ( pack.endsWith( ".*" ) )
                                                    {
                                                        pack = pack.substring( 0, pack.length() - ".*".length() );
                                                        osgiExports.add( pack );
                                                    }
                                                }

                                            }
                                        }
                                    }
                                }
                            }
                            if ( classPath != null )
                            { // MNBMODULE-220 collect wrappedbundleCNBs, later useful in assignClustersToBundles(),
                              // these get removed from list of bundles.
                                String[] paths = StringUtils.split( classPath, " " );
                                for ( String path : paths )
                                {
                                    path = path.trim();
                                    File classpathFile = new File( classpathRoot, path );
                                    if ( path.equals( "${java.home}/lib/ext/jfxrt.jar" ) )
                                    { //MNBMODULE-228
                                        String jhm = System.getProperty( "java.home" );
                                        classpathFile = new File( new File( new File( new File( jhm ), "lib" ), "ext" ),
                                                                  "jfxrt.jar" );
                                        if ( !classpathFile.exists() )
                                        {
                                            File jdk7 = new File( new File( new File( jhm ), "lib" ), "jfxrt.jar" );
                                            if ( jdk7.exists() )
                                            {
                                                classpathFile = jdk7;
                                            }
                                        }
                                    }
                                    if ( !classpathFile.isFile() )
                                    {
                                        getLog().warn( "Could not resolve Class-Path item in " + art.getId()
                                                + ", path is:" + path + ", skipping" );
                                        continue; //try to guard against future failures
                                    }
                                    ExamineManifest ex = new ExamineManifest( getLog() );
                                    ex.setJarFile( classpathFile );
                                    //ex.setPopulateDependencies( true );
                                    ex.checkFile();
                                    if ( ex.isOsgiBundle() )
                                    {
                                        if ( art.getId().contains( groupIdPrefix
                                                + ".modules:org-netbeans-modules-maven-embedder" ) )
                                        {
                                            // in this case we dont want module-maven-embedder to be considered as
                                            // wrapper for his libs guava is provided but ide have it also
                                        }
                                        else
                                        {
                                            getLog().info( ex.getModule() + " added by " + art.getId() + ""
                                                    + classpathFile );
                                            wrappedBundleCNBs.add( ex.getModule() );
                                        }
                                    }
                                }
                            }
                            if ( cluster.newer )
                            {
                                try
                                {
                                    makeTask.execute();
                                }
                                catch ( BuildException e )
                                {
                                    getLog().error( "Cannot Generate update_tracking XML file from " + art.getFile() );
                                    throw new MojoExecutionException( e.getMessage(), e );
                                }

                                if ( executables != null )
                                {
                                    //MNBMODULE-176
                                    for ( String exec : executables )
                                    {
                                        exec = exec.replace( "/", File.separator );
                                        File execFile = new File( cluster.location, exec );
                                        if ( execFile.exists() )
                                        {
                                            execFile.setExecutable( true, false );
                                        }
                                    }
                                }
                            }

                        }
                        finally
                        {
                            jf.close();
                        }
                    }
                    catch ( IOException ex )
                    {
                        getLog().error( art.getFile().getAbsolutePath(), ex );
                    }
                }
                if ( res.isOSGiBundle() )
                {
                    ExamineManifest ex = res.getExaminedManifest();
                    bundles.add( new BundleTuple( art, ex ) );
                    if ( verifyIntegrity )
                    {
                        dependencyCNBs.addAll( ex.getDependencyTokens() );
                        for ( String d : ex.getDependencyTokens() )
                        {
                            addToMap( dependencyCNBBacktraces, d, Collections.singletonList( ex.getModule() ) );
                        }
                        modulesCNBs.add( ex.getModule() );
                        osgiImports.addAll( ex.getOsgiImports() );
                        for ( String d : ex.getOsgiImports() )
                        {
                            addToMap( osgiImportsBacktraces, d, Collections.singletonList( ex.getModule() ) );
                        }

                        osgiExports.addAll( ex.getOsgiExports() );
                    }
                }
            }

            if ( verifyIntegrity )
            {
                if ( getLog().isDebugEnabled() )
                {
                    getLog().debug( "All found codenamebases:" + Arrays.toString( modulesCNBs.toArray() ) );
                    getLog().debug( "All found OSGI exports:" + Arrays.toString( osgiExports.toArray() ) );
                    getLog().debug( "All found provided tokens:" + Arrays.toString( provideTokens.toArray() ) );
                }
                dependencyCNBs.removeAll( modulesCNBs );
                if ( modulesCNBs.contains( "org.netbeans.modules.netbinox" ) )
                {
                    dependencyCNBs.remove( "org.eclipse.osgi" ); //this is special.
                }
                osgiImports.removeAll( osgiExports );
                Iterator<String> it = osgiImports.iterator();
                while ( it.hasNext() )
                {
                    String s = it.next();
                    if ( s.startsWith( "java." )
                            || s.startsWith( "javax." )
                            || s.startsWith( "sun." )
                            || s.startsWith( "org.xml.sax" )
                            || s.startsWith( "org.w3c.dom" )
                            || s.startsWith( "org.ietf.jgss" ) )
                    {
                        it.remove();
                        continue;
                    }
                    for ( String sub : osgiExportsSubs )
                    {
                        if ( s.startsWith( sub ) )
                        {
                            it.remove();
                            break;
                        }
                    }
                }
                requireTokens.removeAll( provideTokens );
                requireTokens.removeAll( defaultPlatformTokens );
                if ( !dependencyCNBs.isEmpty() || !osgiImports.isEmpty() || !requireTokens.isEmpty() )
                {
                    if ( !dependencyCNBs.isEmpty() )
                    {
                        getLog().error(
                                "Some included modules/bundles depend on these codenamebases but they are not included."
                                + " The application will fail starting up. The missing codenamebases are:" );
                        for ( String s : dependencyCNBs )
                        {
                            Set<String> back = dependencyCNBBacktraces.get( s );
                            getLog().error( "   " + s + ( back != null ? "          ref: " + Arrays.toString( back.
                                    toArray() ) : "" ) );
                        }
                    }
                    if ( !osgiImports.isEmpty() )
                    {
                        getLog().error(
                                "Some OSGi imports are not satisfied by included bundles' exports. "
                                + "The application will fail starting up. The missing imports are:" );
                        for ( String s : osgiImports )
                        {
                            Set<String> back = osgiImportsBacktraces.get( s );
                            getLog().error( "   " + s + ( back != null ? "          ref: " + Arrays.toString( back.
                                    toArray() ) : "" ) );
                        }
                    }
                    if ( !requireTokens.isEmpty() )
                    {
                        getLog().error(
                                "Some tokens required by included modules are not provided by included modules. "
                                + "The application will fail starting up. The missing tokens are:" );
                        for ( String s : requireTokens )
                        {
                            Set<String> back = requireTokensBacktraces.get( s );
                            getLog().error( "   " + s + ( back != null ? "          ref: " + Arrays.toString( back.
                                    toArray() ) : "" ) );
                        }
                    }
                    throw new MojoFailureException(
                            "See above for consistency validation check failures. "
                            + " Either fix those by adding the relevant dependencies to the application or "
                            + "disable the check by setting the verifyIntegrity parameter to false or by running with "
                            + "-Dnetbeans.verify.integrity=false cmd line parameter." );
                }
                else
                {
                    getLog().info( "Integrity verification passed." );
                }
            }
            else
            {
                getLog().info( "Integrity verification skipped." );
            }

            //attempt to sort clusters based on the dependencies and cluster content.
            Map<String, Set<String>> cluster2depClusters =
                    computeClusterOrdering( clusterDependencies, clusterModules );
            clusterModules.clear();

            //now assign the cluster to bundles based on dependencies..
            assignClustersToBundles( bundles, wrappedBundleCNBs, clusterDependencies, cluster2depClusters, getLog() );

            for ( BundleTuple ent : bundles )
            {
                Artifact art = ent.artifact;
                final ExamineManifest ex = ent.manifest;

                String clstr = ent.cluster;
                if ( clstr == null )
                {
                    clstr = defaultCluster;
                }

                ClusterTuple cluster = processCluster( clstr, nbmBuildDirFile, art );
                if ( cluster.newer )
                {
                    getLog().info( "Copying " + art.getId() + " to cluster " + clstr );
                    File modules = new File( cluster.location, "modules" );
                    modules.mkdirs();
                    File config = new File( cluster.location, "config" );
                    File confModules = new File( config, "Modules" );
                    confModules.mkdirs();
                    File updateTracking = new File( cluster.location, "update_tracking" );
                    updateTracking.mkdirs();
                    final String cnb = ex.getModule();
                    final String cnbDashed = cnb.replace( ".", "-" );
                    //do we need the file in some canotical name pattern in moduleArt?
                    final File moduleArt = new File( modules, cnbDashed + ".jar" );
                    final String specVer = ex.getSpecVersion();
                    try
                    {
                        FileUtils.copyFile( art.getFile(), moduleArt );
                        final File moduleConf = new File( confModules, cnbDashed + ".xml" );
                        FileUtils.copyStreamToFile( new InputStreamFacade()
                        {
                            @Override
                            public InputStream getInputStream() throws IOException
                            {
                                return new StringInputStream( createBundleConfigFile( cnb, ex.isBundleAutoload() ),
                                                              "UTF-8" );
                            }
                        }, moduleConf );
                        FileUtils.copyStreamToFile( new InputStreamFacade()
                        {
                            @Override
                            public InputStream getInputStream() throws IOException
                            {
                                return new StringInputStream( createBundleUpdateTracking( cnb, moduleArt, moduleConf,
                                                                                          specVer ), "UTF-8" );
                            }
                        }, new File( updateTracking, cnbDashed + ".xml" ) );
                    }
                    catch ( IOException exc )
                    {
                        getLog().error( exc );
                    }
                }
            }

            getLog().info(
                    "Created NetBeans module cluster(s) at " + nbmBuildDirFile.getAbsoluteFile() );

        }
        else
        {
            throw new MojoExecutionException(
                    "This goal only makes sense on project with nbm-application packaging" );
        }
        //in 6.1 the rebuilt modules will be cached if the timestamp is not touched.
        File[] files = nbmBuildDirFile.listFiles();
        for ( File file : files )
        {
            if ( file.isDirectory() )
            {
                File stamp = new File( file, ".lastModified" );
                if ( !stamp.exists() )
                {
                    try
                    {
                        stamp.createNewFile();
                    }
                    catch ( IOException ex )
                    {
                        ex.printStackTrace();
                    }
                }
                stamp.setLastModified( new Date().getTime() );
            }
        }
        try
        {
            createBinEtcDir( nbmBuildDirFile, brandingToken );
        }
        catch ( IOException ex )
        {
            throw new MojoExecutionException(
                    "Cannot process etc folder content creation.", ex );
        }
    }