view fixivy.groovy @ 356:22a86f411b3e

revert changes
author Marc Davis <marc.davis@mcoecn.org>
date Tue, 05 Sep 2023 14:07:22 -0400
parents 90325a10fe95
children
line wrap: on
line source
/*

  This script is (was) used for 'fixing' early SSDT ivy.xml files created by NetBeans/ivyBeans.
  It's primary goal is to migrate configurations from NetBeans conventions to Maven/Gradle conventions.
  In order to accomplish this, it needs to correct dependencies, excludes and configurations.  However,
  it's not able to perfectly correct every ssdt project. Some parts of this script may be commented 
  out.  Results of this script much be reviewed carefully before committing.
*/


import groovy.xml.QName;
import org.codehaus.groovy.runtime.InvokerHelper;

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import groovy.xml.*

//args = [ '-r']
//println args

ant = new AntBuilder()


if (args.any { it.toUpperCase() == '-R'} ) {
    
    new File('.').traverse ([ type: groovy.io.FileType.DIRECTORIES, maxDepth: 3 ]) { project -> 
        if (new File(project,'ivy.xml').exists() ) {
            processIvy(new File(project,'ivy.xml'))
        }
    }

} else {
    processIvy(new File('ivy.xml'))
} 

def processIvy(file) {
    println "-" * 60
    println "processing: $file"
    def xml = new XmlSlurper()
    def ivy = xml.parse(file)

    def cfgs =  ivy.configurations
    
    // default mapping for most dependencies:
    cfgs.@defaultconfmapping = 'compile->default(*)'
    
    // Add default config, if missing:
    if (!cfgs.children().find { it.@name == 'default' } ) {
        println "adding default config"
        cfgs.appendNode {
            conf(name:"default",extends:'compile',visibility:'public')
        }
    }    
    
    if (ivy.dependencies.children().find { it.@name == 'org.springframework.web.servlet' } &&
        !ivy.dependencies.children().find { it.@name == 'servlet-api' } ) {
        ivy.dependencies.children().findAll { it.name() == 'dependency' }.list().last() + {
            dependency(name:'servlet-api', org: 'javax.servlet', rev: '2.5')
            dependency(name:'jsp-api', org: 'javax.servlet', rev: '2.0')
        }
        
    }
    
    ivy.dependencies.children().each { dep ->
       if ( dep.@conf.text()?.contains('test') ) {
           dep.@conf = 'compile-test->default(*)' 
       } else if ( dep.@conf.text().contains('castor-ant') ) {
            dep.@conf = 'castor-ant->default(*)'
       } else if (dep.@conf.text() == 'runtime->default' ) {
        // preserve
       } else if (dep.@conf.text().contains('groovy') ) {
        // preserve
       } else{
//           dep.attributes().remove('conf')
       }
    }

//    ensure(ivy.dependencies,["org.spockframework:spock-core:0.5-groovy-1.8"])

//    ensure(ivy.dependencies, 'hibernate-validator', ['org.slf4j:slf4j-api:1.5.6','org.slf4j:slf4j-log4j12:1.5.6'])
//    ensure(ivy.dependencies, 'usas.repository', ["org.springframework:org.springframework.test:3.0.5.RELEASE","org.codehaus.groovy:groovy-all:1.8.2"])    
//    ensure(ivy.dependencies, 'usps.repository', ["org.springframework:org.springframework.test:3.0.5.RELEASE","org.codehaus.groovy:groovy-all:1.8.2"])    
    
       
//    ensure(ivy.dependencies, 'spock-core', ["org.springframework:org.springframework.test:3.0.5.RELEASE"])
//    ensure(ivy.dependencies, 'org.springframework.test', ['org.junit:com.springsource.org.junit:4.9.0'])
//    ensure(ivy.dependencies, 'org.springframework.test', ["org.spockframework:spock-spring:0.5-groovy-1.8"])

    
    // find groovy dependencies (or null)
/*
    groovy = ivy.dependencies.children().find { it.@org == 'org.codehaus.groovy' && it.@name.text().startsWith('groovy') }
    
    if (groovy) {
        // Add a groovy conig for groovy projects:
        if (!cfgs.children().any { it.@name == 'groovy' } ) {
            println "added private groovy conf"
            cfgs.appendNode { 
                conf(name:'groovy',visibility:'private',transitive: true)
            }
        }
        // Adjust 'compile' to exend from 'groovy' conf
        cfgs.children().find { it.@name == 'compile' }.@extends = 'groovy'
        cfgs.children().find { it.@name == 'groovy' }.@transitive = 'true'
        groovy.@conf = "groovy->default"
        println "Groovy ${groovy.@rev} conf changed to ${groovy.@conf}"    
        // Switch project to use groovy-all instead of groovy + deps
        if (groovy.@name == 'groovy') {
            println "changed groovy to groovy-all"
            groovy.@name = 'groovy-all'
        }
        
        def template = new File(file.parent ?: ".",'template.mf')
        if (template.exists()) {
            println "updating groovy in $template"
            ant.replace(file: template, token: 'org.codehaus.groovy-groovy:major',value:'org.codehaus.groovy-groovy-all:major')
        }
        
    }
*/    
//    resolveJunit(ivy.dependencies)
    
    // remove exclude for groovy-all
    ivy.dependencies.children().find { it.name() == 'exclude' && it.@module.text() == 'groovy-all' }.replaceNode {}
    // remove exclude for commons logging
    ivy.dependencies.children().find { it.name() == 'exclude' && it.@module.text() ==  'com.springsource.org.apache.commons.logging' }.replaceNode {}
   
   // Add exclude for regular groovy:
//    ensureExcluded(ivy.dependencies,"org.codehaus.groovy:groovy")
    
    // ensure modules covered by springsource are exluded;
//  ensureSpringSourceExcludes(ivy.dependencies)
/*
    ensureConfiguration(ivy.dependencies,'org.springframework.test','compile-test->*')
    ensureConfiguration(ivy.dependencies,'com.springsource.org.junit','compile-test')
    ensureConfiguration(ivy.dependencies,'spock-core','compile-test')
    ensureConfiguration(ivy.dependencies,'spock-spring','compile-test')
    ensureConfiguration(ivy.dependencies,'httpunit','compile-test->*')
    ensureConfiguration(ivy.dependencies,'org.springframework.aspects','compile->*')
     
    // patch bad junit exludes
    ivy.dependencies.children().findAll { 
        it.name() == 'exclude' && ("${it.@org}" == 'org.junit' || "${it.@module}" == 'org.junit' )
    }.each {         
        println     "replacing ${it.name()} ${it.@org} ${it.@module} as junit:junit"
        it.@org = 'junit'  
        it.@module = 'junit'
    }  
*/
    cfgs.children().each { it.@visibility = 'public' }  // Should be 'private' after initial conversions.
        
    cfgs.children().find {it.@name == 'runtime' }.@extends = 'compile'
    cfgs.children().find {it.@name == 'compile-test' }.@extends = 'compile'
    cfgs.children().find {it.@name == 'runtime-test' }.@extends = 'runtime,compile-test'
    cfgs.children().find {it.@name == 'runtime-test' }.@visibility = 'public'
    cfgs.children().find {it.@name == 'compile-test' }.@visibility = 'public'
    cfgs.children().find {it.@name == 'default' }.@visibility = 'public'
    cfgs.children().find {it.@name == 'default' }.@extends = 'runtime'
    
    if (!cfgs.children().any { it.@name == 'archives' } ) {
        println "added public 'archives' conf"
        cfgs.appendNode { 
           conf(name:'archives',visibility:'public')
        }
    }
    
    cfgs.children().find {it.@name == 'archives' }.@visibility = 'public'
    
    
    def outputBuilder = new StreamingMarkupBuilder()
    //new File('ivy.xml').write(  XmlUtil.serialize( outputBuilder.bind { mkp.yield ivy }).replaceAll('&gt;','>'))
    
    def stringWriter = new StringWriter()

    def node = new XmlParser().parseText( XmlUtil.serialize( outputBuilder.bind { mkp.yield ivy }))
    new MyNodePrinter(new IndentPrinter( new PrintWriter(stringWriter))).print(node)
    file.write(stringWriter.toString())
    
}

def resolveJunit(depends) {

    if (depends.children().any { it.@name == 'com.springsource.org.junit' } ) {
        depends.children().findAll { "${it.@name}" == 'junit' || it.@module == 'junit' }.each { it.replaceNode {} }
    }
    
    if (!depends.children().any { 
        def name = "${it.@name}"
        name.contains ('junit') || name.contains('spock') } ) {
        ensure(depends,["junit:junit:4.8.2"])
        depends.children().findAll { it.@module == 'junit' }.each { it.replaceNode {} }
    }
}

def ensureConfiguration(depends,name,cfg) {
    depends.children().findAll { it.name() == 'dependency' && it.@name == name}.each {
        it.@conf = cfg.contains('->') ? cfg : "$cfg->default(*)"
    }
}

def ensureExcluded(depends,excludeModule) {
    def (o,m) = excludeModule.split(':')
    if (!depends.children().any { it.name() == 'exclude' && it.@module.text() == m}) {
        depends.appendNode {
            println "excluding $o:$m"
            exclude(org: o, module: m)
        }
    }
}

def ensure(depends,exists,requires) {

    if (depends.children().any { it.name() == 'dependency' && it.@name == exists } ) {
        requires.each {
            def (org,name,rev) = it.split(":")
            if (!depends.children().any { it.@name == name } ) {   
                println "  adding requirement $org:$name for $exists"
                depends.children().findAll { it.name() == 'dependency' }.list().last() + {
                    dependency(name: name, org: org, rev: rev)
                }           
            }
        }        
    }
}

def ensure(depends,requires) {

    requires.each {
        def (org,name,rev) = it.split(":")
        if (!depends.children().any { it.@name == name } ) {   
            println "  adding requirement $org:$name "
            depends.children().findAll { it.name() == 'dependency' }.list().last() + {
                dependency(name: name, org: org, rev: rev)
            }           
        }
    }        
}

def ensureSpringSourceExcludes(depends) {
    
    depends.children().findAll { it.name() == 'dependency' && it.@name.text().startsWith('com.springsource.') }.collect {
        "${it.@org}:${it.@name.text() - 'com.springsource.'}"        
    }.each {  ensureExcluded(depends,it) }        
    
}

/*
The class below is a copy/paste of groovy's XmlNodePrinter customized to order Ivy.xml attributes in
the desired order and to add some whitespace.
*/
class MyNodePrinter  {

    protected void printNameAttributes(Map attributes,  ctx) {
     
       if (attributes == null || attributes.isEmpty()) {
           return;
       }
      def writer = new StringBuffer()
      attributes.entrySet().sort{
           switch (it.key ) {
               case 'org': 
                   1
                   break
               case 'name': 2
                   break
               case 'rev': 3
                   break
               case 'extends': 5
                   break
               default: 99
           }
       }.each { p ->
          def tmp = new StringBuffer()
           Map.Entry entry = (Map.Entry) p;
        
           tmp << " "
           tmp << getName(entry.getKey())
           tmp << "="
           Object value = entry.getValue();
           tmp << quote
           tmp << value         
//           if (value instanceof String) {
//               printEscaped((String) value);
//           } else {
//               printEscaped(InvokerHelper.toString(value));
//           }
           tmp << quote
           def size = entry.getKey() in ['org','name'] ? 35 : 22
           writer << String.format(" %-${size}s",tmp.toString())
//           printNamespace(entry.getKey(), ctx);
       }
       out.print(" " + writer.toString().trim())
   }

    protected final IndentPrinter out;
    private String quote;
    private boolean namespaceAware = true;
    private boolean preserveWhitespace = false;

    public MyNodePrinter(PrintWriter out) {
        this(out, "  ");
    }

    public MyNodePrinter(PrintWriter out, String indent) {
        this(out, indent, "\"");
    }

    public MyNodePrinter(PrintWriter out, String indent, String quote) {
        this(new IndentPrinter(out, indent), quote);
    }

    public MyNodePrinter(IndentPrinter out) {
        this(out, "\"");
    }

    public MyNodePrinter(IndentPrinter out, String quote) {
        if (out == null) {
            throw new IllegalArgumentException("Argument 'IndentPrinter out' must not be null!");
        }
        this.out = out;
        this.quote = quote;
    }

    public MyNodePrinter() {
        this(new PrintWriter(new OutputStreamWriter(System.out)));
    }

    public void print(Node node) {
        print(node, new NamespaceContext());
    }

    /**
     * Check if namespace handling is enabled.
     * Defaults to <code>true</code>.
     *
     * @return true if namespace handling is enabled
     */
    public boolean isNamespaceAware() {
        return namespaceAware;
    }

    /**
     * Enable and/or disable namespace handling.
     *
     * @param namespaceAware the new desired value
     */
    public void setNamespaceAware(boolean namespaceAware) {
        this.namespaceAware = namespaceAware;
    }

    /**
     * Check if whitespace preservation is enabled.
     * Defaults to <code>false</code>.
     *
     * @return true if whitespaces are honoured when printing simple text nodes
     */
    public boolean isPreserveWhitespace() {
        return preserveWhitespace;
    }

    /**
     * Enable and/or disable preservation of whitespace.
     *
     * @param preserveWhitespace the new desired value
     */
    public void setPreserveWhitespace(boolean preserveWhitespace) {
        this.preserveWhitespace = preserveWhitespace;
    }

    /**
     * Get Quote to use when printing attributes.
     *
     * @return the quote character
     */
    public String getQuote() {
        return quote;
    }

    /**
     * Set Quote to use when printing attributes.
     *
     * @param quote the quote character
     */
    public void setQuote(String quote) {
        this.quote = quote;
    }

    protected void print(Node node, NamespaceContext ctx) {
        /*
         * Handle empty elements like '<br/>', '<img/> or '<hr noshade="noshade"/>.
         */
        if (isEmptyElement(node)) {
            printLineBegin();
            out.print("<");
            out.print(getName(node));
            if (ctx != null) {
                printNamespace(node, ctx);
            }
            printNameAttributes(node.attributes(), ctx);
            out.print("/>");
            printLineEnd();
            out.flush();
            return;
        }

        /*
         * Hook for extra processing, e.g. GSP tag element!
         */
        if (printSpecialNode(node)) {
            out.flush();
            return;
        }

        /*
         * Handle normal element like <html> ... </html>.
         */
        Object value = node.value();
        if (value instanceof List) {
            printName(node, ctx, true, isListOfSimple((List) value));
            printList((List) value, ctx);
            printName(node, ctx, false, isListOfSimple((List) value));
            out.flush();
            return;
        }

        // treat as simple type - probably a String
        printName(node, ctx, true, preserveWhitespace);
        printSimpleItemWithIndent(value);
        printName(node, ctx, false, preserveWhitespace);
        out.flush();
    }

    private boolean isListOfSimple(List value) {
        for (Object p : value) {
            if (p instanceof Node) return false;
        }
        return preserveWhitespace;
    }

    protected void printLineBegin() {
        out.printIndent();
    }

    protected void printLineEnd() {
        printLineEnd(null);
    }

    protected void printLineEnd(String comment) {
        if (comment != null) {
            out.print(" <!-- ");
            out.print(comment);
            out.print(" -->");
        }
        out.println();
        out.flush();
    }

    protected void printList(List list, NamespaceContext ctx) {
        out.incrementIndent();
        for (Object value : list) {
            NamespaceContext context = new NamespaceContext(ctx);
            /*
             * If the current value is a node, recurse into that node.
             */
            if (value instanceof Node) {
                print((Node) value, context);
                continue;
            }
            printSimpleItem(value);
        }
        out.decrementIndent();
    }

    protected void printSimpleItem(Object value) {
        if (!preserveWhitespace) printLineBegin();
        printEscaped(InvokerHelper.toString(value));
        if (!preserveWhitespace) printLineEnd();
    }

    protected void printName(Node node, NamespaceContext ctx, boolean begin, boolean preserve) {
        if (node == null) {
            throw new NullPointerException("Node must not be null.");
        }
        Object name = node.name();
        if (name == null) {
            throw new NullPointerException("Name must not be null.");
        }
        if (!preserve || begin) printLineBegin();
        out.print("<");
        if (!begin) {
            out.print("/");
        }
        out.print(getName(node));
        if (ctx != null) {
            printNamespace(node, ctx);
        }
        if (begin) {
            printNameAttributes(node.attributes(), ctx);
        }
        out.print(">");
        if (!preserve || !begin) printLineEnd();
    }

    protected boolean printSpecialNode(Node node) {
        return false;
    }

    protected void printNamespace(Object object, NamespaceContext ctx) {
        if (namespaceAware) {
            if (object instanceof Node) {
                printNamespace(((Node) object).name(), ctx);
            } else if (object instanceof QName) {
                QName qname = (QName) object;
                String namespaceUri = qname.getNamespaceURI();
                if (namespaceUri != null) {
                    String prefix = qname.getPrefix();
                    if (!ctx.isPrefixRegistered(prefix, namespaceUri)) {
                        ctx.registerNamespacePrefix(prefix, namespaceUri);
                        out.print(" ");
                        out.print("xmlns");
                        if (prefix.length() > 0) {
                            out.print(":");
                            out.print(prefix);
                        }
                        out.print("=" + quote);
                        out.print(namespaceUri);
                        out.print(quote);
                    }
                }
            }
        }
    }

  

    private boolean isEmptyElement(Node node) {
        if (node == null) {
            throw new IllegalArgumentException("Node must not be null!");
        }
        if (!node.children().isEmpty()) {
            return false;
        }
        return node.text().length() == 0;
    }

    private String getName(Object object) {
        if (object instanceof String) {
            return (String) object;
        } else if (object instanceof QName) {
            QName qname = (QName) object;
            if (!namespaceAware) {
                return qname.getLocalPart();
            }
            return qname.getQualifiedName();
        } else if (object instanceof Node) {
            Object name = ((Node) object).name();
            return getName(name);
        }
        return object.toString();
    }

    private void printSimpleItemWithIndent(Object value) {
        if (!preserveWhitespace) out.incrementIndent();
        printSimpleItem(value);
        if (!preserveWhitespace) out.decrementIndent();
    }

    // For ' and " we only escape if needed. As far as XML is concerned,
    // we could always escape if we wanted to.
    private void printEscaped(String s) {
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case '<':
                    out.print("&lt;");
                    break;
                case '>':
                    out.print("&gt;");
                    break;
                case '&':
                    out.print("&amp;");
                    break;
                case '\'':
                    if (quote.equals("'"))
                        out.print("&apos;");
                    else
                        out.print(c);
                    break;
                case '"':
                    if (quote.equals("\""))
                        out.print("&quot;");
                    else
                        out.print(c);
                    break;
                default:
                    out.print(c);
            }
        }
    }

    protected class NamespaceContext {
        private final Map<String, String> namespaceMap;

        public NamespaceContext() {
            namespaceMap = new HashMap<String, String>();
        }

        public NamespaceContext(NamespaceContext context) {
            this();
            namespaceMap.putAll(context.namespaceMap);
        }

        public boolean isPrefixRegistered(String prefix, String uri) {
            return namespaceMap.containsKey(prefix) && namespaceMap.get(prefix).equals(uri);
        }

        public void registerNamespacePrefix(String prefix, String uri) {
            if (!isPrefixRegistered(prefix, uri)) {
                namespaceMap.put(prefix, uri);
            }
        }

        public String getNamespace(String prefix) {
            Object uri = namespaceMap.get(prefix);
            return (uri == null) ? null : uri.toString();
        }
    }
}