PageRenderTime 54ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/ide.ergonomics/src-ant/org/netbeans/modules/ide/ergonomics/ant/ExtractLayer.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 646 lines | 579 code | 22 blank | 45 comment | 34 complexity | f0c74ab23ceba53380cc6a5d4a45f19c MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * If you wish your version of this file to be governed by only the CDDL
  28. * or only the GPL Version 2, indicate your decision by adding
  29. * "[Contributor] elects to include this software in this distribution
  30. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  31. * single choice of license, a recipient has the option to distribute
  32. * your version of this file under either the CDDL, the GPL Version 2 or
  33. * to extend the choice of license to its licensees as provided above.
  34. * However, if you add GPL Version 2 code and therefore, elected the GPL
  35. * Version 2 license, then the option applies only if the new code is
  36. * made subject to such option by the copyright holder.
  37. *
  38. * Contributor(s):
  39. *
  40. * Portions Copyrighted 2008 Sun Microsystems, Inc.
  41. */
  42. package org.netbeans.modules.ide.ergonomics.ant;
  43. import java.awt.image.BufferedImage;
  44. import java.io.*;
  45. import java.net.URL;
  46. import java.util.ArrayList;
  47. import java.util.Enumeration;
  48. import java.util.HashMap;
  49. import java.util.HashSet;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.Set;
  53. import java.util.TreeMap;
  54. import java.util.TreeSet;
  55. import java.util.jar.JarEntry;
  56. import java.util.jar.JarFile;
  57. import java.util.jar.Manifest;
  58. import java.util.regex.Pattern;
  59. import javax.imageio.ImageIO;
  60. import javax.xml.parsers.DocumentBuilder;
  61. import javax.xml.parsers.DocumentBuilderFactory;
  62. import javax.xml.parsers.SAXParserFactory;
  63. import javax.xml.transform.Source;
  64. import javax.xml.transform.Transformer;
  65. import javax.xml.transform.TransformerException;
  66. import javax.xml.transform.TransformerFactory;
  67. import javax.xml.transform.URIResolver;
  68. import javax.xml.transform.dom.DOMResult;
  69. import javax.xml.transform.dom.DOMSource;
  70. import javax.xml.transform.sax.SAXTransformerFactory;
  71. import javax.xml.transform.stream.StreamResult;
  72. import javax.xml.transform.stream.StreamSource;
  73. import org.apache.tools.ant.BuildException;
  74. import org.apache.tools.ant.DirectoryScanner;
  75. import org.apache.tools.ant.Project;
  76. import org.apache.tools.ant.Task;
  77. import org.apache.tools.ant.filters.BaseFilterReader;
  78. import org.apache.tools.ant.filters.ChainableReader;
  79. import org.apache.tools.ant.taskdefs.Concat;
  80. import org.apache.tools.ant.taskdefs.Copy;
  81. import org.apache.tools.ant.types.FileSet;
  82. import org.apache.tools.ant.types.FilterChain;
  83. import org.apache.tools.ant.types.Resource;
  84. import org.apache.tools.ant.types.ResourceCollection;
  85. import org.apache.tools.ant.types.resources.StringResource;
  86. import org.apache.tools.ant.types.resources.ZipResource;
  87. import org.apache.tools.ant.util.FileNameMapper;
  88. import org.apache.tools.zip.ZipEntry;
  89. import org.w3c.dom.Document;
  90. import org.w3c.dom.Node;
  91. import org.xml.sax.Attributes;
  92. import org.xml.sax.EntityResolver;
  93. import org.xml.sax.InputSource;
  94. import org.xml.sax.SAXException;
  95. import org.xml.sax.helpers.DefaultHandler;
  96. /** Extracts icons and bundles from layer.
  97. *
  98. * @author Jaroslav Tulach <jtulach@netbeans.org>
  99. */
  100. public final class ExtractLayer extends Task
  101. implements FileNameMapper, URIResolver, EntityResolver {
  102. private List<FileSet> moduleSet = new ArrayList<FileSet>();
  103. public void addConfiguredModules(FileSet fs) {
  104. moduleSet.add(fs);
  105. }
  106. private List<FileSet> entries = new ArrayList<FileSet>();
  107. public void addConfiguredEntries(FileSet fs) {
  108. entries.add(fs);
  109. }
  110. private File output;
  111. public void setDestDir(File f) {
  112. output = f;
  113. }
  114. private File bundle;
  115. public void setBundle(File f) {
  116. bundle = f;
  117. }
  118. private String clusterName;
  119. public void setClusterName(String n) {
  120. clusterName = n;
  121. }
  122. private FilterChain bundleFilter;
  123. public void addConfiguredBundleFilter(FilterChain b) {
  124. bundleFilter = b;
  125. }
  126. private File badgeFile;
  127. public void setBadgeIcon(File f) {
  128. badgeFile = f;
  129. }
  130. @Override
  131. public void execute() throws BuildException {
  132. if (moduleSet.isEmpty()) {
  133. throw new BuildException();
  134. }
  135. if (output == null) {
  136. throw new BuildException();
  137. }
  138. if (clusterName == null) {
  139. throw new BuildException();
  140. }
  141. BufferedImage badgeIcon;
  142. try {
  143. badgeIcon = badgeFile == null ? ImageIO.read(ExtractLayer.class.getResourceAsStream("badge.png")) : ImageIO.read(badgeFile);
  144. } catch (IOException ex) {
  145. throw new BuildException("Error reading " + badgeFile, ex);
  146. }
  147. Transformer ft;
  148. Transformer rt;
  149. Transformer et;
  150. Transformer bt;
  151. try {
  152. StreamSource fullpaths;
  153. StreamSource relative;
  154. StreamSource entryPoints;
  155. StreamSource bundleEntryPoints;
  156. URL fu = ExtractLayer.class.getResource("full-paths.xsl");
  157. URL ru = ExtractLayer.class.getResource("relative-refs.xsl");
  158. URL eu = ExtractLayer.class.getResource("entry-points.xsl");
  159. URL bu = ExtractLayer.class.getResource("entry-points-to-bundle.xsl");
  160. fullpaths = new StreamSource(fu.openStream());
  161. relative = new StreamSource(ru.openStream());
  162. entryPoints = new StreamSource(eu.openStream());
  163. bundleEntryPoints = new StreamSource(bu.openStream());
  164. SAXTransformerFactory fack;
  165. fack = (SAXTransformerFactory)TransformerFactory.newInstance();
  166. assert Boolean.TRUE.equals(fack.getFeature(SAXTransformerFactory.FEATURE));
  167. fack.setURIResolver(this);
  168. ft = fack.newTransformer(fullpaths);
  169. rt = fack.newTransformer(relative);
  170. rt.setParameter("cluster.name", clusterName);
  171. et = fack.newTransformer(entryPoints);
  172. et.setParameter("cluster.name", clusterName);
  173. bt = fack.newTransformer(bundleEntryPoints);
  174. } catch (Exception ex) {
  175. throw new BuildException(ex);
  176. }
  177. StringBuilder modules = new StringBuilder();
  178. String sep = "\n ";
  179. ByteArrayOutputStream uberLayer = new ByteArrayOutputStream();
  180. try {
  181. uberLayer.write("<?xml version='1.0' encoding='UTF-8'?>\n".getBytes("UTF-8"));
  182. uberLayer.write("<filesystem>\n".getBytes("UTF-8"));
  183. } catch (IOException iOException) {
  184. throw new BuildException(iOException);
  185. }
  186. ByteArrayOutputStream bundleHeader = new ByteArrayOutputStream();
  187. StreamResult bundleOut = new StreamResult(bundleHeader);
  188. StreamResult uberOut = new StreamResult(uberLayer);
  189. SAXParserFactory f = SAXParserFactory.newInstance();
  190. f.setValidating(false);
  191. f.setNamespaceAware(false);
  192. for (FileSet fs : moduleSet) {
  193. DirectoryScanner ds = fs.getDirectoryScanner(getProject());
  194. File basedir = ds.getBasedir();
  195. for (String path : ds.getIncludedFiles()) {
  196. File jar = new File(basedir, path);
  197. try {
  198. JarFile jf = new JarFile(jar);
  199. try {
  200. Manifest mf = jf.getManifest();
  201. if (mf == null) {
  202. continue;
  203. }
  204. String modname = mf.getMainAttributes().getValue("OpenIDE-Module");
  205. if (modname == null) {
  206. continue;
  207. }
  208. String skip = mf.getMainAttributes().getValue("FeaturesOnDemand-Proxy-Layer");
  209. if ("false".equals(skip)) {
  210. continue;
  211. }
  212. String show = mf.getMainAttributes().getValue("AutoUpdate-Show-In-Client");
  213. String base = modname.replaceFirst("/[0-9]+$", "");
  214. if (!"false".equals(show)) {
  215. modules.append(sep).append(base);
  216. sep = ",\\\n ";
  217. }
  218. String mflayer = mf.getMainAttributes().getValue("OpenIDE-Module-Layer");
  219. if (mflayer != null) {
  220. String n = mflayer.replaceFirst("/[^/]+$", "").replace('/', '.') + ".xml";
  221. et.setParameter("filename", n);
  222. et.transform(createSource(jf, jf.getEntry(mflayer)), uberOut);
  223. bt.transform(createSource(jf, jf.getEntry(mflayer)), bundleOut);
  224. }
  225. java.util.zip.ZipEntry generatedLayer = jf.getEntry("META-INF/generated-layer.xml");
  226. if (generatedLayer != null) {
  227. et.setParameter("filename", base + "-generated.xml");
  228. et.transform(createSource(jf, generatedLayer), uberOut);
  229. bt.transform(createSource(jf, generatedLayer), bundleOut);
  230. }
  231. } finally {
  232. jf.close();
  233. }
  234. } catch (Exception x) {
  235. throw new BuildException("Reading " + jar + ": " + x, x, getLocation());
  236. }
  237. }
  238. }
  239. Pattern concatPattern;
  240. Pattern copyPattern;
  241. String uberText = null;
  242. byte[] uberArr = null;
  243. DuplKeys duplKeys = null;
  244. try {
  245. uberLayer.write("</filesystem>\n".getBytes("UTF-8"));
  246. uberText = uberLayer.toString("UTF-8");
  247. uberArr = uberLayer.toByteArray();
  248. log("uberLayer for " + clusterName + "\n" + uberText, Project.MSG_VERBOSE);
  249. Set<String> concatregs = new TreeSet<String>();
  250. Set<String> copyregs = new TreeSet<String>();
  251. Map<String,String> keys = new TreeMap<String,String>();
  252. parse(new ByteArrayInputStream(uberArr), concatregs, copyregs, keys);
  253. log("Concats: " + concatregs, Project.MSG_VERBOSE);
  254. log("Copies : " + copyregs, Project.MSG_VERBOSE);
  255. StringBuilder sb = new StringBuilder();
  256. sep = "";
  257. for (String s : concatregs) {
  258. sb.append(sep);
  259. sb.append(s);
  260. sep = "|";
  261. }
  262. concatPattern = Pattern.compile(sb.toString());
  263. sb = new StringBuilder();
  264. sep = "";
  265. for (String s : copyregs) {
  266. sb.append(sep);
  267. sb.append(s);
  268. sep = "|";
  269. }
  270. copyPattern = Pattern.compile(sb.toString());
  271. duplKeys = new DuplKeys(keys.keySet());
  272. } catch (Exception ex) {
  273. throw new BuildException("Cannot parse layers: " + ex.getMessage(), ex);
  274. }
  275. Map<String,ResArray> bundles = new HashMap<String,ResArray>();
  276. bundles.put("", new ResArray());
  277. ResArray icons = new ResArray();
  278. for (FileSet fs : entries == null ? moduleSet : entries) {
  279. DirectoryScanner ds = fs.getDirectoryScanner(getProject());
  280. File basedir = ds.getBasedir();
  281. for (String path : ds.getIncludedFiles()) {
  282. File jar = new File(basedir, path);
  283. try {
  284. JarFile jf = new JarFile(jar);
  285. try {
  286. Enumeration<JarEntry> en = jf.entries();
  287. while (en.hasMoreElements()) {
  288. JarEntry je = en.nextElement();
  289. if (concatPattern.matcher(je.getName()).matches()) {
  290. ZipEntry zipEntry = new ZipEntry(je);
  291. String noExt = je.getName().replaceFirst("\\.[^\\.]*$", "");
  292. int index = noExt.indexOf("_");
  293. String suffix = index == -1 ? "" : noExt.substring(index + 1);
  294. ResArray ra = bundles.get(suffix);
  295. if (ra == null) {
  296. ra = new ResArray();
  297. bundles.put(suffix, ra);
  298. }
  299. ra.add(new ZipResource(jar, "UTF-8", zipEntry));
  300. ra.add(new StringResource("\n\n"));
  301. }
  302. if (copyPattern.matcher(je.getName()).matches()) {
  303. ZipEntry zipEntry = new ZipEntry(je);
  304. Resource zr = new ZipResource(jar, "UTF-8", zipEntry);
  305. if (badgeIcon != null) {
  306. icons.add(new IconResource(zr, badgeIcon));
  307. } else {
  308. icons.add(zr);
  309. }
  310. }
  311. }
  312. } finally {
  313. jf.close();
  314. }
  315. } catch (Exception x) {
  316. throw new BuildException("Reading " + jar + ": " + x, x, getLocation());
  317. }
  318. }
  319. }
  320. for (Map.Entry<String, ResArray> entry : bundles.entrySet()) {
  321. ResArray ra = entry.getValue();
  322. Concat concat = new Concat();
  323. concat.setProject(getProject());
  324. ra.add(new StringResource(""));
  325. concat.add(ra);
  326. concat.setDestfile(localeVariant(bundle, entry.getKey()));
  327. {
  328. FilterChain ch = new FilterChain();
  329. ch.add(duplKeys);
  330. concat.addFilterChain(ch);
  331. concat.addFilterChain(bundleFilter);
  332. }
  333. Concat.TextElement te = new Concat.TextElement();
  334. te.setProject(getProject());
  335. te.addText("\n\n\ncnbs=\\" + modules + "\n\n");
  336. te.setFiltering(false);
  337. try {
  338. final String antProjects = new String(bundleHeader.toByteArray(), "UTF-8");
  339. te.addText(antProjects + "\n\n");
  340. } catch (UnsupportedEncodingException ex) {
  341. throw new BuildException(ex);
  342. }
  343. concat.addFooter(te);
  344. concat.execute();
  345. }
  346. {
  347. HashMap<String,Resource> names = new HashMap<String,Resource>();
  348. HashSet<String> duplicates = new HashSet<String>();
  349. for (Resource r : icons) {
  350. String name = r.getName();
  351. Resource prev = names.put(name, r);
  352. if (prev != null) {
  353. if (prev.getName().equals(r.getName())) {
  354. continue;
  355. }
  356. duplicates.add(r.getName());
  357. duplicates.add(prev.getName());
  358. }
  359. }
  360. if (!duplicates.isEmpty()) {
  361. throw new BuildException("Duplicated resources are forbidden: " + duplicates.toString().replace(',', '\n'));
  362. }
  363. }
  364. Copy copy = new Copy();
  365. copy.setProject(getProject());
  366. copy.add(icons);
  367. copy.setTodir(output);
  368. copy.add(this);
  369. copy.execute();
  370. try {
  371. StreamSource orig = new StreamSource(new ByteArrayInputStream(uberArr));
  372. DOMResult tmpRes = new DOMResult();
  373. ft.transform(orig, tmpRes);
  374. Node filesystem = tmpRes.getNode().getFirstChild();
  375. String n = filesystem.getNodeName();
  376. assert n.equals("filesystem") : n;
  377. if (filesystem.getChildNodes().getLength() > 0) {
  378. DOMSource tmpSrc = new DOMSource(tmpRes.getNode());
  379. StreamResult gen = new StreamResult(new File(output, "layer.xml"));
  380. rt.transform(tmpSrc, gen);
  381. }
  382. } catch (Exception ex) {
  383. throw new BuildException(ex);
  384. }
  385. }
  386. private void parse(
  387. final InputStream is,
  388. final Set<String> concat, final Set<String> copy,
  389. final Map<String,String> additionalKeys
  390. ) throws Exception {
  391. SAXParserFactory f = SAXParserFactory.newInstance();
  392. f.setValidating(false);
  393. f.setNamespaceAware(false);
  394. f.newSAXParser().parse(is, new DefaultHandler() {
  395. String prefix = "";
  396. @Override
  397. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  398. if (qName.equals("folder")) {
  399. String n = attributes.getValue("name");
  400. prefix += n + "/";
  401. } else if (qName.equals("file")) {
  402. String n = attributes.getValue("name");
  403. addResource(attributes.getValue("url"), true);
  404. prefix += n;
  405. } else if (qName.equals("attr")) {
  406. String name = attributes.getValue("name");
  407. if (name.equals("SystemFileSystem.localizingBundle")) {
  408. String bundlepath = attributes.getValue("stringvalue").replace('.', '/') + ".*properties";
  409. concat.add(bundlepath);
  410. String key;
  411. if (prefix.endsWith("/")) {
  412. key = prefix.substring(0, prefix.length() - 1);
  413. } else {
  414. key = prefix;
  415. }
  416. additionalKeys.put(key, bundlepath);
  417. } else if (name.equals("iconResource") || name.equals("iconBase")) {
  418. String s = attributes.getValue("stringvalue");
  419. if (s == null) {
  420. throw new BuildException("No stringvalue attribute for " + name);
  421. }
  422. addResource("nbresloc:" + s, false);
  423. } else if (attributes.getValue("bundlevalue") != null) {
  424. String bundlevalue = attributes.getValue("bundlevalue");
  425. int idx = bundlevalue.indexOf('#');
  426. String bundle = bundlevalue.substring(0, idx);
  427. String key = bundlevalue.substring(idx + 1);
  428. String bundlepath = bundle.replace('.', '/') + ".*properties";
  429. String prev = additionalKeys.put(key, bundle);
  430. if (prev != null && !bundle.equals(prev)) {
  431. throw new IllegalStateException("key " + key + " from " + bundlepath + " was already defined among " + prev);
  432. }
  433. concat.add(bundlepath);
  434. } else {
  435. addResource(attributes.getValue("urlvalue"), false);
  436. }
  437. }
  438. }
  439. @Override
  440. public void endElement(String uri, String localName, String qName) throws SAXException {
  441. if (qName.equals("folder")) {
  442. prefix = prefix.replaceFirst("[^/]+/$", "");
  443. } else if (qName.equals("file")) {
  444. prefix = prefix.replaceFirst("[^/]+$", "");
  445. }
  446. }
  447. @Override
  448. public InputSource resolveEntity(String pub, String sys) throws IOException, SAXException {
  449. return new InputSource(new StringReader(""));
  450. }
  451. private void addResource(String url, boolean localAllowed) throws BuildException {
  452. if (url == null) {
  453. return;
  454. }
  455. if (url.startsWith("nbres:")) {
  456. url = "nbresloc:" + url.substring(6);
  457. }
  458. final String prfx = "nbresloc:";
  459. if (!url.startsWith(prfx)) {
  460. if (localAllowed) {
  461. if (url.startsWith("/")) {
  462. copy.add(url.substring(1));
  463. } else {
  464. copy.add(".*/" + url);
  465. }
  466. return;
  467. } else {
  468. throw new BuildException("Unknown urlvalue was: " + url);
  469. }
  470. } else {
  471. url = url.substring(prfx.length());
  472. if (url.startsWith("/")) {
  473. url = url.substring(1);
  474. }
  475. }
  476. url = url.replaceFirst("(\\.[^\\.])+$*", ".*$1");
  477. copy.add(url);
  478. }
  479. });
  480. }
  481. private static File localeVariant(File base, String locale) {
  482. if (locale.length() == 0) {
  483. return base;
  484. }
  485. String name = base.getName().replaceFirst("\\.", "_" + locale + ".");
  486. return new File(base.getParentFile(), name);
  487. }
  488. public void setFrom(String arg0) {
  489. }
  490. public void setTo(String arg0) {
  491. }
  492. /** Dash instead of slash file mapper */
  493. public String[] mapFileName(String fileName) {
  494. return new String[] { fileName.replace('/', '-') };
  495. }
  496. public Source resolve(String href, String base) throws TransformerException {
  497. return null;
  498. }
  499. public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
  500. return new InputSource(new ByteArrayInputStream(new byte[0]));
  501. }
  502. private Source createSource(JarFile jf, java.util.zip.ZipEntry entry) {
  503. try {
  504. DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
  505. f.setValidating(false);
  506. DocumentBuilder b = f.newDocumentBuilder();
  507. b.setEntityResolver(this);
  508. Document doc = b.parse(jf.getInputStream(entry));
  509. return new DOMSource(doc);
  510. } catch (Exception ex) {
  511. throw new BuildException(ex);
  512. }
  513. }
  514. private static final class ResArray extends ArrayList<Resource>
  515. implements ResourceCollection {
  516. public boolean isFilesystemOnly() {
  517. return false;
  518. }
  519. }
  520. private class DuplKeys extends BaseFilterReader
  521. implements ChainableReader {
  522. private final Set<String> acceptKeys;
  523. private Map<String,String> map;
  524. private String line;
  525. private int lineIdx;
  526. public DuplKeys(Set<String> acceptKeys) {
  527. this.acceptKeys = acceptKeys;
  528. }
  529. public DuplKeys(Reader in, Set<String> acceptKeys) {
  530. super(new BufferedReader(in));
  531. this.acceptKeys = acceptKeys;
  532. }
  533. @Override
  534. public Reader chain(Reader rdr) {
  535. return new DuplKeys(rdr, acceptKeys);
  536. }
  537. private BufferedReader in() {
  538. return (BufferedReader) in;
  539. }
  540. @Override
  541. public int read() throws IOException {
  542. int equals;
  543. String key;
  544. for (;;) {
  545. if (line != null) {
  546. final int len = line.length();
  547. if (lineIdx < len) {
  548. return line.charAt(lineIdx++);
  549. } else {
  550. if (len > 0 && line.charAt(len - 1) == '\\') {
  551. line = in().readLine();
  552. lineIdx = 0;
  553. } else {
  554. line = null;
  555. }
  556. return '\n';
  557. }
  558. }
  559. do {
  560. line = in().readLine();
  561. if (line == null) {
  562. return -1;
  563. }
  564. } while (line.startsWith("#"));
  565. lineIdx = 0;
  566. equals = line.indexOf('=');
  567. if (equals == -1) {
  568. line = null;
  569. continue;
  570. }
  571. key = line.substring(0, equals).trim();
  572. if (!acceptKeys.contains(key)) {
  573. line = null;
  574. continue;
  575. }
  576. final String value = line.substring(equals + 1);
  577. if (map == null) {
  578. map = new HashMap<String, String>();
  579. }
  580. if (map.containsKey(key)) {
  581. final String oldValue = map.get(key);
  582. if (!value.equals(oldValue)) {
  583. final String msg = "The key " + key +
  584. " is duplicated and values are not identical: '" +
  585. value + "' and '" + oldValue + "'!";
  586. throw new BuildException(msg);
  587. }
  588. // ignore the line
  589. line = null;
  590. continue;
  591. }
  592. map.put(key, value);
  593. continue;
  594. }
  595. }
  596. }
  597. }