PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/netbeans-7.3/nbbuild/antsrc/org/netbeans/nbbuild/JarWithModuleAttributes.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 418 lines | 332 code | 19 blank | 67 comment | 112 complexity | 88451a991eb67fdf0637e2f77be029d4 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-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. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.nbbuild;
  45. import java.io.File;
  46. import java.io.FileInputStream;
  47. import java.io.IOException;
  48. import java.io.InputStream;
  49. import java.io.InputStreamReader;
  50. import java.util.SortedMap;
  51. import java.util.TreeMap;
  52. import java.util.jar.Attributes;
  53. import java.util.regex.Matcher;
  54. import java.util.regex.Pattern;
  55. import org.apache.tools.ant.BuildException;
  56. import org.apache.tools.ant.Project;
  57. import org.apache.tools.ant.taskdefs.Jar;
  58. import org.apache.tools.ant.taskdefs.Manifest;
  59. /**
  60. * Task just like <jar> but predefines various module attributes.
  61. * Cf. projectized.xml#jar
  62. * @author Jesse Glick
  63. */
  64. public class JarWithModuleAttributes extends Jar {
  65. public JarWithModuleAttributes() {}
  66. private static final Pattern COMMA_SPACE = Pattern.compile(", *");
  67. private static final Pattern IMPL_DEP = Pattern.compile(" *([a-zA-Z0-9_.]+)(/[0-9]+)? *= *(.+) *");
  68. private File stamp;
  69. /** Location of a stamp file to create and/or make newer than the JAR file.
  70. *
  71. * @param stamp the file to create and update
  72. */
  73. public void setStamp(File stamp) {
  74. this.stamp = stamp;
  75. }
  76. static String extractCodeName(Attributes attr) {
  77. return extractCodeName(attr, null);
  78. }
  79. static String extractCodeName(Attributes attr, boolean[] osgi) {
  80. String codename = attr.getValue("OpenIDE-Module");
  81. if (codename != null) {
  82. return codename;
  83. }
  84. codename = attr.getValue("Bundle-SymbolicName");
  85. if (codename == null) {
  86. return null;
  87. }
  88. codename = codename.replace('-', '_');
  89. if (osgi != null) {
  90. osgi[0] = true;
  91. }
  92. int params = codename.indexOf(';');
  93. if (params >= 0) {
  94. return codename.substring(0, params);
  95. } else {
  96. return codename;
  97. }
  98. }
  99. @Override
  100. public void setManifest(File manifestFile) throws BuildException {
  101. Manifest added = new Manifest();
  102. try {
  103. // Check to see if OpenIDE-Module-Implementation-Version is already defined.
  104. String implVers;
  105. String specVer;
  106. String ownCnb;
  107. Manifest staticManifest;
  108. InputStream is = new FileInputStream(manifestFile);
  109. boolean isOSGiMode = false;
  110. try {
  111. staticManifest = new Manifest(new InputStreamReader(is, "UTF-8"));
  112. Manifest.Section mainSection = staticManifest.getMainSection();
  113. implVers = mainSection.getAttributeValue("OpenIDE-Module-Implementation-Version");
  114. specVer = mainSection.getAttributeValue("OpenIDE-Module-Specification-Version");
  115. String myself = mainSection.getAttributeValue("OpenIDE-Module");
  116. if (myself == null) {
  117. myself = mainSection.getAttributeValue("Bundle-SymbolicName");
  118. isOSGiMode = myself != null;
  119. }
  120. if (myself == null) {
  121. throw new BuildException("No OpenIDE-Module in " + manifestFile);
  122. }
  123. int slash = myself.indexOf('/');
  124. if (slash == -1) {
  125. ownCnb = myself;
  126. } else {
  127. ownCnb = myself.substring(0, slash);
  128. }
  129. String cnbs = getProject().getProperty("code.name.base.slashes");
  130. String cnbDots = (cnbs != null) ? cnbs.replace('/', '.') : null;
  131. if (!ownCnb.equals(cnbDots)) {
  132. // #58248: make sure these stay in synch.
  133. throw new BuildException("Mismatch in module code name base: manifest says " + ownCnb +
  134. " but project.xml says " + cnbDots, getLocation());
  135. }
  136. } finally {
  137. is.close();
  138. }
  139. if (isOSGiMode) {
  140. added.addConfiguredAttribute(new Manifest.Attribute("Bundle-ManifestVersion", "2")); // NOI18N
  141. }
  142. String pubPkgs = getProject().getProperty("public.packages");
  143. if (pubPkgs == null) {
  144. throw new BuildException("Must have defined 'public.packages'", getLocation());
  145. }
  146. if (isOSGiMode) {
  147. if (pubPkgs != null && !pubPkgs.equals("-")) {
  148. added.addConfiguredAttribute(new Manifest.Attribute("Export-Package", pubPkgs.replaceAll("\\.\\*", ""))); // NOI18N
  149. }
  150. } else {
  151. added.addConfiguredAttribute(new Manifest.Attribute("OpenIDE-Module-Public-Packages", pubPkgs));
  152. }
  153. String friends = getProject().getProperty("friends");
  154. if (friends != null) {
  155. if (isOSGiMode) {
  156. throw new BuildException("friends defined, yet OSGi does not support that " + friends);
  157. }
  158. added.addConfiguredAttribute(new Manifest.Attribute("OpenIDE-Module-Friends", friends));
  159. }
  160. // #52354: define Class-Path in the manifest automatically.
  161. String javahelpClassPathExtension = getProject().getProperty("javahelp.class.path.extension");
  162. String classPathExtensions = getProject().getProperty("class.path.extensions");
  163. String cp;
  164. if (javahelpClassPathExtension != null) {
  165. if (classPathExtensions != null) {
  166. cp = classPathExtensions + " " + javahelpClassPathExtension;
  167. } else {
  168. cp = javahelpClassPathExtension;
  169. }
  170. } else {
  171. cp = classPathExtensions;
  172. }
  173. if (cp != null) {
  174. added.addConfiguredAttribute(new Manifest.Attribute("Class-Path", cp));
  175. }
  176. String moduleDeps = getProject().getProperty("module.dependencies");
  177. if (moduleDeps != null) {
  178. if (isOSGiMode) {
  179. StringBuilder sb = new StringBuilder();
  180. String sep = "";
  181. for (String one : moduleDeps.split(",")) {
  182. if (one.indexOf('=') != -1) {
  183. throw new BuildException("Implementation dependencies not supported in Netigso mode: " + one);
  184. }
  185. String versionS, codename;
  186. int greaterThan = one.indexOf('>');
  187. if (greaterThan == -1) {
  188. versionS = "0";
  189. codename = one.trim();
  190. } else {
  191. versionS = one.substring(greaterThan + 1).trim();
  192. codename = one.substring(0, greaterThan).trim();
  193. }
  194. if (codename.equals("org.netbeans.libs.osgi")) {
  195. // #184434: do not include a dep on a NB pseudomodule.
  196. // apisupport's BundleActivator wizard anyway adds to manifest:
  197. // Import-Package: org.osgi.framework
  198. continue;
  199. }
  200. int[] version = parseDecimal(versionS, 3);
  201. int slash = codename.indexOf('/');
  202. int hiMajor;
  203. String cnb;
  204. if (slash >= 0) {
  205. cnb = codename.substring(0, slash).trim();
  206. String range = codename.substring(slash + 1).trim();
  207. int dash = range.indexOf('-');
  208. if (dash == -1) {
  209. hiMajor = Integer.parseInt(range);
  210. version[0] += 100 * hiMajor;
  211. } else {
  212. hiMajor = Integer.parseInt(range.substring(dash + 1));
  213. version[0] += 100 * Integer.parseInt(range.substring(0, dash));
  214. }
  215. } else {
  216. cnb = codename;
  217. hiMajor = 0;
  218. }
  219. sb.append(sep);
  220. sep = ", ";
  221. sb.append(cnb).append(";bundle-version=\"[");
  222. String conditionalDot = "";
  223. for (int i = 0; i < version.length; i++) {
  224. sb.append(conditionalDot);
  225. sb.append(version[i]);
  226. conditionalDot = ".";
  227. }
  228. sb.append(",").append((hiMajor + 1) * 100).append(")\"");
  229. }
  230. added.addConfiguredAttribute(new Manifest.Attribute("Require-Bundle", sb.toString())); // NOI18N
  231. } else {
  232. added.addConfiguredAttribute(new Manifest.Attribute("OpenIDE-Module-Module-Dependencies", moduleDeps));
  233. }
  234. }
  235. String javaDep = getProject().getProperty("javac.target");
  236. if (javaDep != null && javaDep.matches("[0-9]+(\\.[0-9]+)*")) {
  237. if (isOSGiMode) {
  238. if (javaDep.matches("1\\.[0-5]")) {
  239. added.addConfiguredAttribute(new Manifest.Attribute("Bundle-RequiredExecutionEnvironment", "J2SE-" + javaDep));
  240. } else {
  241. added.addConfiguredAttribute(new Manifest.Attribute("Bundle-RequiredExecutionEnvironment", "JavaSE-" + javaDep));
  242. }
  243. } else {
  244. added.addConfiguredAttribute(new Manifest.Attribute("OpenIDE-Module-Java-Dependencies", "Java > " + javaDep));
  245. }
  246. }
  247. String buildNumber = getProject().getProperty("buildnumber");
  248. if (buildNumber == null) {
  249. throw new BuildException("Must have defined 'buildnumber'", getLocation());
  250. }
  251. String attrToAdd = implVers != null ? "OpenIDE-Module-Build-Version" : "OpenIDE-Module-Implementation-Version";
  252. added.addConfiguredAttribute(new Manifest.Attribute(attrToAdd, buildNumber));
  253. // If spec.version.base is defined, use it, after tacking on any numeric impl deps (sorted by CNB of the dep for stability),
  254. // and also using the implementation version of this module as well if it is numeric.
  255. // This trick makes sure that if you have an impl dep on some module which changes its (numeric) impl version,
  256. // your spec version will also change correspondingly, so e.g. Auto Update will see a new version of your module too.
  257. String specVersBase = getProject().getProperty("spec.version.base");
  258. if (specVersBase != null) {
  259. boolean edited = false;
  260. if (implVers != null) {
  261. try {
  262. parseInt(implVers);
  263. specVersBase += "." + implVers;
  264. edited = true;
  265. } catch (NumberFormatException e) {
  266. // OK, ignore it, not numeric.
  267. specVersBaseWarning(manifestFile, "use of spec.version.base with non-integer OpenIDE-Module-Implementation-Version");
  268. }
  269. }
  270. SortedMap<String,Integer> additions = new TreeMap<String,Integer>();
  271. if (moduleDeps != null) {
  272. for (String individualDep : COMMA_SPACE.split(moduleDeps)) {
  273. Matcher m = IMPL_DEP.matcher(individualDep);
  274. if (m.matches()) {
  275. String cnb = m.group(1);
  276. String version = m.group(3);
  277. try {
  278. additions.put(cnb, parseInt(version));
  279. } catch (NumberFormatException e) {
  280. // OK, ignore this one, not numeric.
  281. specVersBaseWarning(manifestFile,
  282. "use of spec.version.base with non-integer OpenIDE-Module-Implementation-Version from " + cnb);
  283. }
  284. }
  285. }
  286. }
  287. for (int version : additions.values()) {
  288. specVersBase += "." + version;
  289. edited = true;
  290. }
  291. String versionTag = isOSGiMode ? "Bundle-Version" : "OpenIDE-Module-Specification-Version";
  292. if (edited) {
  293. log("Computed " + versionTag + ": " + specVersBase);
  294. } else {
  295. specVersBaseWarning(manifestFile,
  296. "using spec.version.base for no reason; could just use " + versionTag + " statically in the manifest");
  297. }
  298. if (staticManifest.getMainSection().getAttributeValue(versionTag) != null) {
  299. specVersBaseWarning(manifestFile,
  300. "attempting to use spec.version.base while some " + versionTag + " is statically defined in manifest.mf; this cannot work");
  301. } else {
  302. added.addConfiguredAttribute(new Manifest.Attribute(versionTag, specVersBase));
  303. }
  304. } else if (moduleDeps != null && moduleDeps.indexOf('=') != -1) {
  305. specVersBaseWarning(manifestFile,
  306. "not using spec.version.base, yet declaring implementation dependencies; may lead to problems with Auto Update");
  307. } else if (implVers != null) {
  308. if (specVersBase == null) {
  309. specVersBaseWarning(manifestFile,
  310. "not using spec.version.base, yet declaring implementation version; may lead to problems with Auto Update");
  311. } else {
  312. try {
  313. parseInt(implVers);
  314. } catch (NumberFormatException e) {
  315. specVersBaseWarning(manifestFile,
  316. "use of non-integer OpenIDE-Module-Implementation-Version may be problematic for clients trying to use spec.version.base");
  317. }
  318. }
  319. }
  320. if (isOSGiMode && added.getMainSection().getAttribute("Bundle-Version") == null && specVer != null) {
  321. added.getMainSection().addConfiguredAttribute(new Manifest.Attribute("Bundle-Version", specVer));
  322. }
  323. boolean old = false; // #110661
  324. String destDir = getProject().getProperty("netbeans.dest.dir");
  325. if (destDir != null) {
  326. for (File cluster : getProject().resolveFile(destDir).listFiles()) {
  327. if (new File(cluster, "modules/org-netbeans-modules-autoupdate.jar").isFile()) {
  328. old = true;
  329. break;
  330. }
  331. }
  332. }
  333. if (!old) {
  334. added.addConfiguredAttribute(new Manifest.Attribute("AutoUpdate-Show-In-Client", Boolean.toString( // #110572
  335. !Project.toBoolean(getProject().getProperty("is.autoload")) && !Project.toBoolean(getProject().getProperty("is.eager")) &&
  336. "modules".equals(getProject().getProperty("module.jar.dir")))));
  337. }
  338. // Now ask the regular <jar> task to add all this stuff to the regular manifest.mf.
  339. added.merge(staticManifest);
  340. if (!"lib".equals (getProject().getProperty("module.jar.dir")) && !isOSGiMode) {
  341. // modules in lib cannot request this token
  342. String key = "OpenIDE-Module-Requires";
  343. String token = "org.openide.modules.ModuleFormat1";
  344. String requires = staticManifest.getMainSection().getAttributeValue(key);
  345. String newRequires;
  346. if (requires != null) {
  347. // #59671: have to modify it, not just use super.setManifest(manifestFile).
  348. added.getMainSection().removeAttribute(key);
  349. newRequires = requires + ", " + token;
  350. } else {
  351. newRequires = token;
  352. }
  353. added.addConfiguredAttribute(new Manifest.Attribute(key, newRequires));
  354. }
  355. addConfiguredManifest(added);
  356. } catch (Exception e) {
  357. throw new BuildException(e, getLocation());
  358. }
  359. }
  360. private int[] parseDecimal(String trim, int max) {
  361. String[] segments = trim.split("\\.");
  362. int[] arr = new int[segments.length > max ? max : segments.length];
  363. for (int i = 0; i < arr.length; i++) {
  364. arr[i] = parseInt(segments[i]);
  365. }
  366. return arr;
  367. }
  368. private static int parseInt(String v) throws NumberFormatException {
  369. if (!v.matches("0|[1-9][0-9]*")) { // 050123 is a date, -12 is illegal, etc.
  370. throw new NumberFormatException(v);
  371. }
  372. return Integer.parseInt(v);
  373. }
  374. private void specVersBaseWarning(File manifestFile, String message) throws BuildException {
  375. message = manifestFile + ": " + message + "\n(see http://wiki.netbeans.org/DevFaqImplementationDependency)" +
  376. "\n(define spec.version.base.fatal.warning=false in project.properties to make this be a nonfatal warning)";
  377. if (Project.toBoolean(getProject().getProperty("spec.version.base.fatal.warning"))) {
  378. throw new BuildException(message);
  379. } else {
  380. log(message, Project.MSG_WARN);
  381. }
  382. }
  383. @Override
  384. public void execute() throws BuildException {
  385. super.execute();
  386. if (stamp != null) {
  387. log("Stamp " + stamp + " against " + zipFile, Project.MSG_DEBUG);
  388. if (stamp.lastModified() < zipFile.lastModified()) {
  389. try {
  390. stamp.getParentFile().mkdirs();
  391. stamp.createNewFile();
  392. stamp.setLastModified(zipFile.lastModified());
  393. } catch (IOException ex) {
  394. throw new BuildException(ex);
  395. }
  396. }
  397. }
  398. }
  399. }