1 /* |
|
2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.ant; |
|
19 |
|
20 import java.io.File; |
|
21 import java.io.IOException; |
|
22 import java.util.ArrayList; |
|
23 import java.util.Enumeration; |
|
24 import java.util.HashSet; |
|
25 import java.util.Hashtable; |
|
26 import java.util.Iterator; |
|
27 import java.util.List; |
|
28 import java.util.Vector; |
|
29 |
|
30 import org.apache.tools.ant.BuildException; |
|
31 import org.apache.tools.ant.Project; |
|
32 import org.apache.tools.ant.Target; |
|
33 import org.apache.tools.ant.types.DataType; |
|
34 import org.dom4j.Comment; |
|
35 import org.dom4j.Document; |
|
36 import org.dom4j.DocumentException; |
|
37 import org.dom4j.Element; |
|
38 import org.dom4j.Node; |
|
39 import org.dom4j.Visitor; |
|
40 import org.dom4j.VisitorSupport; |
|
41 import org.dom4j.io.SAXReader; |
|
42 |
|
43 import com.nokia.helium.ant.data.PropertyCommentMeta; |
|
44 import com.nokia.helium.ant.data.PropertyMeta; |
|
45 import com.nokia.helium.core.ant.PostBuildAction; |
|
46 |
|
47 /** |
|
48 * Class to store the status of the signal of a particular target. |
|
49 */ |
|
50 public class BuildStatusDef extends DataType implements PostBuildAction { |
|
51 private static final String DEPRECATED = "deprecated:"; |
|
52 private HashSet<String> output = new HashSet<String>(); |
|
53 |
|
54 @Override |
|
55 public void executeOnPostBuild(Project project, String[] targetNames) { |
|
56 // Run after targets execute so dynamic target names are resolved |
|
57 for (int i = 0; i < targetNames.length; i++) { |
|
58 String[] array = { targetNames[i] }; |
|
59 Target target = findTarget(targetNames[i], getProject(), array); |
|
60 targetCallsHeliumTarget(target, getProject()); |
|
61 } |
|
62 checkTargetsProperties(getProject()); |
|
63 checkDeprecatedProperties(getProject()); |
|
64 |
|
65 if (!output.isEmpty()) { |
|
66 log("*** Configuration report ***", Project.MSG_INFO); |
|
67 for (String outputStr : output) { |
|
68 log(outputStr, Project.MSG_INFO); |
|
69 } |
|
70 } |
|
71 } |
|
72 |
|
73 /** |
|
74 * @param desiredTarget |
|
75 * Target name to search |
|
76 * @param project |
|
77 * Object of the project |
|
78 * @param targetNames |
|
79 * Array of target names |
|
80 * |
|
81 */ |
|
82 @SuppressWarnings("unchecked") |
|
83 public Target findTarget(String desiredTarget, Project project, |
|
84 String[] targetNames) { |
|
85 Hashtable<String, Target> targets; |
|
86 Vector<Target> sorted; |
|
87 |
|
88 // get all targets of the current project |
|
89 targets = project.getTargets(); |
|
90 |
|
91 // sort all targets of the current project |
|
92 sorted = project.topoSort(targetNames[0], targets); |
|
93 |
|
94 // Find the desiredTarget Target object |
|
95 for (Target target : sorted) { |
|
96 if (target.getName().equals(desiredTarget)) { |
|
97 return target; |
|
98 } |
|
99 } |
|
100 throw new BuildException("Could not find target matching " |
|
101 + desiredTarget + "\n"); |
|
102 } |
|
103 |
|
104 /** |
|
105 * If a target defined outside helium are calling a private Helium target |
|
106 * then print warning |
|
107 * |
|
108 */ |
|
109 @SuppressWarnings("unchecked") |
|
110 public void targetCallsHeliumTarget(Target target, Project project) { |
|
111 String location = target.getLocation().getFileName(); |
|
112 |
|
113 try { |
|
114 String heliumpath = new File(project.getProperty("helium.dir")) |
|
115 .getCanonicalPath(); |
|
116 String targetpath = new File(location).getCanonicalPath(); |
|
117 |
|
118 if (!targetpath.contains(heliumpath)) { |
|
119 ArrayList<String> antcallTargets = new ArrayList<String>(); |
|
120 Visitor visitorTarget = new AntTargetVisitor(antcallTargets, |
|
121 project); |
|
122 |
|
123 Element element = findTargetElement(target, project); |
|
124 if (element != null) { |
|
125 element.accept(visitorTarget); |
|
126 } |
|
127 for (String depTargetString : antcallTargets) { |
|
128 String[] array = { depTargetString }; |
|
129 try { |
|
130 Target depTarget = findTarget(depTargetString, project, |
|
131 array); |
|
132 targetCallsHeliumTarget(depTarget, project); |
|
133 } catch (BuildException x) { |
|
134 // We are Ignoring the errors as no need to fail the |
|
135 // build. |
|
136 log( |
|
137 "Exception occured while target defined outside helium are calling a private Helium target " |
|
138 + x.toString(), Project.MSG_DEBUG); |
|
139 x = null; |
|
140 } |
|
141 } |
|
142 |
|
143 for (Enumeration<String> depsEnum = target.getDependencies(); depsEnum |
|
144 .hasMoreElements();) { |
|
145 String depTargetString = depsEnum.nextElement(); |
|
146 String[] array = { depTargetString }; |
|
147 try { |
|
148 Target depTarget = findTarget(depTargetString, project, |
|
149 array); |
|
150 targetCallsHeliumTarget(depTarget, project); |
|
151 } catch (BuildException x) { |
|
152 // We are Ignoring the errors as no need to fail the |
|
153 // build. |
|
154 log( |
|
155 "Exception occured while target defined outside helium are calling a private Helium target " |
|
156 + x.toString(), Project.MSG_DEBUG); |
|
157 x = null; |
|
158 } |
|
159 } |
|
160 } else { |
|
161 checkIfTargetPrivate(target, project); |
|
162 } |
|
163 |
|
164 } catch (IOException e) { |
|
165 // We are Ignoring the errors as no need to fail the build. |
|
166 log( |
|
167 "IOException occured while target defined outside helium are calling a private Helium target " |
|
168 + e.getMessage(), Project.MSG_DEBUG); |
|
169 e.printStackTrace(); |
|
170 } |
|
171 } |
|
172 |
|
173 private class AntTargetVisitor extends VisitorSupport { |
|
174 private List<String> targetList; |
|
175 private Project project; |
|
176 |
|
177 public AntTargetVisitor(List<String> targetList, Project project) { |
|
178 this.targetList = targetList; |
|
179 this.project = project; |
|
180 } |
|
181 |
|
182 public void visit(Element node) { |
|
183 String name = node.getName(); |
|
184 if (name.equals("antcall") || name.equals("runtarget")) { |
|
185 String text = node.attributeValue("target"); |
|
186 extractTarget(text); |
|
187 } |
|
188 } |
|
189 |
|
190 private void extractTarget(String text) { |
|
191 String iText = project.replaceProperties(text); |
|
192 targetList.add(iText); |
|
193 } |
|
194 |
|
195 } |
|
196 |
|
197 /** |
|
198 * Find the xml Element for the target |
|
199 * |
|
200 */ |
|
201 @SuppressWarnings("unchecked") |
|
202 public Element findTargetElement(Target target, Project project) { |
|
203 SAXReader xmlReader = new SAXReader(); |
|
204 |
|
205 Document antDoc = null; |
|
206 |
|
207 String location = target.getLocation().getFileName(); |
|
208 |
|
209 try { |
|
210 File file = new File(location); |
|
211 antDoc = xmlReader.read(file); |
|
212 } catch (DocumentException e) { |
|
213 // We are Ignoring the errors as no need to fail the build. |
|
214 log("Not able read the XML file. " + e.getMessage(), |
|
215 Project.MSG_WARN); |
|
216 } |
|
217 |
|
218 String projectName = antDoc.valueOf("/project/@name"); |
|
219 for (Iterator<Element> iterator = antDoc.selectNodes("//target") |
|
220 .iterator(); iterator.hasNext();) { |
|
221 Element element = iterator.next(); |
|
222 |
|
223 String targetName = element.attributeValue("name"); |
|
224 if (targetName.equals(target.getName()) |
|
225 || (projectName + "." + targetName) |
|
226 .equals(target.getName())) { |
|
227 return element; |
|
228 } |
|
229 } |
|
230 return null; |
|
231 } |
|
232 |
|
233 /** |
|
234 * If target has comment that says it is private them print warning |
|
235 * |
|
236 */ |
|
237 @SuppressWarnings("unchecked") |
|
238 public void checkIfTargetPrivate(Target target, Project project) { |
|
239 Element targetElement = findTargetElement(target, project); |
|
240 if (targetElement != null) { |
|
241 List<Node> children = targetElement |
|
242 .selectNodes("preceding-sibling::node()"); |
|
243 if (children.size() > 0) { |
|
244 // Scan past the text nodes, which are most likely whitespace |
|
245 int index = children.size() - 1; |
|
246 Node child = children.get(index); |
|
247 while (index > 0 && child.getNodeType() == Node.TEXT_NODE) { |
|
248 index--; |
|
249 child = (Node) children.get(index); |
|
250 } |
|
251 |
|
252 // Check if there is a comment node |
|
253 String commentText = null; |
|
254 if (child.getNodeType() == Node.COMMENT_NODE) { |
|
255 Comment macroComment = (Comment) child; |
|
256 commentText = macroComment.getStringValue().trim(); |
|
257 // log(macroName + " comment: " + commentText, |
|
258 // Project.MSG_DEBUG); |
|
259 } |
|
260 |
|
261 if (commentText != null) { |
|
262 if (commentText.contains("Private:")) { |
|
263 output |
|
264 .add("Warning: " |
|
265 + target.getName() |
|
266 + " is private and should only be called by helium"); |
|
267 } |
|
268 if (commentText.contains("<deprecated>")) { |
|
269 output.add("Warning: " + target.getName() + "\n" |
|
270 + commentText); |
|
271 } |
|
272 } |
|
273 } |
|
274 } |
|
275 } |
|
276 |
|
277 /** |
|
278 * To check, is the private properties are overridden by customers. |
|
279 * |
|
280 * @param project |
|
281 */ |
|
282 public void checkTargetsProperties(Project project) { |
|
283 try { |
|
284 String heliumpath = new File(project.getProperty("helium.dir")) |
|
285 .getCanonicalPath(); |
|
286 com.nokia.helium.ant.data.Database db = new com.nokia.helium.ant.data.Database( |
|
287 project, "private"); |
|
288 ArrayList<String> customerProps = getCustomerProperties(project); |
|
289 |
|
290 for (PropertyMeta propertyMeta : db.getProperties()) { |
|
291 if (propertyMeta.getType().equals("boolean")) |
|
292 { |
|
293 String value = project.getProperty(propertyMeta.getName()); |
|
294 if (value != null && !value.equals("true") && !value.equals("false")) |
|
295 { |
|
296 output.add("Warning: " + propertyMeta.getName() + " property is boolean type and not set to true or false, value is " + value); |
|
297 } |
|
298 } |
|
299 } |
|
300 for (PropertyCommentMeta propertyMeta : db.getCommentProperties()) { |
|
301 if (propertyMeta.getType().equals("boolean")) |
|
302 { |
|
303 String value = project.getProperty(propertyMeta.getName()); |
|
304 if (value != null && !value.equals("true") && !value.equals("false")) |
|
305 { |
|
306 output.add("Warning: " + propertyMeta.getName() + " property is boolean type and not set to true or false, value is " + value); |
|
307 } |
|
308 } |
|
309 } |
|
310 for (PropertyMeta propertyMeta : db.getProperties()) { |
|
311 if (propertyMeta.getLocation().contains(heliumpath) |
|
312 && propertyMeta.getScope().equals("private") |
|
313 && customerProps.contains(propertyMeta.getName())) { |
|
314 output.add("Warning: " + propertyMeta.getName() |
|
315 + " property has been overridden"); |
|
316 } |
|
317 } |
|
318 |
|
319 for (PropertyCommentMeta propertyCommentMeta : db.getCommentProperties()) { |
|
320 if (propertyCommentMeta.getLocation().contains(heliumpath) |
|
321 && propertyCommentMeta.getScope().equals("private") |
|
322 && customerProps |
|
323 .contains(propertyCommentMeta.getName())) { |
|
324 output.add("Warning: " + propertyCommentMeta.getName() |
|
325 + " property has been overridden"); |
|
326 } |
|
327 } |
|
328 } catch (IOException e) { |
|
329 e.printStackTrace(); |
|
330 } |
|
331 } |
|
332 |
|
333 /** |
|
334 * To display the warnings for deprecated properties. |
|
335 * |
|
336 * @param project |
|
337 */ |
|
338 public void checkDeprecatedProperties(Project project) { |
|
339 try { |
|
340 String heliumpath = new File(project.getProperty("helium.dir")) |
|
341 .getCanonicalPath(); |
|
342 com.nokia.helium.ant.data.Database db = new com.nokia.helium.ant.data.Database( |
|
343 project, "private"); |
|
344 ArrayList<String> customerProps = getCustomerProperties(project); |
|
345 |
|
346 for (PropertyMeta propertyMeta : db.getProperties()) { |
|
347 if (propertyMeta.getLocation().contains(heliumpath) |
|
348 && (!propertyMeta.getDeprecated().equals("")) |
|
349 && customerProps.contains(propertyMeta.getName())) { |
|
350 output.add("Warning: " |
|
351 + propertyMeta.getName() |
|
352 + " property has been deprecated " |
|
353 + propertyMeta.getDeprecated() |
|
354 + "." |
|
355 + propertyMeta.getSummary().substring( |
|
356 propertyMeta.getSummary().lastIndexOf( |
|
357 DEPRECATED) |
|
358 + DEPRECATED.length())); |
|
359 } |
|
360 } |
|
361 |
|
362 for (PropertyCommentMeta propertyCommentMeta : db |
|
363 .getCommentProperties()) { |
|
364 if (propertyCommentMeta.getLocation().contains(heliumpath) |
|
365 && (!propertyCommentMeta.getDeprecated().equals("")) |
|
366 && customerProps |
|
367 .contains(propertyCommentMeta.getName())) { |
|
368 output.add("Warning: " |
|
369 + propertyCommentMeta.getName() |
|
370 + " property has been deprecated " |
|
371 + propertyCommentMeta.getDeprecated() |
|
372 + "." |
|
373 + propertyCommentMeta.getSummary().substring( |
|
374 propertyCommentMeta.getSummary() |
|
375 .lastIndexOf(DEPRECATED) |
|
376 + DEPRECATED.length())); |
|
377 } |
|
378 } |
|
379 } catch (IOException e) { |
|
380 e.printStackTrace(); |
|
381 } |
|
382 } |
|
383 |
|
384 @SuppressWarnings("unchecked") |
|
385 public ArrayList<String> getCustomerProperties(Project project) { |
|
386 ArrayList<String> props = new ArrayList<String>(); |
|
387 Database db = new Database(null, null, null); |
|
388 try { |
|
389 String heliumpath = new File(project.getProperty("helium.dir")) |
|
390 .getCanonicalPath(); |
|
391 |
|
392 for (Object object : db.getAntFiles(project)) { |
|
393 String antFile = (String) object; |
|
394 antFile = new File(antFile).getCanonicalPath(); |
|
395 |
|
396 if (!antFile.contains(heliumpath)) { |
|
397 SAXReader xmlReader = new SAXReader(); |
|
398 Document antDoc = xmlReader.read(new File(antFile)); |
|
399 |
|
400 List<Element> propertyNodes = antDoc |
|
401 .selectNodes("//property | //param"); |
|
402 for (Element propertyNode : propertyNodes) { |
|
403 props.add(propertyNode.attributeValue("name")); |
|
404 } |
|
405 } |
|
406 } |
|
407 } catch (IOException e) { |
|
408 // We are Ignoring the errors as no need to fail the build. |
|
409 log("IOException: Not able read the Customer Properties " |
|
410 + e.getMessage(), Project.MSG_WARN); |
|
411 } catch (DocumentException e) { |
|
412 // We are Ignoring the errors as no need to fail the build. |
|
413 log("DocumentException: Not able read the Customer Properties " |
|
414 + e.getMessage(), Project.MSG_WARN); |
|
415 } |
|
416 |
|
417 return props; |
|
418 } |
|
419 |
|
420 } |
|