View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.definition;
9   
10  import org.codehaus.aspectwerkz.ContextClassLoader;
11  import org.codehaus.aspectwerkz.exception.DefinitionException;
12  import org.codehaus.aspectwerkz.util.SequencedHashMap;
13  
14  import java.io.File;
15  import java.io.InputStream;
16  import java.net.MalformedURLException;
17  import java.net.URL;
18  import java.util.ArrayList;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Map;
22  
23  /***
24   * Handles the loading of the definition in various ways and formats.
25   * 
26   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
27   * @TODO: IMPORTANT - Needs to be cleaned up and refactored a lot. Right now it is a mess.
28   */
29  public class DefinitionLoader {
30      /***
31       * The UUID of the single AspectWerkz system if only one definition is used.
32       */
33      public static final String DEFAULT_SYSTEM = "default";
34  
35      /***
36       * The path to the definition file.
37       */
38      public static final String DEFINITION_FILE = System.getProperty("aspectwerkz.definition.file", null);
39  
40      /***
41       * The default name for the definition file.
42       */
43      public static final String DEFAULT_DEFINITION_FILE_NAME = "aspectwerkz.xml";
44  
45      /***
46       * The aspectwerkz definition lists mapped to its UUID.
47       */
48      private static Map s_definitions = new SequencedHashMap();
49  
50      /***
51       * Loads the aspectwerkz definition from disk based on a specific UUID. <p/>Only loads from the disk if the
52       * timestamp for the latest parsing is older than the timestamp for the weave model. <p/>Used in the runtime (not
53       * transformation) process only.
54       * 
55       * @param loader the current class loader
56       * @param uuid the uuid for the weave model to load
57       * @return the aspectwerkz definition
58       */
59      public static SystemDefinition getDefinition(final ClassLoader loader, final String uuid) {
60          final boolean isDirty = false;
61          final List definitions;
62          if (DEFINITION_FILE == null) {
63              // no definition file is specified => try to locate the definition as a resource on the
64              // classpath
65              definitions = loadDefinitionsAsResource(loader);
66          } else {
67              // definition file is specified => create one in memory
68              definitions = loadDefinitionsFromFile(loader, isDirty);
69          }
70  
71          // add the definitions parsed to the cache
72          for (Iterator it = definitions.iterator(); it.hasNext();) {
73              SystemDefinition definition = (SystemDefinition) it.next();
74              if (isDirty || !s_definitions.containsKey(uuid)) {
75                  synchronized (s_definitions) {
76                      s_definitions.put(uuid, definition);
77                  }
78              }
79          }
80          SystemDefinition defToReturn = (SystemDefinition) s_definitions.get(uuid);
81          if (defToReturn == null) {
82              throw new RuntimeException("could not find definition with id [" + uuid + ']');
83          }
84          return defToReturn;
85      }
86  
87      /***
88       * Loads the definitions from disk. Only loads a new model from disk if it has changed.
89       * 
90       * @param loader the current class loader
91       * @return the definitions
92       */
93      private static List loadDefinitionsAsResource(final ClassLoader loader) {
94          final InputStream stream = ContextClassLoader.getResourceAsStream(DEFAULT_DEFINITION_FILE_NAME);
95          if (stream == null) {
96              throw new DefinitionException(
97                  "either you have to specify an XML definition file using the -Daspectwerkz.definition.file=... option or you have to have the XML definition file <aspectwerkz.xml> somewhere on the classpath");
98          }
99          return XmlParser.parse(loader, stream);
100     }
101 
102     /***
103      * Loads the definitions from file.
104      * 
105      * @param useCache use cache
106      * @return the definition
107      */
108     private static List loadDefinitionsFromFile(final ClassLoader loader, final boolean useCache) {
109         String definitionFileName;
110         if (DEFINITION_FILE == null) {
111             URL definition = ContextClassLoader.loadResource(DEFAULT_DEFINITION_FILE_NAME);
112             if (definition == null) {
113                 throw new DefinitionException(
114                     "definition file could not be found on classpath (either specify the file by using the -Daspectwerkz.definition.file=.. option or by having a definition file called aspectwerkz.xml somewhere on the classpath)");
115             }
116             definitionFileName = definition.getFile();
117         } else {
118             definitionFileName = DEFINITION_FILE;
119         }
120         File definitionFile = new File(definitionFileName);
121         return XmlParser.parse(loader, definitionFile, useCache);
122     }
123 
124     /***
125      * Loads the definitions from disk. Only loads a new model from disk if it has changed.
126      * 
127      * @return the definitions
128      */
129     private static List loadAspectClassNamesAsResource() {
130         final InputStream stream = ContextClassLoader.getResourceAsStream(DEFAULT_DEFINITION_FILE_NAME);
131         if (stream == null) {
132             throw new DefinitionException(
133                 "either you have to specify an XML definition file using the -Daspectwerkz.definition.file=... option or you have to have the XML definition file <aspectwerkz.xml> somewhere on the classpath");
134         }
135         return XmlParser.getAspectClassNames(stream);
136     }
137 
138     /***
139      * Loads the definitions from file.
140      * 
141      * @return the definition
142      */
143     private static List loadAspectClassNamesFromFile() {
144         String definitionFileName;
145         if (DEFINITION_FILE == null) {
146             URL definition = ContextClassLoader.loadResource(DEFAULT_DEFINITION_FILE_NAME);
147             if (definition == null) {
148                 throw new DefinitionException(
149                     "definition file could not be found on classpath (either specify the file by using the -Daspectwerkz.definition.file=.. option or by having a definition file called aspectwerkz.xml somewhere on the classpath)");
150             }
151             definitionFileName = definition.getFile();
152         } else {
153             definitionFileName = DEFINITION_FILE;
154         }
155         return XmlParser.getAspectClassNames(new File(definitionFileName));
156     }
157 
158     /***
159      * Returns the default defintion.
160      * 
161      * @param loader
162      * @return the default defintion
163      */
164     public static List getDefaultDefinition(final ClassLoader loader) {
165         if (DEFINITION_FILE != null) {
166             File file = new File(DEFINITION_FILE);
167             if (file.canRead()) {
168                 try {
169                     return XmlParser.parseNoCache(loader, file.toURL());
170                 } catch (MalformedURLException e) {
171                     System.err.println("<WARN> Cannot read " + DEFINITION_FILE);
172                     e.printStackTrace();
173                 }
174             } else {
175                 System.err.println("<WARN> Cannot read " + DEFINITION_FILE);
176             }
177         }
178         return new ArrayList();
179     }
180 
181     /***
182      * Returns the aspect names in the default definition.
183      * 
184      * @return the aspect names in the default definition
185      */
186     public static List getDefaultDefinitionAspectNames() {
187         if (DEFINITION_FILE != null) {
188             File file = new File(DEFINITION_FILE);
189             if (file.canRead()) {
190                 return XmlParser.getAspectClassNames(file);
191             } else {
192                 System.err.println("<WARN> Cannot read " + DEFINITION_FILE);
193             }
194         }
195         return new ArrayList();
196     }
197 }