1 //usr/bin/env jshell "$0" "$@"; exit $? 2 //usr/bin/env jshell --execution local "$0" "$@"; exit $? 3 4 /* 5 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. Oracle designates this 11 * particular file as subject to the "Classpath" exception as provided 12 * by Oracle in the LICENSE file that accompanied this code. 13 * 14 * This code is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * version 2 for more details (a copy is included in the LICENSE file that 18 * accompanied this code). 19 * 20 * You should have received a copy of the GNU General Public License version 21 * 2 along with this work; if not, write to the Free Software Foundation, 22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 * 24 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 25 * or visit www.oracle.com if you need additional information or have any 26 * questions. 27 */ 28 29 import javax.xml.transform.OutputKeys; 30 import javax.xml.transform.TransformerFactory; 31 import javax.xml.transform.dom.DOMSource; 32 import javax.xml.transform.stream.StreamResult; 33 import java.io.*; 34 import java.util.*; 35 import java.util.regex.*; 36 import java.nio.file.*; 37 import java.util.stream.Stream; 38 import java.nio.charset.Charset; 39 import java.nio.charset.StandardCharsets; 40 public class PomChecker { 41 public static class XMLNode { 42 org.w3c.dom.Element element; 43 List<XMLNode> children = new ArrayList<>(); 44 Map<String, String> attrMap = new HashMap<>(); 45 46 XMLNode(org.w3c.dom.Element element) { 47 this.element = element; 48 this.element.normalize(); 49 for (int i = 0; i < this.element.getChildNodes().getLength(); i++) { 50 if (this.element.getChildNodes().item(i) instanceof org.w3c.dom.Element e){ 51 this.children.add(new XMLNode(e)); 52 } 53 } 54 for (int i = 0; i < element.getAttributes().getLength(); i++) { 55 if (element.getAttributes().item(i) instanceof org.w3c.dom.Attr attr){ 56 this.attrMap.put(attr.getName(),attr.getValue()); 57 } 58 } 59 } 60 public boolean hasAttr(String name) { return attrMap.containsKey(name); } 61 public String attr(String name) { return attrMap.get(name); } 62 XMLNode(File file) throws Throwable { 63 this(javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file).getDocumentElement()); 64 } 65 void write(File file) throws Throwable { 66 var transformer = TransformerFactory.newInstance().newTransformer(); 67 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 68 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 69 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); 70 transformer.transform(new DOMSource(element.getOwnerDocument()), new StreamResult(file)); 71 } 72 } 73 static Pattern varPattern=Pattern.compile("\\$\\{([^}]*)\\}"); 74 static Pattern trailingWhitespacePattern=Pattern.compile(".* *"); 75 static public String varExpand(Map<String,String> props, String value){ // recurse 76 String result = value; 77 if (varPattern.matcher(value) instanceof Matcher matcher && matcher.find()) { 78 var v = matcher.group(1); 79 result = varExpand(props,value.substring(0, matcher.start()) 80 +(v.startsWith("env") 81 ?System.getenv(v.substring(4)) 82 :props.get(v)) 83 +value.substring(matcher.end())); 84 //out.println("incomming ='"+value+"' v= '"+v+"' value='"+value+"'->'"+result+"'"); 85 } 86 return result; 87 } 88 static boolean isParent(File possibleParent, File maybeChild){ 89 File parent = maybeChild.getParentFile(); 90 while ( parent != null ) { 91 if ( parent.equals( possibleParent ) ) 92 return true; 93 parent = parent.getParentFile(); 94 } 95 return false; 96 } 97 98 99 100 public static void main(String[] args) throws Throwable{ 101 var out = System.out; 102 var err = System.out; 103 104 var osArch = System.getProperty("os.arch"); 105 var osName = System.getProperty("os.name"); 106 var osVersion = System.getProperty("os.version"); 107 var javaVersion = System.getProperty("java.version"); 108 var javaHome = System.getProperty("java.home"); 109 var pwd = new File(System.getProperty("user.dir")); 110 111 if (javaVersion.startsWith("24")){ 112 //out.println("javaVersion "+javaVersion+" looks OK"); 113 114 var props = new LinkedHashMap<String,String>(); 115 var dir = new File("."); 116 var topPom = new XMLNode(new File(dir,"pom.xml")); 117 var babylonDirKey = "babylon.dir"; 118 var spirvDirKey = "beehive.spirv.toolkit.dir"; 119 var hatDirKey = "hat.dir"; 120 var interestingKeys = Set.of(spirvDirKey, babylonDirKey,hatDirKey); 121 var requiredDirKeys = Set.of(babylonDirKey, hatDirKey); 122 var dirKeyToDirMap = new HashMap<String,File>(); 123 124 topPom.children.stream().filter(e->e.element.getNodeName().equals("properties")).forEach(properties -> 125 properties.children.stream().forEach(property ->{ 126 var key = property.element.getNodeName(); 127 var value = varExpand(props,property.element.getTextContent()); 128 props.put(key, value); 129 if (interestingKeys.contains(key)){ 130 var file = new File(value); 131 if (requiredDirKeys.contains(key) && !file.exists()){ 132 err.println("ERR pom.xml has property '"+key+"' with value '"+value+"' but that dir does not exists!"); 133 System.exit(1); 134 } 135 dirKeyToDirMap.put(key,file); 136 } 137 }) 138 ); 139 for (var key:requiredDirKeys){ 140 if (!props.containsKey(key)){ 141 err.println("ERR pom.xml expected to have property '"+key+"' "); 142 System.exit(1); 143 } 144 } 145 146 var javaHomeDir = new File(javaHome); 147 var babylonDir = dirKeyToDirMap.get(babylonDirKey); 148 if (isParent(babylonDir, javaHomeDir)){ 149 var hatDir = dirKeyToDirMap.get(hatDirKey); 150 if (hatDir.equals(pwd)){ 151 var backendsPom = new XMLNode(new File(dir,"backends/pom.xml")); 152 var modules = backendsPom.children.stream().filter(e->e.element.getNodeName().equals("modules")).findFirst().get(); 153 var spirvModule = modules.children.stream().filter(e->e.element.getTextContent().equals("spirv")).findFirst(); 154 if (spirvModule.isPresent()){ 155 if (dirKeyToDirMap.containsKey(spirvDirKey)) { 156 var spirvDir = dirKeyToDirMap.get(spirvDirKey); 157 if (!spirvDir.exists()) { 158 err.println("ERR "+spirvDirKey + " -> '" + spirvDir + "' dir does not exists but module included in backends "); 159 System.exit(1); 160 } 161 }else{ 162 err.println("ERR "+spirvDirKey + " -> variable dir does not exists but module included in backends "); 163 System.exit(1); 164 } 165 } else{ 166 if (dirKeyToDirMap.containsKey(spirvDirKey)) { 167 var spirvDir = dirKeyToDirMap.get(spirvDirKey); 168 if (spirvDir.exists()){ 169 out.println("WRN "+spirvDirKey+" -> '"+spirvDir+"' exists but spirv module not included in backends "); 170 }else{ 171 out.println("INF "+spirvDirKey+" -> '"+spirvDir+"' does not exist and not included in backends "); 172 } 173 } 174 } 175 } else{ 176 err.println("ERR hat.dir='"+hatDir+"' != ${pwd}='"+pwd+"'"); 177 System.exit(1); 178 } 179 }else{ 180 err.println("ERR babylon.dir '"+babylonDir+"' is not a child of javaHome '"+javaHome+"'"); 181 System.exit(1); 182 } 183 }else{ 184 err.println("ERR Incorrect Java version. Is babylon jdk in your path?"); 185 System.exit(1); 186 } 187 188 Set.of("hat", "examples", "backends").forEach(dirName->{ 189 try{ 190 Files.walk(Paths.get(dirName)).filter(p->{ 191 var name = p.toString(); 192 return !name.contains("cmake-build-debug") 193 && !name.contains("rleparser") 194 && ( name.endsWith(".java") || name.endsWith(".cpp") || name.endsWith(".h")); 195 }).forEach(path->{ 196 try{ 197 boolean license = false; 198 for (String line: Files.readAllLines(path, StandardCharsets.UTF_8)){ 199 if (line.contains("\t")){ 200 err.println("ERR TAB "+path+":"+line); 201 } 202 if (line.endsWith(" ")) { 203 err.println("ERR TRAILING WHITESPACE "+path+":"+line); 204 } 205 if (Pattern.matches("^ *(package|import).*$",line)) { // I saw this a few times....? 206 err.println("ERR WEIRD INDENT "+path+":"+line); 207 } 208 if (Pattern.matches("^.*Copyright.*202[4-9].*Oracle.*$",line)) { // not foolproof I know 209 license = true; 210 } 211 } 212 if (!license){ 213 err.println("ERR MISSING LICENSE "+path); 214 } 215 } catch(IOException ioe){ 216 err.println(ioe); 217 } 218 }); 219 } catch(IOException ioe){ 220 err.println(ioe); 221 } 222 }); 223 } 224 } 225