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
64
65 definitions = loadDefinitionsAsResource(loader);
66 } else {
67
68 definitions = loadDefinitionsFromFile(loader, isDirty);
69 }
70
71
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 }