1 /*
   2  * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package build.tools.logutil;
  27 
  28 import java.io.BufferedReader;
  29 import java.io.File;
  30 import java.io.FileInputStream;
  31 import java.io.FileNotFoundException;
  32 import java.io.InputStreamReader;
  33 import java.io.IOException;
  34 
  35 import java.util.LinkedList;
  36 import java.util.Queue;
  37 
  38 import java.util.regex.Matcher;
  39 import java.util.regex.Pattern;
  40 
  41 public class Input {
  42 
  43   /**
  44    * The name of the package this class will inhabit.
  45    */
  46   private String packageName;
  47 
  48   /**
  49    * The name of the generated class.
  50    */
  51   private String className;
  52 
  53   /**
  54    * The name of the group of exceptions handled by the class.
  55    */
  56   private String groupName;
  57 
  58   /**
  59    * The group of exceptions.
  60    */
  61   private Queue<InputException> exceptions;
  62 
  63   /**
  64    * Represents the current state of parsing the input.
  65    */
  66   private enum State
  67   {
  68     OUTER,
  69     IN_CLASS,
  70     IN_EXCEPTION_LIST
  71   };
  72 
  73   /**
  74    * Regular expression to match each code line.
  75    */
  76   private static final Pattern EXCEPTION_INFO_REGEX =
  77     Pattern.compile("(\\w+)\\s*(\\d+)\\s*(\\w+)");
  78 
  79   /**
  80    * Parses the specified file to create a new {@link Input}
  81    * object.
  82    *
  83    * @param filename the file to parse.
  84    * @throws FileNotFoundException if the file can't be found.
  85    * @throws IOException if an I/O error occurs.
  86    */
  87   public Input(final String filename)
  88   throws FileNotFoundException, IOException {
  89     BufferedReader r =
  90       new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
  91     State state = State.OUTER;
  92     InputException current = null;
  93     exceptions = new LinkedList<InputException>();
  94     String line;
  95     while ((line = r.readLine()) != null) {
  96       // Skip ; comments
  97       if (line.startsWith(";"))
  98         continue;
  99 
 100       int index = line.indexOf("(");
 101       if (index == -1)
 102         continue;
 103 
 104       switch (state) {
 105       case OUTER:
 106         state = State.IN_CLASS;
 107         String[] classInfo = line.substring(index).split(" ");
 108         packageName = classInfo[0].substring(2, classInfo[0].length() - 1);
 109         className = classInfo[1].substring(1, classInfo[1].length() - 1);
 110         groupName = classInfo[2];
 111         break;
 112       case IN_CLASS:
 113         state = State.IN_EXCEPTION_LIST;
 114         break;
 115       case IN_EXCEPTION_LIST:
 116         boolean inQuote = false;
 117         boolean inCode = false;
 118         boolean end = false;
 119         int start = index + 1;
 120         Queue<String> lines = new LinkedList<String>();
 121         for (int a = start; a < line.length(); ++a) {
 122           if (line.charAt(a) == '(' && !inCode && !inQuote) {
 123             if (current == null)
 124               current =
 125                 new InputException(line.substring(start, a).trim());
 126             start = a + 1;
 127             inCode = true;
 128           }
 129           if (line.charAt(a) == '"')
 130             inQuote = !inQuote;
 131           if (line.charAt(a) == ')' && !inQuote) {
 132             if (inCode) {
 133               lines.offer(line.substring(start, a));
 134               inCode = false;
 135             } else
 136               end = true;
 137           }
 138           if (!end && a == line.length() - 1)
 139             line += r.readLine();
 140         }
 141         for (String l : lines) {
 142           int stringStart = l.indexOf("\"") + 1;
 143           int stringEnd = l.indexOf("\"", stringStart);
 144           Matcher matcher = EXCEPTION_INFO_REGEX.matcher(l.substring(0, stringStart));
 145           if (matcher.find())
 146             current.add(new InputCode(matcher.group(1),
 147                                       Integer.parseInt(matcher.group(2)),
 148                                       matcher.group(3),
 149                                       l.substring(stringStart, stringEnd)));
 150         }
 151         exceptions.offer(current);
 152         current = null;
 153         break;
 154       }
 155     }
 156   }
 157 
 158   /**
 159    * Returns the name of this group of exceptions.
 160    *
 161    * @return the name of this group of exceptions.
 162    */
 163   public String getGroupName()
 164   {
 165     return groupName;
 166   }
 167 
 168   /**
 169    * Returns the name of the package this class will go in.
 170    *
 171    * @return the name of the package.
 172    */
 173   public String getPackageName()
 174   {
 175     return packageName;
 176   }
 177 
 178   /**
 179    * Returns the name of the generated class.
 180    *
 181    * @return the name of the class.
 182    */
 183   public String getClassName()
 184   {
 185     return className;
 186   }
 187 
 188   /**
 189    * Returns the exceptions contained in this class.
 190    *
 191    * @return the exceptions.
 192    */
 193   public Queue<InputException> getExceptions() {
 194     return exceptions;
 195   }
 196 
 197   /**
 198    * Returns a textual representation of this input.
 199    *
 200    * @return a textual representation.
 201    */
 202   public String toString() {
 203     return getClass().getName() +
 204       "[packageName=" + packageName +
 205       ",className=" + className +
 206       ",groupName=" + groupName +
 207       ",exceptions=" + exceptions +
 208       "]";
 209   }
 210 
 211 }