Mercurial > public > develkit
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("<"); | |
437 break; | |
438 case '>': | |
439 out.print(">"); | |
440 break; | |
441 case '&': | |
442 out.print("&"); | |
443 break; | |
444 case '\'': | |
445 if (quote.equals("'")) | |
446 out.print("'"); | |
447 else | |
448 out.print(c); | |
449 break; | |
450 case '"': | |
451 if (quote.equals("\"")) | |
452 out.print("""); | |
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('>','>')) |