]>
Commit | Line | Data |
---|---|---|
878ddf1f | 1 | /** @file\r |
2 | OverrideProcess class.\r | |
3 | \r | |
4 | OverrideProcess class is used to override surface area information. \r | |
5 | \r | |
6 | Copyright (c) 2006, Intel Corporation\r | |
7 | All rights reserved. This program and the accompanying materials\r | |
8 | are licensed and made available under the terms and conditions of the BSD License\r | |
9 | which accompanies this distribution. The full text of the license may be found at\r | |
10 | http://opensource.org/licenses/bsd-license.php\r | |
11 | \r | |
12 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
13 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
14 | \r | |
15 | **/\r | |
16 | package org.tianocore.build.global;\r | |
17 | \r | |
18 | import java.util.HashMap;\r | |
19 | import java.util.Map;\r | |
20 | \r | |
21 | import javax.xml.namespace.QName;\r | |
22 | \r | |
23 | import org.apache.tools.ant.BuildException;\r | |
24 | import org.apache.xmlbeans.XmlCursor;\r | |
25 | import org.apache.xmlbeans.XmlObject;\r | |
26 | import org.tianocore.BootModesDocument;\r | |
27 | import org.tianocore.BuildOptionsDocument;\r | |
28 | import org.tianocore.DataHubsDocument;\r | |
29 | import org.tianocore.EventsDocument;\r | |
30 | import org.tianocore.ExternsDocument;\r | |
31 | import org.tianocore.FormsetsDocument;\r | |
32 | import org.tianocore.GuidsDocument;\r | |
33 | import org.tianocore.HobsDocument;\r | |
34 | import org.tianocore.IncludesDocument;\r | |
35 | import org.tianocore.LibrariesDocument;\r | |
36 | import org.tianocore.LibraryClassDefinitionsDocument;\r | |
37 | import org.tianocore.MsaHeaderDocument;\r | |
38 | import org.tianocore.MsaLibHeaderDocument;\r | |
ad82307c | 39 | import org.tianocore.PcdCodedDocument;\r |
878ddf1f | 40 | import org.tianocore.PPIsDocument;\r |
41 | import org.tianocore.ProtocolsDocument;\r | |
42 | import org.tianocore.SourceFilesDocument;\r | |
43 | import org.tianocore.SystemTablesDocument;\r | |
44 | import org.tianocore.VariablesDocument;\r | |
250258de | 45 | import org.tianocore.PackageDependenciesDocument;\r |
878ddf1f | 46 | \r |
47 | /**\r | |
48 | This class is used to override surface area information. For example, MBD can\r | |
49 | overried MSA, Platform can override all information of the module. \r | |
50 | \r | |
51 | <p>Override will take effect if two element satisfy one of following two condition: </p>\r | |
52 | <ul>\r | |
53 | <li>Element name and its attribute OverrideID equal each other. </li>\r | |
54 | <li>Element is defined as exclusive which mean such element can be\r | |
55 | only appeared in the surface area. </li>\r | |
56 | </ul>\r | |
57 | \r | |
58 | <p>For example, here OutputDirectory element is exclusive: </p>\r | |
59 | \r | |
60 | <pre>\r | |
61 | Low priority Xml Document fragment:\r | |
62 | <Libraries>\r | |
63 | <Arch ArchType="IA32">\r | |
64 | <Library OverrideID="8888">EdkPeCoffLoaderLib</Library>\r | |
65 | <Library OverrideID="8888">BasePeCoffLib</Library>\r | |
66 | </Arch>\r | |
67 | </Libraries> \r | |
68 | <BuildOptions>\r | |
69 | <OutputDirectory IntermediateDirectories="MODULE"/>\r | |
70 | <Option>CC_FLAGS = "/NOLOGO", "/C"</Option>\r | |
71 | <BuildOptions>\r | |
72 | \r | |
73 | High priority Xml Document fragment:\r | |
74 | <Libraries>\r | |
75 | <Arch ArchType="IA32">\r | |
76 | <Library OverrideID="8888">Nt32PeCoffLoaderLib</Library>\r | |
77 | </Arch>\r | |
78 | </Libraries>\r | |
79 | <BuildOptions>\r | |
80 | <OutputDirectory IntermediateDirectories="UNIFIED"/>\r | |
81 | <Option>LIB_FLAGS = "/NOLOGO"</Option>\r | |
82 | <BuildOptions>\r | |
83 | \r | |
84 | The result is: \r | |
85 | <Libraries>\r | |
86 | <Arch ArchType="IA32">\r | |
87 | <Library OverrideID="8888">Nt32PeCoffLoaderLib</Library>\r | |
88 | </Arch>\r | |
89 | </Libraries>\r | |
90 | <BuildOptions>\r | |
91 | <OutputDirectory IntermediateDirectories="UNIFIED"/>\r | |
92 | <Option>CC_FLAGS = "/NOLOGO", "/C"</Option>\r | |
93 | <Option>LIB_FLAGS = "/NOLOGO"</Option>\r | |
94 | <BuildOptions>\r | |
95 | \r | |
96 | </pre>\r | |
97 | \r | |
98 | <p>Note that using XmlBeans to walk through the whole XML document tree.</p> \r | |
99 | \r | |
100 | @since GenBuild 1.0\r | |
101 | @see org.apache.xmlbeans.XmlBeans\r | |
102 | **/\r | |
103 | public class OverrideProcess {\r | |
104 | \r | |
105 | ///\r | |
106 | /// URI, the namespace of current XML schema\r | |
107 | ///\r | |
108 | public static String prefix = "http://www.TianoCore.org/2006/Edk2.0";\r | |
109 | \r | |
110 | ///\r | |
111 | /// list of top elements of surface area\r | |
112 | ///\r | |
113 | public static String[] topElements = { "LibraryClassDefinitions",\r | |
250258de | 114 | "SourceFiles", "Includes", "PackageDependencies", "Libraries", "Protocols",\r |
878ddf1f | 115 | "Events", "Hobs", "PPIs", "Variables", "BootModes",\r |
116 | "SystemTables", "DataHubs", "Formsets", "Guids", "Externs",\r | |
ad82307c | 117 | "PcdCoded", "BuildOptions" };\r |
878ddf1f | 118 | \r |
119 | ///\r | |
120 | /// list of exclusive elements\r | |
121 | ///\r | |
122 | public static String[] exclusiveElements = {"OutputDirectory"};\r | |
123 | \r | |
124 | /**\r | |
125 | Recursively find out all elements specified with OverrideId attribute\r | |
126 | and exclusive elements in current XML object. \r | |
127 | \r | |
128 | @param o curent parsing XML object\r | |
129 | @param map Map to list elements specified OverrideID attribute\r | |
130 | @param execlusiveMap Map to list exclusive elements appeared in current XMl object\r | |
131 | @param level the depth in XML document tree\r | |
132 | **/\r | |
133 | private void listOverrideID(XmlObject o, Map<String,Object> map, Map<String,Object> execlusiveMap, int level) {\r | |
134 | XmlCursor cursor = o.newCursor();\r | |
135 | String name = cursor.getName().getLocalPart();\r | |
136 | for (int i = 0 ; i < exclusiveElements.length; i++){\r | |
137 | if (name.equalsIgnoreCase(exclusiveElements[i])){\r | |
138 | execlusiveMap.put(exclusiveElements[i], cursor.getObject());\r | |
139 | }\r | |
140 | }\r | |
141 | String overrideID = cursor.getAttributeText(new QName("OverrideID"));\r | |
142 | if (overrideID != null) {\r | |
143 | map.put(name + ":" + overrideID, cursor.getObject());\r | |
144 | }\r | |
145 | if (cursor.toFirstChild()) {\r | |
146 | do {\r | |
147 | listOverrideID(cursor.getObject(), map, execlusiveMap, level + 1);\r | |
148 | } while (cursor.toNextSibling());\r | |
149 | }\r | |
150 | }\r | |
151 | \r | |
152 | /**\r | |
153 | This function is used to prepare for overriding with changing data. \r | |
154 | \r | |
155 | @param map original surface area information \r | |
156 | @return after normalize surface area information\r | |
157 | **/\r | |
158 | public synchronized static Map<String, XmlObject> deal(Map<String, XmlObject> map) {\r | |
159 | Map<String, XmlObject> newMap = new HashMap<String, XmlObject>();\r | |
160 | if (map.get("MsaHeader") != null) {\r | |
161 | newMap.put("MsaHeader", ((MsaHeaderDocument) map.get("MsaHeader"))\r | |
162 | .getMsaHeader());\r | |
163 | }\r | |
164 | if (map.get("MsaLibHeader") != null) {\r | |
165 | newMap.put("MsaLibHeader", ((MsaLibHeaderDocument) map\r | |
166 | .get("MsaLibHeader")).getMsaLibHeader());\r | |
167 | }\r | |
168 | if (map.get("LibraryClassDefinitions") != null) {\r | |
169 | newMap.put("LibraryClassDefinitions",\r | |
170 | ((LibraryClassDefinitionsDocument) map\r | |
171 | .get("LibraryClassDefinitions"))\r | |
172 | .getLibraryClassDefinitions());\r | |
173 | }\r | |
174 | if (map.get("SourceFiles") != null) {\r | |
175 | newMap.put("SourceFiles", ((SourceFilesDocument) map\r | |
176 | .get("SourceFiles")).getSourceFiles());\r | |
177 | }\r | |
178 | if (map.get("Includes") != null) {\r | |
179 | newMap.put("Includes", ((IncludesDocument) map.get("Includes"))\r | |
180 | .getIncludes());\r | |
181 | }\r | |
250258de | 182 | if (map.get("PackageDependencies") != null) {\r |
183 | newMap.put("PackageDependencies", ((PackageDependenciesDocument) map.get("PackageDependencies"))\r | |
184 | .getPackageDependencies());\r | |
185 | }\r | |
878ddf1f | 186 | if (map.get("Libraries") != null) {\r |
187 | newMap.put("Libraries", ((LibrariesDocument) map.get("Libraries"))\r | |
188 | .getLibraries());\r | |
189 | }\r | |
190 | if (map.get("Protocols") != null) {\r | |
191 | newMap.put("Protocols", ((ProtocolsDocument) map.get("Protocols"))\r | |
192 | .getProtocols());\r | |
193 | }\r | |
194 | if (map.get("Events") != null) {\r | |
195 | newMap.put("Events", ((EventsDocument) map.get("Events"))\r | |
196 | .getEvents());\r | |
197 | }\r | |
198 | if (map.get("Hobs") != null) {\r | |
199 | newMap.put("Hobs", ((HobsDocument) map.get("Hobs")).getHobs());\r | |
200 | }\r | |
201 | if (map.get("PPIs") != null) {\r | |
202 | newMap.put("PPIs", ((PPIsDocument) map.get("PPIs")).getPPIs());\r | |
203 | }\r | |
204 | if (map.get("Variables") != null) {\r | |
205 | newMap.put("Variables", ((VariablesDocument) map.get("Variables"))\r | |
206 | .getVariables());\r | |
207 | }\r | |
208 | if (map.get("BootModes") != null) {\r | |
209 | newMap.put("BootModes", ((BootModesDocument) map.get("BootModes"))\r | |
210 | .getBootModes());\r | |
211 | }\r | |
212 | if (map.get("SystemTables") != null) {\r | |
213 | newMap.put("SystemTables", ((SystemTablesDocument) map\r | |
214 | .get("SystemTables")).getSystemTables());\r | |
215 | }\r | |
216 | if (map.get("DataHubs") != null) {\r | |
217 | newMap.put("DataHubs", ((DataHubsDocument) map.get("DataHubs"))\r | |
218 | .getDataHubs());\r | |
219 | }\r | |
220 | if (map.get("Formsets") != null) {\r | |
221 | newMap.put("Formsets", ((FormsetsDocument) map.get("Formsets"))\r | |
222 | .getFormsets());\r | |
223 | }\r | |
224 | if (map.get("Guids") != null) {\r | |
225 | newMap.put("Guids", ((GuidsDocument) map.get("Guids")).getGuids());\r | |
226 | }\r | |
227 | if (map.get("Externs") != null) {\r | |
228 | newMap.put("Externs", ((ExternsDocument) map.get("Externs"))\r | |
229 | .getExterns());\r | |
230 | }\r | |
ad82307c | 231 | if (map.get("PcdCoded") != null) {\r |
232 | newMap.put("PcdCoded", ((PcdCodedDocument) map.get("PcdCoded")).getPcdCoded());\r | |
878ddf1f | 233 | }\r |
234 | if (map.get("BuildOptions") != null) {\r | |
235 | newMap.put("BuildOptions", ((BuildOptionsDocument) map\r | |
236 | .get("BuildOptions")).getBuildOptions());\r | |
237 | }\r | |
238 | return newMap;\r | |
239 | }\r | |
240 | \r | |
241 | /**\r | |
242 | Recursively remove all subelement in Xml Object l (with low priority) \r | |
243 | based on OverrideID or exclusive elements. \r | |
244 | \r | |
245 | @param l the XML object to process\r | |
246 | @param map list of elements with OverrideID in high priority XML object\r | |
247 | @param execusiveMap list of exclusive elements in high priority XML object\r | |
248 | **/\r | |
249 | private void cut(XmlCursor l, Map map, Map execusiveMap) {\r | |
250 | String name = l.getName().getLocalPart();\r | |
251 | if (execusiveMap.containsKey(name)){\r | |
252 | l.removeXml();\r | |
253 | return;\r | |
254 | }\r | |
255 | String overrideID = l.getAttributeText(new QName("OverrideID"));\r | |
256 | if (overrideID != null) {\r | |
257 | if (map.containsKey(name + ":" + overrideID)) {\r | |
258 | l.removeXml();\r | |
259 | return;\r | |
260 | }\r | |
261 | }\r | |
262 | if (l.toFirstChild()) {\r | |
263 | do {\r | |
264 | cut(l, map, execusiveMap);\r | |
265 | } while (l.toNextSibling());\r | |
266 | }\r | |
267 | }\r | |
268 | \r | |
269 | private XmlObject cloneXmlObject(XmlObject object, boolean deep) throws BuildException {\r | |
270 | XmlObject result = null;\r | |
271 | try {\r | |
272 | result = XmlObject.Factory.parse(object.getDomNode()\r | |
273 | .cloneNode(deep));\r | |
274 | } catch (Exception ex) {\r | |
275 | throw new BuildException(ex.getMessage());\r | |
276 | }\r | |
277 | return result;\r | |
278 | }\r | |
279 | \r | |
280 | /**\r | |
281 | Process every item list in h and l.\r | |
282 | \r | |
283 | @param h surface area info with high priority\r | |
284 | @param l surface area info with low priority\r | |
285 | @return surface area after override\r | |
286 | **/\r | |
287 | public Map<String, XmlObject> override(Map<String, XmlObject> h,\r | |
288 | Map<String, XmlObject> l) {\r | |
289 | Map<String, XmlObject> result = new HashMap<String, XmlObject>();\r | |
290 | result.put("MsaHeader", override(l.get("MsaHeader"), null));\r | |
291 | result.put("MsaLibHeader", override(l.get("MsaLibHeader"), null));\r | |
292 | for (int i = 0; i < topElements.length; i++) {\r | |
250258de | 293 | if (h != null) {\r |
294 | result.put(topElements[i], override(h.get(topElements[i]), l.get(topElements[i])));\r | |
295 | } else {\r | |
296 | result.put(topElements[i], override(l.get(topElements[i]), null));\r | |
297 | }\r | |
878ddf1f | 298 | }\r |
299 | return result;\r | |
300 | }\r | |
301 | \r | |
302 | /**\r | |
303 | Recursively override two Xml Objects.\r | |
304 | \r | |
305 | @param h Xml Object info with high priority\r | |
306 | @param l Xml Object info with low priority\r | |
307 | @return Xml Object after area\r | |
308 | **/\r | |
309 | public XmlObject override(XmlObject h, XmlObject l) {\r | |
310 | if (l == null && h == null) {\r | |
311 | return null;\r | |
312 | }\r | |
313 | if (h == null) {\r | |
314 | return cloneXmlObject(l, true);\r | |
315 | }\r | |
316 | if (l == null) {\r | |
317 | return cloneXmlObject(h, true);\r | |
318 | }\r | |
319 | XmlCursor hc = h.newCursor();\r | |
320 | if (h.getClass() != l.getClass()) {\r | |
250258de | 321 | System.out.println("Error: Two XmlObject does not with compliant format.");\r |
878ddf1f | 322 | return null;\r |
323 | }\r | |
324 | if (!hc.toFirstChild()) {\r | |
325 | return cloneXmlObject(l, true);\r | |
326 | }\r | |
327 | \r | |
328 | XmlCursor result = cloneXmlObject(h, true).newCursor();\r | |
329 | XmlCursor lcursor = cloneXmlObject(l, true).newCursor();\r | |
330 | result.push();\r | |
331 | result.toNextToken();\r | |
332 | result.insertNamespace("", prefix);\r | |
333 | result.toFirstChild();\r | |
334 | //\r | |
335 | // found out all element specified a OverrideID\r | |
336 | //\r | |
337 | Map<String,Object> hmap = new HashMap<String,Object>();\r | |
338 | Map<String,Object> execlusiveMap = new HashMap<String,Object>();\r | |
339 | listOverrideID(h, hmap, execlusiveMap, 0);\r | |
340 | lcursor.toNextToken();\r | |
341 | lcursor.push();\r | |
342 | //\r | |
343 | // for every direct subelement of l, cut all element satisfied with\r | |
344 | // override rule\r | |
345 | //\r | |
346 | if (lcursor.toFirstChild()) {\r | |
347 | do {\r | |
348 | cut(lcursor, hmap, execlusiveMap);\r | |
349 | } while (lcursor.toNextSibling());\r | |
350 | }\r | |
351 | lcursor.pop();\r | |
352 | if (lcursor.toFirstChild()) {\r | |
353 | do {\r | |
354 | lcursor.copyXml(result);\r | |
355 | result.insertChars("\n");\r | |
356 | } while (lcursor.toNextSibling());\r | |
357 | }\r | |
358 | result.pop();\r | |
359 | return result.getObject();\r | |
360 | }\r | |
361 | } |