alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2002 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.autoupdate;

import java.util.*;
import org.openide.DialogDisplayer;

import org.openide.util.NbBundle;
import org.openide.NotifyDescriptor;
import org.openide.modules.ModuleInfo;
import org.openide.modules.Dependency;
import org.openide.modules.SpecificationVersion;

/** Support class for checking dependencies between modules
 *
 * @author  phrebejk
 */
class DependencyChecker extends Object {

    /** DependencyChecker is a singleton */
    DependencyChecker() {        
    }

    /** Gets collection of modules which have to be added to download list
     * if we have to add the toAddModule.
     */
    Collection modulesToAdd( ModuleUpdate toAdd, Enumeration selected, List group, StringBuffer dontAddModuleName ) {
        Collection result = new ArrayList();
        checkDependencies( toAdd.getRemoteModule(), result, selected, group, dontAddModuleName, toAdd.getLocalModule() != null );
        return result;
    }

    /** Gets collection of modules which we have to remove from download list
     * if we have to remove the toRemove module.
     */
    Collection modulesToRemove( ModuleUpdate toRemove, ModuleUpdate toReplace ) {
        Collection result = new ArrayList();
        checkReverseDependencies( toRemove.getRemoteModule(), result, toReplace );
        return result;
    }

    /** Builds Collection with modules which should be added
     * into download list to satisfy module dependencies.
     */
    private boolean checkDependencies( ModuleInfo md, Collection result, Enumeration selected, List group, 
            StringBuffer dontAddModuleName, boolean isUpgrade ) {

        // Get all module dependencies
        Set depsS = md.getDependencies();
        Dependency[] deps = (Dependency[])depsS.toArray(new Dependency[depsS.size()]);
        // Array values say if the dependency is satisfied or not
        boolean[] satisfied = new boolean [ deps.length ];

        // All installed modules
        ModuleInfo[] installedModules = Updates.getInstalledModules();
        ModuleInfo[] installedPatches = Updates.getInstalledPatches();

        // For all dependencies
        for ( int j = 0; j < deps.length; j++ ) {

            String message = null;

            // The module depends on other module
            if (deps[j].getType() == Dependency.TYPE_MODULE || deps[j].getType() == Dependency.TYPE_REQUIRES) {

                boolean ok = false;

                // Try to figure out if the dependency is satisfied by installed modules
                for (int i = 0; i < installedModules.length; i++) {
                    ok = checkModuleDependency ( deps[j], installedModules[i] );
                    if ( ok )
                        break;
                }

                if ( !ok ) {
                    // Try to figure out if the dependency is satisfied by installed patches
                    for (int i = 0; i < installedPatches.length; i++) {
                        ok = checkModuleDependency ( deps[j], installedPatches[i] );
                        if ( ok )
                            break;
                    }
                }
                
                // Dependency was not satisfied by other module let's try modules
                // available for download
                if ( !ok && selected != null ) {

                    while ( selected.hasMoreElements() ) {
                        ModuleUpdate mu = (ModuleUpdate)selected.nextElement();

                        ok = checkModuleDependency ( deps[j], mu.getRemoteModule() );

                        if ( ok ) {
                            if ( !result.contains( mu ) ) {
                                result.add( mu );
                            }
                            break;
                        }
                    }
                }
                
                if ( !ok && group != null ) {

                    Iterator it = group.iterator();
                    while ( it.hasNext() ) {
                        ModuleUpdate mu = (ModuleUpdate)it.next();

                        ok = checkModuleDependency ( deps[j], mu.getRemoteModule() );

                        if ( ok ) {
                            if ( !result.contains( mu ) ) {
                                result.add( mu );
                            }
                            break;
                        }
                    }
                }
                
                if ( !ok ) {

                    Iterator it = Wizard.getAllModules().iterator();
                    while ( it.hasNext() ) {
                        ModuleUpdate mu = (ModuleUpdate)it.next();

                        ok = checkModuleDependency ( deps[j], mu.getRemoteModule() );

                        if ( ok ) {
                            if ( !result.contains( mu ) ) {
                                result.add( mu );
                            }
                            break;
                        }
                    }
                }

                if ( !ok )
                    satisfied[j] = false;
                else
                    satisfied[j] = true;
            }
            // Module depends on specific version of IDE
            else if ( deps[j].getType() == Dependency.TYPE_IDE ) {
                // Try to figure out if the dependency is satisfied by installed ide
                if (  checkIdeDependency ( deps[j], IdeDescription.getIdeDescription() ) ) {
                    satisfied[j] = true;
                }
                else {
                    // Try to find suitable IDE between the modules
                    Iterator it = Wizard.getAllModules().iterator();
                    boolean ok = false;
                    while ( it.hasNext() ) {
                        ModuleUpdate mu = (ModuleUpdate)it.next();

                        ok = checkModuleDependency ( deps[j], mu.getRemoteModule() );

                        if ( ok ) {
                            if ( !result.contains( mu ) ) {
                                result.add( mu );
                            }
                            break;
                        }
                    }
                    satisfied[j] = ok;
                }
            }
            else // XXX what about Java/VM dependencies?!
                satisfied[j] = true;
        }


        StringBuffer sb = new StringBuffer( 280 );
        sb.append( getBundle( "MSG_NotSatisfied" ) + "MODULE :" + md.getCodeName() );

        int notSatisfied = 0;

        // For all dependencies
        for ( int j = 0; j < deps.length; j++ ) {
            if ( !satisfied[j] ) {
                sb.append( deps[j] );
                notSatisfied++;
            }
        }
        
        StringBuffer sbbroken = null;
        if ( isUpgrade ) {
            // Checking, if upgrade of module doesn't break dependency of already
            // installed modules on it's certain implementation version
            List brokenlist = checkBrokenImplDependency( md, result );
            if ( brokenlist.size() > 0 ) {
                sbbroken = new StringBuffer( 280 );
                sbbroken.append( "MODULE :" + md.getCodeName() );        // NOI18N
                sbbroken.append( getBundle( "MSG_BadsList" ) );
                Iterator it = brokenlist.iterator();
                while ( it.hasNext() )
                    sbbroken.append( "\n" + ((ModuleInfo) it.next()).getCodeName() );  // NOI18N
                sbbroken.append( getBundle( "MSG_IncludeBadsAnyway" ) );
            }
        }
        
        if ( notSatisfied == 0 && sbbroken == null )
            return true;

        if ( notSatisfied > 0 ) {
            sb.append( getBundle( "MSG_IncludeAnyway" ) );
            NotifyDescriptor.Confirmation nd = new NotifyDescriptor.Confirmation(
                                              sb.toString(),
                                              NotifyDescriptor.YES_NO_OPTION,
                                              NotifyDescriptor.ERROR_MESSAGE );

            if ( ! DialogDisplayer.getDefault().notify( nd ).equals( NotifyDescriptor.YES_OPTION ) ) {
                dontAddModuleName.append( md.getDisplayName() );
                return false;
            }
        }
        if ( sbbroken != null ) {
            NotifyDescriptor.Confirmation nd = new NotifyDescriptor.Confirmation(
                                              sbbroken.toString(),
                                              NotifyDescriptor.YES_NO_OPTION,
                                              NotifyDescriptor.ERROR_MESSAGE );

            if ( ! DialogDisplayer.getDefault().notify( nd ).equals( NotifyDescriptor.YES_OPTION ) )
                dontAddModuleName.append( md.getDisplayName() );
        }

        return false;
    }


    /** Builds Collection with modules which should be removed
     * from download list to satisfy module dependencies.
     */
    boolean checkReverseDependencies( ModuleInfo module, Collection result, ModuleUpdate toReplace ) {

        //ArrayList dependentModules = new ArrayList();
        ModuleInfo[] installedModules = Updates.getInstalledModules();
        ModuleInfo[] installedPatches = Updates.getInstalledPatches();

        // All listed modules
        Iterator it = Wizard.getAllModules().iterator();
        while ( it.hasNext() ) {
            ModuleUpdate mu = (ModuleUpdate)it.next();


            //if ( !info.update() ) We have to check all modules
            //  continue;

            ModuleInfo md = mu.getRemoteModule();
            Set depsS = md.getDependencies();
            Dependency[] deps = (Dependency[])depsS.toArray(new Dependency[depsS.size()]);

            // All dependencies of module
            boolean moduleOk = true;
            for ( int j = 0; j < deps.length; j++ ) {



                if ( (deps[j].getType() == Dependency.TYPE_MODULE &&
                         (deps[j].getName() + "/").startsWith( module.getCodeNameBase() + "/" )) || // NOI18N
                     (deps[j].getType() == Dependency.TYPE_REQUIRES &&
                         Arrays.asList(module.getProvides()).contains(deps[j].getName())) ) {

                    boolean ok = false;

                    // Check if not satisfied by installed modules
                    for (int k = 0; k < installedModules.length; k++) {
                        ok = checkModuleDependency ( deps[j], installedModules[k] );
                        if ( ok )
                            break;
                    }
                    
                    // Check if not satisfied by replacing module
                    if ( !ok && toReplace != null )
                        ok = checkModuleDependency ( deps[j], toReplace.getRemoteModule() );

                    // Check if it is not stisfied by installed patches
                    if ( !ok )
                        for (int k = 0; k < installedPatches.length; k++) {
                            ok = checkModuleDependency ( deps[j], installedPatches[k] );
                            if ( ok )
                                break;
                        }


                    // The module has unsatisfied dependency we have to remove it
                    if ( !ok ) {
                        moduleOk = false;
                        break;
                    }
                }
                else if ( deps[j].getType() == Dependency.TYPE_IDE &&
                          // XXX how can this be true?!
                          deps[j].getName().equals( module.getCodeName() ) ) {

                    //Check if not satisfied by installed IDE
                    if ( !checkModuleDependency ( deps[j], IdeDescription.getIdeDescription() ) ) {
                        moduleOk = false;
                        break;
                    }
                }
            }

            if ( !moduleOk ) {
                if ( ! result.contains( mu ) ) {
                    result.add( mu );
                    //checkReverseDependencies( mu.getRemoteModule(), result );
                }
            }
        }

        return result.size() == 0;
    }


    /** Tests if the dependency on module is satisfied by the otherModule
     */
    static boolean checkModuleDependency ( Dependency dep,
                                    ModuleInfo otherModule ) {

        if (dep.getType() == Dependency.TYPE_REQUIRES) {
            return Arrays.asList(otherModule.getProvides()).contains(dep.getName());
        }

        boolean satisfied = false;
        String depName = dep.getName();

        if ( depName.equals (otherModule.getCodeName ())) {
            if ( dep.getComparison() == Dependency.COMPARE_ANY) {
                return true;
            }
            else if (dep.getComparison() == Dependency.COMPARE_SPEC) {
                    if (otherModule.getSpecificationVersion() == null)
                        return false;
                    else if (new SpecificationVersion(dep.getVersion()).compareTo(otherModule.getSpecificationVersion()) > 0)
                        return false;
                    else
                        return true;
            }
            else {
                // COMPARE_IMPL
                if (otherModule.getImplementationVersion () == null)
                    return false;
                else if (! otherModule.getImplementationVersion ().equals (dep.getVersion()))
                    return false;
                else
                    return true;
            }
        }

        int dash = depName.indexOf('-'); // NOI18N
        if (dash != -1) {
            // Ranged major release version, cf. #19714.
            int slash = depName.indexOf('/'); // NOI18N
            String cnb = depName.substring(0, slash);
            int relMin = Integer.parseInt(depName.substring(slash + 1, dash));
            int relMax = Integer.parseInt(depName.substring(dash + 1));
            if (cnb.equals(otherModule.getCodeNameBase()) &&
                    relMin <= otherModule.getCodeNameRelease() &&
                    relMax >= otherModule.getCodeNameRelease()) {
                if (dep.getComparison() == Dependency.COMPARE_ANY) {
                    return true;
                } else {
                    // COMPARE_SPEC; COMPARE_IMPL not allowed here
                    if (otherModule.getCodeNameRelease() > relMin) {
                        // Great, skip the spec version.
                        return true;
                    } else {
                        // As usual.
                        if (otherModule.getSpecificationVersion() == null)
                            return false;
                        else if (new SpecificationVersion(dep.getVersion()).compareTo(otherModule.getSpecificationVersion()) > 0)
                            return false;
                        else
                            return true;
                    }
                }
            }
        }

        return false;
    }


    /** Tests dependency on the IDE */
    boolean checkIdeDependency( Dependency dep,
                                ModuleInfo ide ) {

        String IDEName = ide.getCodeName();
        SpecificationVersion IDESpecVersion = ide.getSpecificationVersion();
        String IDEImplVersion = ide.getImplementationVersion();

        // Not equal names
        if ( !IDEName.equals ( dep.getName() ) )
            return false;
        //return ModuleDescription.getStringFormatted ("MSG_IDE_Name", name, IDEName); // NOI18N

            if ( dep.getComparison() == Dependency.COMPARE_SPEC ) {
                return new SpecificationVersion(dep.getVersion()).compareTo(IDESpecVersion) <= 0;
                // ? null : ModuleDescription.getStringFormatted ("MSG_IDE_Spec", version, IDESpecVersion); // NOI18N
            }
            else if ( dep.getComparison() == Dependency.COMPARE_IMPL ) {
                return dep.getVersion().equals (IDEImplVersion);
                // ? null : ModuleDescription.getStringFormatted ("MSG_IDE_Impl", version, IDEImplVersion); // NOI18N
            }
            else {
                // COMPARE_ANY
                throw new IllegalStateException("Cannot have COMPARE_ANY on IDE dependency"); // NOI18N
            }
    }
    
    private List checkBrokenImplDependency( ModuleInfo md, Collection result ) {
        ModuleInfo[] installedModules = Updates.getInstalledModules();
        
        List brokenlist = new ArrayList();
        Dependency dep, depR;
        for (int i = 0; i < installedModules.length; i++) {
            Iterator deps = installedModules[i].getDependencies().iterator();
            while ( deps.hasNext() ) {
                dep = (Dependency) deps.next();
                if ( dep.getName().equals (md.getCodeName ())
                        && dep.getComparison() == Dependency.COMPARE_IMPL ) {                          
                    if ( ! dep.getVersion().equals( md.getImplementationVersion() ) ) {
                        // Dependency ids broken, try to find if there is new version
                        // of module with proper implementation version
                        Iterator it = Wizard.getAllModules().iterator();
                        boolean found = false;
                        while ( it.hasNext() ) {
                            ModuleUpdate mu = (ModuleUpdate)it.next();
                            if ( mu.getRemoteModule().getCodeName().equals( installedModules[i].getCodeName() )
                                && mu.getRemoteModule().getSpecificationVersion().compareTo(
                                installedModules[i].getSpecificationVersion() ) > 0 )
                            {
                                boolean maybeOK = true;
                                Iterator depsR = mu.getRemoteModule().getDependencies().iterator();
                                while ( depsR.hasNext() ) {
                                    depR = (Dependency) depsR.next();
                                    if ( depR.getName().equals (md.getCodeName ())
                                            && depR.getComparison() == Dependency.COMPARE_IMPL
                                            && !depR.getVersion().equals( md.getImplementationVersion() ) )
                                    {
                                        maybeOK = false;
                                        break;
                                    }
                                }
                                if ( maybeOK ) {
                                    if ( !result.contains( mu ) ) {
                                        result.add( mu );
                                    }
                                    found = true;
                                    break;
                                }
                            }
                        }
                        if ( !found ) {
                            brokenlist.add( installedModules[i] );
                        }
                        break;
                    }
                    break;
                }
            }
        }

        return brokenlist;
    }
    
    private String getBundle( String key ) {
        return NbBundle.getMessage( DependencyChecker.class, key );
    }
    
    static Comparator getModuleDependencyComparator() {
        return new ModuleDependencyComparator();
    }
    
    static class ModuleDependencyComparator implements Comparator {
        
        public int compare(Object obj, Object obj1) {
             if ( ! ( ( obj instanceof ModuleUpdate ) && ( obj1 instanceof ModuleUpdate ) ) )
                return 0;
            ModuleInfo modA  = ((ModuleUpdate)obj).getRemoteModule();
            ModuleInfo modB  = ((ModuleUpdate)obj1).getRemoteModule();

            if ( moduleDependsOnModule( modA, modB ) )
                return 1;
            else if ( moduleDependsOnModule( modB, modA ) )
                return -1;
            else
                return 0;
        }
        
        // returns true if modA depends on modB
        private boolean moduleDependsOnModule(ModuleInfo modA, ModuleInfo modB) {
            Set depsA = modA.getDependencies();
            Iterator it = depsA.iterator();
            while ( it.hasNext() ) {
                Dependency dep = (Dependency)(it.next());
                if (dep.getType() == Dependency.TYPE_MODULE || dep.getType() == Dependency.TYPE_REQUIRES) {
                    if ( checkModuleDependency ( dep, modB ) )
                        return true;
                }
            }
            return false;
        }
        
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.