1/* 2 [The "BSD licence"] 3 Copyright (c) 2009 Shaoting Cai 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*/ 28package org.antlr.gunit.swingui.runner; 29 30import java.io.*; 31import java.util.HashMap; 32 33/** 34 * Class loader for parser & lexer generated by antlr. 35 * @author Shaoting 36 */ 37public class ParserLoader extends ClassLoader { 38 39 private HashMap<String, Class> classList; 40 private String grammar; 41 42 /** 43 * Create a class loader for antlr parser/lexer. 44 * @param grammarName 45 * @param classDir 46 */ 47 public ParserLoader(String grammarName, String classDir) throws IOException, ClassNotFoundException { 48 49 final String lexerName = grammarName + "Lexer"; 50 51 // load all the class files in the "classDir" related to the grammarName 52 File dir = new File(classDir); 53 if(dir.isDirectory()) { 54 classList = new HashMap<String, Class>(); 55 grammar = grammarName; 56 File[] files = dir.listFiles(new ClassFilenameFilter(grammarName)); 57 for(File f : files) { 58 59 // load class data 60 final InputStream in = new BufferedInputStream(new FileInputStream(f)); 61 final byte[] classData = new byte[in.available()]; 62 in.read(classData); 63 in.close(); 64 65 // define class 66 final Class newClass = defineClass(null, classData, 0, classData.length); 67 assert(newClass != null); 68 resolveClass(newClass); 69 70 // save to hashtable 71 final String fileName = f.getName(); 72 final String className = fileName.substring(0, fileName.lastIndexOf(".")); 73 classList.put(className, newClass); 74 //System.out.println("adding: " + className); 75 } 76 } else { 77 throw new IOException(classDir + " is not a directory."); 78 } 79 80 if(classList.isEmpty() || !classList.containsKey(lexerName)) { 81 throw new ClassNotFoundException(lexerName + " not found."); 82 } 83 84 } 85 86 87 88 @Override 89 public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { 90 //System.out.print("loading: " + name); 91 if(name.startsWith(grammar)) { 92 if(classList.containsKey(name)) { 93 //System.out.println(" .... found"); 94 return classList.get(name); 95 } else { 96 //System.out.println(" .... not found"); 97 throw new ClassNotFoundException(name); 98 } 99 100 } else { 101 final Class c = findSystemClass(name); 102 //System.out.println(" .... system found " + c.getName()); 103 return c; 104 } 105 } 106 107 /** 108 * Accepts grammarname...($...)?.class 109 */ 110 protected static class ClassFilenameFilter implements FilenameFilter { 111 112 private String grammarName; 113 114 protected ClassFilenameFilter(String name) { 115 grammarName = name; 116 } 117 118 public boolean accept(File dir, String name) { 119 return name.startsWith(grammarName) && name.endsWith(".class"); 120 } 121 122 } 123 124} 125