| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.uima.util.jet; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileReader; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| |
| public class JetExpander { |
| |
| static final String APACHE_2_LICENSE_HEADER = |
| "/*\n" + |
| " * Licensed to the Apache Software Foundation (ASF) under one\n" + |
| " * or more contributor license agreements. See the NOTICE file\n" + |
| " * distributed with this work for additional information\n" + |
| " * regarding copyright ownership. The ASF licenses this file\n" + |
| " * to you under the Apache License, Version 2.0 (the\n" + |
| " * \"License\"); you may not use this file except in compliance\n" + |
| " * with the License. You may obtain a copy of the License at\n" + |
| " * \n" + |
| " * http://www.apache.org/licenses/LICENSE-2.0\n" + |
| " * \n" + |
| " * Unless required by applicable law or agreed to in writing,\n" + |
| " * software distributed under the License is distributed on an\n" + |
| " * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" + |
| " * KIND, either express or implied. See the License for the\n" + |
| " * specific language governing permissions and limitations\n" + |
| " * under the License.\n" + |
| " */\n\n"; |
| |
| static class ErrorExit extends RuntimeException { |
| private static final long serialVersionUID = 1L; |
| String msg; |
| ErrorExit(String msg) { |
| super(); |
| this.msg = msg; |
| System.err.println("JetExpander error: " + msg); |
| } |
| } |
| |
| FileWriter fileWriter; |
| String outDir; |
| String in; |
| String rootDir; |
| |
| public static void main(String[] args) { |
| // arg 1 = source |
| // arg 2 = dir where output goes |
| JetExpander je = new JetExpander(); |
| je.main1(args); |
| } |
| |
| void main1(String[] args) { |
| try { |
| if (args.length != 2) |
| throw new ErrorExit("Bad Arguments - need 2, source, and output directory."); |
| |
| File inputFile = new File(args[0]); |
| outDir = args[1]; |
| try { |
| rootDir = pathOnly(inputFile.getCanonicalPath()); |
| } catch (IOException e1) { |
| e1.printStackTrace(); |
| throw new ErrorExit("trouble getting input file canonical path."); |
| } |
| |
| in = readFile(args[0]); |
| int i; |
| try { |
| i = outputStart(); |
| expand(i); |
| fileWriter.write("\n return stringBuilder.toString();\n }\n}"); |
| fileWriter.close(); |
| } catch (IOException e2) { |
| e2.printStackTrace(); |
| throw new ErrorExit("IO error writing output file startup."); |
| } |
| } |
| catch (ErrorExit e) { |
| } |
| } |
| |
| String readFile(String fileName) { |
| FileReader fileReader = null; |
| try { |
| File file = new File(fileName); |
| file = file.getCanonicalFile(); |
| fileReader = new FileReader(file); |
| |
| int fileLength = (int)file.length(); // length in bytes >= length in chars due to char encoding |
| char[] buffer = new char [fileLength]; |
| int read_so_far = 0; |
| while (read_so_far < fileLength) { |
| int count = fileReader.read(buffer, read_so_far, fileLength - read_so_far); |
| if (0 > count) |
| break; |
| read_so_far += count; |
| } |
| return new String(buffer, 0, read_so_far).replaceAll("\\r",""); // for linux/unix |
| } catch (FileNotFoundException e) { |
| e.printStackTrace(); |
| throw new ErrorExit("Bad Input File - can't read it: '" + fileName + "'"); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| throw new ErrorExit("IO Error reading input file: '" + fileName + "'"); |
| } finally { |
| if (null != fileReader) |
| try { |
| fileReader.close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| |
| String pathOnly(String f) { |
| int lastSep = f.lastIndexOf(File.separatorChar); |
| return f.substring(0, lastSep); |
| } |
| |
| int outputStart() throws IOException { |
| |
| String p1 = "<%@ jet package=\""; |
| int i = in.indexOf(p1); |
| if (i < 0 ) |
| throw new ErrorExit("Cant find the <% jet package= sequence."); |
| i = i + p1.length(); |
| int nextQuotePos = in.indexOf('"',i); |
| String pkg = in.substring(i,nextQuotePos); |
| |
| String p2 = "imports=\""; |
| i = in.indexOf(p2, nextQuotePos) + p2.length(); |
| nextQuotePos = in.indexOf('"',i); |
| String [] imports = in.substring(i, nextQuotePos).split("\\s+"); |
| |
| String p3 = "class=\""; |
| i = in.indexOf(p3, nextQuotePos) + p3.length(); |
| nextQuotePos = in.indexOf('"',i); |
| String className = in.substring(i, nextQuotePos); |
| |
| String p4 = "implements=\""; |
| String implementsName = null; |
| i = in.indexOf(p4, nextQuotePos) + p4.length(); |
| if (i > 0) { |
| nextQuotePos = in.indexOf('"',i); |
| implementsName = in.substring(i, nextQuotePos); |
| } |
| |
| String outFileName = null; |
| try { |
| // replaceAll with replacement of "File.separator" fails in Java 8 with |
| // illegal arg exception; needs to be doubled! |
| // avoid that by using forward slash which works with Java paths anyways. |
| outFileName = outDir + File.separator + pkg.replaceAll("\\.","/") + File.separator + className + ".java"; |
| (new File(pathOnly(outFileName))).mkdirs(); |
| fileWriter = new FileWriter(outFileName); |
| } catch (IOException e1) { |
| e1.printStackTrace(); |
| throw new ErrorExit( |
| "Bad outputFile - can't open for writing: '" + outFileName + "'"); |
| } |
| fileWriter.write(APACHE_2_LICENSE_HEADER); |
| fileWriter.write("package " + pkg + ";\n\n"); |
| |
| for (int j = 0; j < imports.length; j++) { |
| fileWriter.write("import " + imports[j] + ";\n"); |
| } |
| |
| fileWriter.write("\npublic class " + className); |
| if (implementsName != null) { |
| fileWriter.write(" implements " + implementsName); |
| } |
| fileWriter.write(" {\n\n"); |
| fileWriter.write(" public String generate(Object argument) {\n"); |
| fileWriter.write(" StringBuilder stringBuilder = new StringBuilder();\n"); |
| |
| return in.indexOf('\n', nextQuotePos); |
| } |
| |
| String fixupStr (int start, int end) { |
| // for linux - have to remove the backslash-r sequence |
| return in.substring(start, end).replaceAll("\n","\\\\n").replaceAll("\r","") |
| .replaceAll("\"","\\\\\"") |
| ; |
| } |
| |
| void expand (int i) throws IOException{ |
| for (; i < in.length(); ) { |
| int trigger = in.indexOf("<%",i); |
| if (trigger >= 0) { |
| |
| // String [] lines = in.substring(i,trigger).split("\n",-1); |
| // for (int j = 0; j < lines.length; j++) { |
| // fileWriter.write("\n stringBuilder.append(\"" + lines[j] + |
| // ((j < lines.length-1) ? "\\n" : "") + "\");"); |
| // } |
| fileWriter.write("\n stringBuilder.append(\"" + fixupStr(i, trigger) + "\");"); |
| |
| if (in.charAt(trigger+2) == '@') { |
| i = doInclude(trigger+3); |
| continue; |
| } |
| |
| if (in.charAt(trigger+2) == '=') { |
| i = doInsert(trigger+3); |
| continue; |
| } |
| |
| //fileWriter.write("\n "); |
| int triggerEnd = in.indexOf("%>",trigger+2); |
| fileWriter.write("\n " + in.substring(trigger+2, triggerEnd)); |
| i = triggerEnd+2; |
| if (in.charAt(i) == '\n') |
| i += 1; |
| |
| continue; |
| } |
| else { |
| fileWriter.write("\n stringBuilder.append(\"" + fixupStr(i, in.length()) + "\");"); |
| break; |
| } |
| } |
| } |
| |
| int doInclude(int i) throws IOException { |
| final String p1 = " include file=\""; |
| String savedIn = in; |
| |
| if (!in.substring(i, i + p1.length()).equals(p1)) { |
| throw new ErrorExit("bad include: " + in.substring(i, i+100)); |
| } |
| i = i + p1.length(); |
| int includeEnd = in.indexOf("\"", i); |
| String includeFileName = in.substring(i, includeEnd); |
| String savedUserDir = System.getProperty("user.dir"); |
| System.setProperty("user.dir", rootDir); |
| in = readFile(includeFileName); |
| // strip off headers |
| int endLoc = in.indexOf("*/"); |
| if (endLoc < 0) |
| throw new ErrorExit("Missing initial comment in included file " + includeFileName); |
| in = in.substring(endLoc + 3); // skip over */ plus nl |
| expand(0); |
| System.setProperty("user.dir", savedUserDir); |
| in = savedIn; |
| i = in.indexOf("%>", includeEnd) + 2; |
| if (in.charAt(i) == '\n') |
| i += 1; |
| return i; |
| } |
| |
| int doInsert(int i) throws IOException { |
| int insertEnd = in.indexOf("%>", i); |
| fileWriter.write("\n stringBuilder.append(" + in.substring(i, insertEnd) + ");"); |
| return insertEnd + 2; |
| } |
| } |