View Javadoc

    1   /*
    2    * $Id: CompileUnit.java,v 1.9 2004/07/10 03:31:38 bran Exp $
    3    *
    4    * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
    5    *
    6    * Redistribution and use of this software and associated documentation
    7    * ("Software"), with or without modification, are permitted provided that the
    8    * following conditions are met:
    9    *  1. Redistributions of source code must retain copyright statements and
    10   * notices. Redistributions must also contain a copy of this document.
    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 "groovy" must not be used to endorse or promote products
    15   * derived from this Software without prior written permission of The Codehaus.
    16   * For written permission, please contact info@codehaus.org.
    17   *  4. Products derived from this Software may not be called "groovy" nor may
    18   * "groovy" appear in their names without prior written permission of The
    19   * Codehaus. "groovy" is a registered trademark of The Codehaus.
    20   *  5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
    21   *
    22   * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
    23   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    24   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    25   * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
    26   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    27   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    28   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    29   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    30   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    31   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
    32   * DAMAGE.
    33   *
    34   */
    35  package org.codehaus.groovy.ast;
    36
    37  import java.security.CodeSource;
    38  import java.util.ArrayList;
    39  import java.util.HashMap;
    40  import java.util.Iterator;
    41  import java.util.List;
    42  import java.util.Map;
    43
    44  import org.codehaus.groovy.control.CompilerConfiguration;
    45
    46  /***
    47   * Represents the entire contents of a compilation step which consists of one
    48   * or more {@link ModuleNode}instances
    49   *
    50   * @author <a href="mailto:james@coredevelopers.net">James Strachan </a>
    51   * @version $Revision: 1.9 $
    52   */
    53  public class CompileUnit {
    54
    55      private List modules = new ArrayList();
    56      private Map classes = new HashMap();
    57      private CompilerConfiguration config;
    58      private ClassLoader classLoader;
    59      private CodeSource codeSource;
    60      private Map cachedClasses = new HashMap();
    61
    62      public static final Object NO_CLASS = new Object();
    63
    64
    65      public CompileUnit(ClassLoader classLoader, CompilerConfiguration config) {
    66      	this(classLoader, null, config);
    67      }
    68
    69      public CompileUnit(ClassLoader classLoader, CodeSource codeSource, CompilerConfiguration config) {
    70          this.classLoader = classLoader;
    71          this.config = config;
    72          this.codeSource = codeSource;
    73      }
    74
    75      public List getModules() {
    76          return modules;
    77      }
    78
    79      public void addModule(ModuleNode node) {
    80          modules.add(node);
    81          node.setUnit(this);
    82          addClasses(node.classes);
    83      }
    84
    85      /***
    86       * @return the ClassNode for the given qualified name or returns null if
    87       *         the name does not exist in the current compilation unit
    88       *         (ignoring the .class files on the classpath)
    89       */
    90      public ClassNode getClass(String name) {
    91          return (ClassNode) classes.get(name);
    92      }
    93
    94      /***
    95       * @return a list of all the classes in each module in the compilation unit
    96       */
    97      public List getClasses() {
    98          List answer = new ArrayList();
    99          for (Iterator iter = modules.iterator(); iter.hasNext();) {
    100             ModuleNode module = (ModuleNode) iter.next();
    101             answer.addAll(module.getClasses());
    102         }
    103         return answer;
    104     }
    105
    106     public CompilerConfiguration getConfig() {
    107         return config;
    108     }
    109
    110     public ClassLoader getClassLoader() {
    111         return classLoader;
    112     }
    113
    114     public CodeSource getCodeSource() {
    115     	return codeSource;
    116     }
    117
    118
    119     /***
    120      * Loads a class on the compile classpath so that it can be introspected
    121      *
    122      * @param type
    123      * @return @throws
    124      *         ClassNotFoundException
    125      */
    126     public Class loadClass(String type) throws ClassNotFoundException {
    127     	Object obj = cachedClasses.get(type);
    128     	if ( obj == NO_CLASS ) {
    129     		throw new ClassNotFoundException(type);
    130     	}
    131     	if ( obj != null) {
    132     		return (Class)obj;
    133     	}
    134
    135     	Class answer = null;
    136     	ClassLoader lastLoader  = getClassLoader();
    137     	try {
    138     		answer = lastLoader.loadClass(type);
    139     	} catch (ClassNotFoundException e) {
    140     		// fall through
    141     	}
    142
    143         try {
    144             ClassLoader loader = Thread.currentThread().getContextClassLoader();
    145         	if ( answer == null && loader != lastLoader /*&& loader != null*/) {
    146                 lastLoader = loader;
    147         		answer = loader.loadClass(type);
    148         	}
    149         }
    150         catch (ClassNotFoundException e1) {
    151             // fall through
    152         }
    153
    154         // lets try our class loader
    155         try {
    156             ClassLoader loader = getClass().getClassLoader();
    157         	if ( answer == null && loader != lastLoader) {
    158                 lastLoader = loader;
    159         		answer = loader.loadClass(type);
    160         	}
    161         }
    162         catch (ClassNotFoundException e2) {
    163             // fall through
    164         }
    165
    166         try {
    167         	if (answer == null ) {
    168         		answer = Class.forName(type);
    169         	}
    170         }
    171         catch (ClassNotFoundException e2) {
    172             // fall through
    173         }
    174
    175         if ( answer == null ) {
    176         	cachedClasses.put(type,NO_CLASS);
    177         	throw new ClassNotFoundException(type);
    178         } else {
    179             if (!type.equals(answer.getName())) { // br case sensitive match
    180                 cachedClasses.put(type,NO_CLASS);
    181                 System.out.println("Mismatch: answer.getName() = " + answer.getName() + ", type = " + type);
    182                 throw new ClassNotFoundException(type);
    183             }
    184             cachedClasses.put(type,answer);
    185         }
    186
    187         return answer;
    188     }
    189
    190
    191     /***
    192      * Appends all of the fully qualified class names in this
    193      * module into the given map
    194      */
    195     void addClasses(List classList) {
    196         for (Iterator iter = classList.iterator(); iter.hasNext();) {
    197             addClass((ClassNode) iter.next());
    198         }
    199     }
    200
    201     /***
    202      *  Adds a class to the unit.
    203      */
    204     public void addClass(ClassNode node) {
    205         String name = node.getName();
    206         if (classes.containsKey(name)) {
    207             throw new RuntimeException(
    208                 "Error: duplicate class declaration for name: " + name + " and class: " + node);
    209         }
    210         classes.put(name, node);
    211     }
    212
    213 }