Archive comparison
Épp a minap futottam bele egy igen nehéz JBoss és classloader problémába. Persze mi voltunk a hibásak, de azért elvitte az egész napot, amíg megtaláltuk a probléma forrását.
A gond az volt, hogy egy EAR
filon belül azegyik WAR
tartalmazott egy extra és felesleges log4j jar-t, ami a classloader sajátosságai miatt nem talált configurációt (noha a JBoss jól volt globálisan beállítva) és emiatt az alapértelmezett beállításokat használta, ami minden debug szinten tolt ki. És beleérte valami thirdparty komponest is, ami teljesen kiakasztotta a rendszert. A megoldás az lett, hogy ear shared library szintre hoztuk a log4j jar-t (pontosabban már ott volt, csak a war-ból kellett kegyomlálni). A végén csak egy kis pom file bűvészkedés volt a megoldás.
És hogyan kerüljük el a hasonló problémákat a jövőben? Az a stratégia, hogy a fejlesztés végén a “before” és “after” ear fájlokat üsszehasonlítjuk és a változások alapján rábólintunk, vagy megnézzük még egy alkalommal.
A munka dandárját egy olyan kis utility végzi, ami hierarchikusan kicsomagolja az egymásba ágyazott zip állományokat.
1import groovy.io.FileType 2 3import java.security.MessageDigest 4 5File.metaClass.extension { 6 path.substring(path.lastIndexOf(".") + 1) 7} 8File.metaClass.isZip { 9 ["zip", "ear", "war"].contains(extension()) 10} 11 12def LeftFile = /c:\environment\_work\ZipComparison\x\LeftFile.zip/ 13def RightFile = /c:\environment\_work\ZipComparison\x\RightFile.zip/ 14 15Map leftHashes = generateHash(cleanup(unzip(new File(LeftFile)))) 16Map rightHashes = generateHash(cleanup(unzip(new File(RightFile)))) 17Map diff = mapDiff(leftHashes, rightHashes) 18printReport(diff) 19 20 21def unzip(File path) { 22 if (!path.isZip()) { 23 return path 24 } 25 File destination = new File(path.path + ".dir") 26 if (destination.exists()) 27 destination.deleteDir() 28 destination.mkdirs() 29 def ant = new AntBuilder() 30 ant.project.getBuildListeners().firstElement().setMessageOutputLevel(1) 31 ant.unzip(src: path.path, 32 dest: destination.path, 33 overwrite: "false") 34 35 destination.eachFileRecurse(FileType.FILES) { File child -> 36 unzip(child) 37 } 38 return destination 39} 40 41def cleanup(File file) { 42 file.eachFileRecurse(FileType.FILES) { File f -> 43 if (f.isZip()) { 44 f.delete() 45 } 46 } 47 return file; 48} 49 50def generateHash(File dir) { 51 Map hashes = [:] 52 dir.eachFileRecurse(FileType.FILES) { File file -> 53 def md = generateMD5(file) 54 hashes[file.path.substring(dir.path.length() + 1)] = md 55 } 56 hashes 57} 58 59def generateMD5(final File file) { 60 MessageDigest digest = MessageDigest.getInstance("MD5") 61 file.withInputStream() { is -> 62 byte[] buffer = new byte[8192] 63 int read = 0 64 while ((read = is.read(buffer)) > 0) { 65 digest.update(buffer, 0, read); 66 } 67 } 68 byte[] md5sum = digest.digest() 69 BigInteger bigInt = new BigInteger(1, md5sum) 70 return bigInt.toString(16).padLeft(32, '0') 71} 72 73 74def mapDiff(Map oldMap, Map newMap) { 75 def newKeys = newMap*.key 76 def oldKeys = oldMap*.key 77 78 def removedKeys = oldKeys - newKeys 79 def addedKeys = newKeys - oldKeys 80 def commonKeys = newKeys - removedKeys - addedKeys 81 def changedKeys = commonKeys.findAll { oldMap[it] != newMap[it] } 82 def unchangedKeys = commonKeys - changedKeys 83 84 def changes = [ 85 removed: oldMap.findAll { it.key in removedKeys }, 86 added: newMap.findAll { it.key in addedKeys }, 87 changed: oldMap.findAll { it.key in changedKeys }, 88 unchanged: newMap.findAll { it.key in unchangedKeys } 89 ] 90} 91 92private void printReport(Map diff) { 93 println "Only In Left" 94 println "============" 95 diff["removed"].each { 96 println it.key 97 } 98 println "Only In Right" 99 println "============" 100 diff["added"].each { 101 println it.key 102 } 103 println "Changed" 104 println "============" 105 diff["changed"].each { 106 println it.key 107 } 108}