View Javadoc

1   /*
2    * Jour - java profiler and monitoring library
3    *
4    * Copyright (C) 2004 Jour team
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Library General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Library General Public License for more details.
15   *
16   * You should have received a copy of the GNU Library General Public
17   * License along with this library; if not, write to the
18   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   * Boston, MA  02111-1307, USA.
20   */
21  package net.sf.jour;
22  
23  import java.io.IOException;
24  import java.lang.reflect.InvocationTargetException;
25  import java.lang.reflect.Method;
26  import java.net.URL;
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  import javax.xml.parsers.ParserConfigurationException;
33  
34  import net.sf.jour.config.Aspect;
35  import net.sf.jour.config.AspectProperty;
36  import net.sf.jour.config.Jour;
37  import net.sf.jour.config.Pointcut;
38  import net.sf.jour.filter.ClassFilter;
39  import net.sf.jour.filter.PointcutListFilter;
40  import net.sf.jour.instrumentor.Instrumentor;
41  import net.sf.jour.instrumentor.InstrumentorFactory;
42  import net.sf.jour.log.Logger;
43  import net.sf.jour.util.ConfigFileUtil;
44  import net.sf.jour.util.FileUtil;
45  
46  import org.w3c.dom.Document;
47  import org.w3c.dom.Node;
48  import org.w3c.dom.NodeList;
49  import org.xml.sax.SAXException;
50  
51  /**
52   * @author michaellif
53   */
54  public class Config {
55  
56  	protected static final Logger log = Logger.getLogger();
57  
58  	public static final String DEFAULTCONFING_FILE = "jour.xml";
59  
60  	protected boolean isDebug;
61  
62  	private boolean isSetSerialVersionUID;
63  	
64  	/**
65  	 * Key - ClassFilter, value - Instrumentor
66  	 */
67  	private HashMap instrumentors = new HashMap();
68  
69  	public Config() {
70  		initialize(FileUtil.getFile(DEFAULTCONFING_FILE));
71  	}
72  
73  	public Config(String configFileName) {
74  		if (configFileName == null) {
75  			configFileName = DEFAULTCONFING_FILE;
76  		}
77  		initialize(FileUtil.getFile(configFileName));
78  	}
79  
80  	public Config(URL configLocation) {
81  		initialize(configLocation);
82  	}
83  
84  	protected void initialize(URL configLocation) {
85  		Jour jour = parsJourXML(configLocation);
86  		if (jour != null) {
87  			isDebug = jour.isDebug();
88  			isSetSerialVersionUID = jour.isSetSerialVersionUID();
89  			List aspectList = jour.getAspect();
90  			if (aspectList == null) {
91  				return;
92  			}
93  			for (Iterator i = aspectList.iterator(); i.hasNext();) {
94  				Aspect aspectCfg = (Aspect) i.next();
95  				if (aspectCfg.isEnabled()) {
96  					ClassFilter filter = createFilter(aspectCfg.getTypedef());
97  					PointcutListFilter pointcuts = new PointcutListFilter();
98  					pointcuts.readConfig(aspectCfg.getPointcut());
99  					Instrumentor instr = InstrumentorFactory.createInstrumentor(aspectCfg.getType(), pointcuts);
100 					if (aspectCfg.getProperty() != null) {
101 						for (Iterator pi = aspectCfg.getProperty().iterator(); pi.hasNext();) {
102 							AspectProperty prop = (AspectProperty) pi.next();
103 							setInstrumentorProperty(instr, prop.getName(), prop.getValue());
104 						}
105 					}
106 					instrumentors.put(filter, instr);
107 				}
108 			}
109 		}
110 	}
111 	
112 	private Jour parsJourXML(URL configLocation) {
113 		Jour jour = new Jour();
114 		try {
115 			Document xmlDoc = ConfigFileUtil.loadDocument(configLocation);
116 			Node jourNode = ConfigFileUtil.getFirstElement(xmlDoc, "jour");
117 			if (jourNode == null) {
118 				throw new ConfigException("Invalid XML root");
119 			}
120 			
121 			jour.setDebug(ConfigFileUtil.getNodeAttribute(jourNode, "debug", false));
122 			jour.setSetSerialVersionUID(ConfigFileUtil.getNodeAttribute(jourNode, "setSerialVersionUID", false));
123 			
124 			NodeList aspectList = jourNode.getChildNodes();
125 			for (int j = 0; j < aspectList.getLength(); j++) {
126 	            Node aspectNode = aspectList.item(j);
127 	            if (!"aspect".equals(aspectNode.getNodeName())) {
128 	            	continue;
129 	            }
130 	            
131 	            Aspect aspect = new Aspect();
132 	            
133 	            aspect.setDescr(ConfigFileUtil.getNodeAttribute(aspectNode, "descr"));
134 	            aspect.setType(ConfigFileUtil.getNodeAttribute(aspectNode, "type"));
135 	            aspect.setEnabled(ConfigFileUtil.getNodeAttribute(aspectNode, "enabled", true));
136 	            aspect.setTypedef(ConfigFileUtil.getNodeValue(aspectNode, "typedef"));
137 	            
138 	            NodeList aspectChildList = aspectNode.getChildNodes();
139 	            for (int k = 0; k < aspectChildList.getLength(); k++) {
140 		            Node aspectChildNode = aspectChildList.item(k);
141 		            String nodeName = aspectChildNode.getNodeName();
142 		            
143 		            if ("pointcut".equals(nodeName)) {
144 		            	aspect.addPointcut(parsPointcut(aspectChildNode));
145 		            } else if ("property".equals(nodeName)) {
146 		            	aspect.addProperty(parsProperty(aspectChildNode));
147 		            }
148 		            
149 	            }
150 	            jour.addAspect(aspect);
151 			}
152 		} catch (ParserConfigurationException e) {
153 			throw new ConfigException("Error parsing XML", e);
154 		} catch (SAXException e) {
155 			throw new ConfigException("Error parsing XML", e);
156 		} catch (IOException e) {
157 			throw new ConfigException("Error parsing XML", e);
158 		}
159 		return jour;
160 	}
161 	
162 	private AspectProperty parsProperty(Node node) {
163 		AspectProperty p = new AspectProperty();
164 		p.setName(ConfigFileUtil.getNodeAttribute(node, "name"));
165 		
166 		String value = ConfigFileUtil.getNodeValue(node, "value");
167 		if (value == null) {
168 			value = ConfigFileUtil.getNodeAttribute(node, "value");
169 		}
170 		p.setValue(value);
171 		return p;
172 	}
173 
174 	private Pointcut parsPointcut(Node node) {
175 		Pointcut p = new Pointcut();
176 		String expr = ConfigFileUtil.getNodeAttribute(node, "expr");
177 		if (expr == null) {
178 			expr = node.getNodeValue();
179 		}
180 		p.setExpr(expr);
181 		return p;
182 	}
183 
184 	void setInstrumentorProperty(Instrumentor instrumentor, String name, String value) {
185 		try {
186 			Method method = instrumentor.getClass().getMethod(name, new Class[] {String.class});
187 			method.invoke(instrumentor, new Object[] {value});
188 		} catch (NoSuchMethodException e) {
189 			throw new Error("Can't set property " + name, e);
190 		} catch (IllegalAccessException e) {
191 			throw new Error("Can't set property " + name, e);
192 		} catch (InvocationTargetException e) {
193 			throw new Error("Can't set property " + name, e);
194 		}	
195 	}
196 
197 	public boolean isSetSerialVersionUID() {
198 		return isSetSerialVersionUID;
199 	}
200 	
201 	protected void checkUniqueAspect() throws ConfigException {
202 		HashMap map = new HashMap();
203 		Iterator iter = instrumentors.entrySet().iterator();
204 		while (iter.hasNext()) {
205 			String instrumentor = (String) iter.next();
206 			map.put(instrumentor, "");
207 		}
208 		if (instrumentors.entrySet().size() > map.size()) {
209 			throw new ConfigException("Duplicate aspects in jour.xml are not supported");
210 		}
211 	}
212 
213 	protected ClassFilter createFilter(String typedef) {
214 		return new ClassFilter(typedef);
215 	}
216 
217 	public Instrumentor[] getInstrumentors(String className) throws InterceptorException {
218 		ArrayList instrList = new ArrayList();
219 		Iterator filters = instrumentors.keySet().iterator();
220 		while (filters.hasNext()) {
221 			ClassFilter filter = (ClassFilter) filters.next();
222 			if (filter.accept(className)) {
223 				instrList.add(instrumentors.get(filter));
224 			}
225 		}
226 		return (Instrumentor[]) instrList.toArray(new Instrumentor[0]);
227 	}
228 
229 	public Instrumentor[] getAllInstrumentors() {
230 		ArrayList instrList = new ArrayList();
231 		Iterator filters = instrumentors.keySet().iterator();
232 		while (filters.hasNext()) {
233 			ClassFilter filter = (ClassFilter) filters.next();
234 			instrList.add(instrumentors.get(filter));
235 		}
236 		return (Instrumentor[]) instrList.toArray(new Instrumentor[0]);
237 	}
238 }