comparison fix-ivy.groovy @ 88:9f2ab59a5333

improve ivy clean up and control order of attribs
author smith@nwoca.org
date Wed, 15 Feb 2012 17:11:10 -0500
parents da29f9bde0da
children
comparison
equal deleted inserted replaced
87:be111b66cdc6 88:9f2ab59a5333
1
2 import groovy.xml.QName;
3 import org.codehaus.groovy.runtime.InvokerHelper;
4
5 import java.io.OutputStreamWriter;
6 import java.io.PrintWriter;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10
1 import groovy.xml.* 11 import groovy.xml.*
2 12
3 def xml = new XmlSlurper() 13 println args
4 def ivy = xml.parse( new File('ivy.xml')) 14
5 15 if (args.any { it.toUpperCase() == '-R'} ) {
6 def cfgs = ivy.configurations 16
7 17
8 if (cfgs.@defaultconfmapping.size() == 0) { 18 } else {
9 println "adding defaultconfmapping" 19 processIvy(new File('ivy.xml')
10 cfgs.@defaultconfmapping = '*->default' 20 }
21
22 def processIvy(file) {
23
24 def xml = new XmlSlurper()
25 def ivy = xml.parse( file)
26
27 def cfgs = ivy.configurations
28
29 // default mapping for most dependencies:
30 cfgs.@defaultconfmapping = 'compile->default'
31
32 // Add default config, if missing:
33 if (!cfgs.children().find { it.@name == 'default' } ) {
34 println "adding default config"
35 cfgs.appendNode {
36 conf(name:"default")
37 }
38 }
39
40
41 ivy.dependencies.children().each { dep ->
42 if ( dep.@conf.text()?.contains('test') ) {
43 dep.@conf = 'compile-test->default'
44 } else {
45 dep.attributes().remove('conf')
46 }
47 }
48
49 // find groovy dependencies (or null)
50 groovy = ivy.dependencies.children().find { it.@org == 'org.codehaus.groovy' && it.@name.text().startsWith('groovy') }
51
52 if (groovy) {
53 // Add a groovy conig for groovy projects:
54 if (!cfgs.children().any { it.@name == 'groovy' } ) {
55 println "added private groovy conf"
56 cfgs.appendNode {
57 conf(name:'groovy',visibility:'private',transitive: true)
58 }
59 }
60 // Adjust 'compile' to exend from 'groovy' conf
61 cfgs.children().find { it.@name == 'compile' }.@extends = 'groovy'
62 cfgs.children().find { it.@name == 'groovy' }.@transitive = 'true'
63 groovy.@conf = "groovy->default"
64 println "Groovy ${groovy.@rev} conf changed to ${groovy.@conf}"
65 // Switch project to use groovy-all instead of groovy + deps
66 if (groovy.@name == 'groovy') {
67 println "changed groovy to groovy-all"
68 groovy.@name = 'groovy-all'
69 }
70 // remove exclude for groovy-all
71 ivy.dependencies.children().find { it.name() == 'exclude' && it.@module.text() == 'groovy-all' }.replaceNode {}
72 }
73
74 //def sameConfMappings = ivy.dependencies.children().findAll { it.@conf in ['*->@','*->*'] }
75 //
76 //sameConfMappings.each {
77 // it.@conf = null // "default->compile;%->@"
78 // println "changing conf for ${it.@name} to ${it.@conf}"
79 //}
80
81
82 cfgs.children().each { it.@visibility = 'private' }
83 cfgs.children().find {it.@name == 'runtime' }.@extends = 'compile'
84 cfgs.children().find {it.@name == 'compile-test' }.@extends = 'compile'
85 cfgs.children().find {it.@name == 'runtime-test' }.@extends = 'runtime,compile-test'
86 cfgs.children().find {it.@name == 'default' }.@visibility = 'public'
87 cfgs.children().find {it.@name == 'default' }.@extends = 'runtime'
88
89 if (!cfgs.children().any { it.@name == 'archives' } ) {
90 println "added public 'archives' conf"
91 cfgs.appendNode {
92 conf(name:'archives',visibility:'public')
93 }
94 }
95 cfgs.children().find {it.@name == 'archives' }.@visibility = 'public'
96
97
98 def outputBuilder = new StreamingMarkupBuilder()
99 //new File('ivy.xml').write( XmlUtil.serialize( outputBuilder.bind { mkp.yield ivy }).replaceAll('>','>'))
100
101 def stringWriter = new StringWriter()
102
103
104 def node = new XmlParser().parseText( XmlUtil.serialize( outputBuilder.bind { mkp.yield ivy }))
105 new MyNodePrinter(new IndentPrinter( new PrintWriter(stringWriter))).print(node)
106 file.write(stringWriter.toString())
107
11 } 108 }
12 109 /*
13 if (!cfgs.children().find { it.@name == 'default' } ) { 110 The class below is a copy/paste of groovy's XmlNodePrinter customized to order Ivy.xml attributes in
14 println "adding default config" 111 the desired order and to add some whitespace.
15 cfgs.appendNode { 112 */
16 conf(name:"default") 113 class MyNodePrinter {
114
115 protected void printNameAttributes(Map attributes, ctx) {
116
117 if (attributes == null || attributes.isEmpty()) {
118 return;
119 }
120 def writer = new StringBuffer()
121 attributes.entrySet().sort{
122 switch (it.key ) {
123 case 'org':
124 1
125 break
126 case 'name': 2
127 break
128 case 'rev': 3
129 break
130 case 'extends': 5
131 break
132 default: 99
133 }
134 }.each { p ->
135 def tmp = new StringBuffer()
136 Map.Entry entry = (Map.Entry) p;
137
138 tmp << " "
139 tmp << getName(entry.getKey())
140 tmp << "="
141 Object value = entry.getValue();
142 tmp << quote
143 tmp << value
144 // if (value instanceof String) {
145 // printEscaped((String) value);
146 // } else {
147 // printEscaped(InvokerHelper.toString(value));
148 // }
149 tmp << quote
150 writer << String.format(" %-35s",tmp.toString())
151 // printNamespace(entry.getKey(), ctx);
152 }
153 out.print(" " + writer.toString().trim())
154 }
155
156 protected final IndentPrinter out;
157 private String quote;
158 private boolean namespaceAware = true;
159 private boolean preserveWhitespace = false;
160
161 public MyNodePrinter(PrintWriter out) {
162 this(out, " ");
163 }
164
165 public MyNodePrinter(PrintWriter out, String indent) {
166 this(out, indent, "\"");
167 }
168
169 public MyNodePrinter(PrintWriter out, String indent, String quote) {
170 this(new IndentPrinter(out, indent), quote);
171 }
172
173 public MyNodePrinter(IndentPrinter out) {
174 this(out, "\"");
175 }
176
177 public MyNodePrinter(IndentPrinter out, String quote) {
178 if (out == null) {
179 throw new IllegalArgumentException("Argument 'IndentPrinter out' must not be null!");
180 }
181 this.out = out;
182 this.quote = quote;
183 }
184
185 public MyNodePrinter() {
186 this(new PrintWriter(new OutputStreamWriter(System.out)));
187 }
188
189 public void print(Node node) {
190 print(node, new NamespaceContext());
191 }
192
193 /**
194 * Check if namespace handling is enabled.
195 * Defaults to <code>true</code>.
196 *
197 * @return true if namespace handling is enabled
198 */
199 public boolean isNamespaceAware() {
200 return namespaceAware;
201 }
202
203 /**
204 * Enable and/or disable namespace handling.
205 *
206 * @param namespaceAware the new desired value
207 */
208 public void setNamespaceAware(boolean namespaceAware) {
209 this.namespaceAware = namespaceAware;
210 }
211
212 /**
213 * Check if whitespace preservation is enabled.
214 * Defaults to <code>false</code>.
215 *
216 * @return true if whitespaces are honoured when printing simple text nodes
217 */
218 public boolean isPreserveWhitespace() {
219 return preserveWhitespace;
220 }
221
222 /**
223 * Enable and/or disable preservation of whitespace.
224 *
225 * @param preserveWhitespace the new desired value
226 */
227 public void setPreserveWhitespace(boolean preserveWhitespace) {
228 this.preserveWhitespace = preserveWhitespace;
229 }
230
231 /**
232 * Get Quote to use when printing attributes.
233 *
234 * @return the quote character
235 */
236 public String getQuote() {
237 return quote;
238 }
239
240 /**
241 * Set Quote to use when printing attributes.
242 *
243 * @param quote the quote character
244 */
245 public void setQuote(String quote) {
246 this.quote = quote;
247 }
248
249 protected void print(Node node, NamespaceContext ctx) {
250 /*
251 * Handle empty elements like '<br/>', '<img/> or '<hr noshade="noshade"/>.
252 */
253 if (isEmptyElement(node)) {
254 printLineBegin();
255 out.print("<");
256 out.print(getName(node));
257 if (ctx != null) {
258 printNamespace(node, ctx);
259 }
260 printNameAttributes(node.attributes(), ctx);
261 out.print("/>");
262 printLineEnd();
263 out.flush();
264 return;
265 }
266
267 /*
268 * Hook for extra processing, e.g. GSP tag element!
269 */
270 if (printSpecialNode(node)) {
271 out.flush();
272 return;
273 }
274
275 /*
276 * Handle normal element like <html> ... </html>.
277 */
278 Object value = node.value();
279 if (value instanceof List) {
280 printName(node, ctx, true, isListOfSimple((List) value));
281 printList((List) value, ctx);
282 printName(node, ctx, false, isListOfSimple((List) value));
283 out.flush();
284 return;
285 }
286
287 // treat as simple type - probably a String
288 printName(node, ctx, true, preserveWhitespace);
289 printSimpleItemWithIndent(value);
290 printName(node, ctx, false, preserveWhitespace);
291 out.flush();
292 }
293
294 private boolean isListOfSimple(List value) {
295 for (Object p : value) {
296 if (p instanceof Node) return false;
297 }
298 return preserveWhitespace;
299 }
300
301 protected void printLineBegin() {
302 out.printIndent();
303 }
304
305 protected void printLineEnd() {
306 printLineEnd(null);
307 }
308
309 protected void printLineEnd(String comment) {
310 if (comment != null) {
311 out.print(" <!-- ");
312 out.print(comment);
313 out.print(" -->");
314 }
315 out.println();
316 out.flush();
317 }
318
319 protected void printList(List list, NamespaceContext ctx) {
320 out.incrementIndent();
321 for (Object value : list) {
322 NamespaceContext context = new NamespaceContext(ctx);
323 /*
324 * If the current value is a node, recurse into that node.
325 */
326 if (value instanceof Node) {
327 print((Node) value, context);
328 continue;
329 }
330 printSimpleItem(value);
331 }
332 out.decrementIndent();
333 }
334
335 protected void printSimpleItem(Object value) {
336 if (!preserveWhitespace) printLineBegin();
337 printEscaped(InvokerHelper.toString(value));
338 if (!preserveWhitespace) printLineEnd();
339 }
340
341 protected void printName(Node node, NamespaceContext ctx, boolean begin, boolean preserve) {
342 if (node == null) {
343 throw new NullPointerException("Node must not be null.");
344 }
345 Object name = node.name();
346 if (name == null) {
347 throw new NullPointerException("Name must not be null.");
348 }
349 if (!preserve || begin) printLineBegin();
350 out.print("<");
351 if (!begin) {
352 out.print("/");
353 }
354 out.print(getName(node));
355 if (ctx != null) {
356 printNamespace(node, ctx);
357 }
358 if (begin) {
359 printNameAttributes(node.attributes(), ctx);
360 }
361 out.print(">");
362 if (!preserve || !begin) printLineEnd();
363 }
364
365 protected boolean printSpecialNode(Node node) {
366 return false;
367 }
368
369 protected void printNamespace(Object object, NamespaceContext ctx) {
370 if (namespaceAware) {
371 if (object instanceof Node) {
372 printNamespace(((Node) object).name(), ctx);
373 } else if (object instanceof QName) {
374 QName qname = (QName) object;
375 String namespaceUri = qname.getNamespaceURI();
376 if (namespaceUri != null) {
377 String prefix = qname.getPrefix();
378 if (!ctx.isPrefixRegistered(prefix, namespaceUri)) {
379 ctx.registerNamespacePrefix(prefix, namespaceUri);
380 out.print(" ");
381 out.print("xmlns");
382 if (prefix.length() > 0) {
383 out.print(":");
384 out.print(prefix);
385 }
386 out.print("=" + quote);
387 out.print(namespaceUri);
388 out.print(quote);
389 }
390 }
391 }
392 }
393 }
394
395
396
397 private boolean isEmptyElement(Node node) {
398 if (node == null) {
399 throw new IllegalArgumentException("Node must not be null!");
400 }
401 if (!node.children().isEmpty()) {
402 return false;
403 }
404 return node.text().length() == 0;
405 }
406
407 private String getName(Object object) {
408 if (object instanceof String) {
409 return (String) object;
410 } else if (object instanceof QName) {
411 QName qname = (QName) object;
412 if (!namespaceAware) {
413 return qname.getLocalPart();
414 }
415 return qname.getQualifiedName();
416 } else if (object instanceof Node) {
417 Object name = ((Node) object).name();
418 return getName(name);
419 }
420 return object.toString();
421 }
422
423 private void printSimpleItemWithIndent(Object value) {
424 if (!preserveWhitespace) out.incrementIndent();
425 printSimpleItem(value);
426 if (!preserveWhitespace) out.decrementIndent();
427 }
428
429 // For ' and " we only escape if needed. As far as XML is concerned,
430 // we could always escape if we wanted to.
431 private void printEscaped(String s) {
432 for (int i = 0; i < s.length(); i++) {
433 char c = s.charAt(i);
434 switch (c) {
435 case '<':
436 out.print("&lt;");
437 break;
438 case '>':
439 out.print("&gt;");
440 break;
441 case '&':
442 out.print("&amp;");
443 break;
444 case '\'':
445 if (quote.equals("'"))
446 out.print("&apos;");
447 else
448 out.print(c);
449 break;
450 case '"':
451 if (quote.equals("\""))
452 out.print("&quot;");
453 else
454 out.print(c);
455 break;
456 default:
457 out.print(c);
458 }
459 }
460 }
461
462 protected class NamespaceContext {
463 private final Map<String, String> namespaceMap;
464
465 public NamespaceContext() {
466 namespaceMap = new HashMap<String, String>();
467 }
468
469 public NamespaceContext(NamespaceContext context) {
470 this();
471 namespaceMap.putAll(context.namespaceMap);
472 }
473
474 public boolean isPrefixRegistered(String prefix, String uri) {
475 return namespaceMap.containsKey(prefix) && namespaceMap.get(prefix).equals(uri);
476 }
477
478 public void registerNamespacePrefix(String prefix, String uri) {
479 if (!isPrefixRegistered(prefix, uri)) {
480 namespaceMap.put(prefix, uri);
481 }
482 }
483
484 public String getNamespace(String prefix) {
485 Object uri = namespaceMap.get(prefix);
486 return (uri == null) ? null : uri.toString();
487 }
17 } 488 }
18 } 489 }
19
20 groovy = ivy.dependencies.children().find { it.@org == 'org.codehaus.groovy' && it.@name == 'groovy' }
21 if (groovy) {
22 groovy.@conf = "*->default,optional"
23 println "Groovy ${groovy.@rev} conf changed to ${groovy.@conf}"
24 }
25
26 def sameConfMappings = ivy.dependencies.children().findAll { it.@conf in ['*->@','*->*'] }
27
28 println sameConfMappings.each {
29 it.@conf = "default->compile;%->@"
30 println "changing conf for ${it.@name} to ${it.@conf}"
31 }
32
33
34 def outputBuilder = new StreamingMarkupBuilder()
35 new File('ivy.xml').write( XmlUtil.serialize( outputBuilder.bind { mkp.yield ivy }).replaceAll('&gt;','>'))