summaryrefslogtreecommitdiffstats
path: root/build
diff options
context:
space:
mode:
authorMarko Grönroos <magi@iki.fi>2010-10-22 13:53:28 +0000
committerMarko Grönroos <magi@iki.fi>2010-10-22 13:53:28 +0000
commited9132f848d68a8edf51e649856c805bd179c567 (patch)
tree9bee05fe9a67bb6142e5939616df62923d8fd2ad /build
parent30a5dee6b6327a2f9f9b95e5748f27a7db657235 (diff)
downloadvaadin-framework-ed9132f848d68a8edf51e649856c805bd179c567.tar.gz
vaadin-framework-ed9132f848d68a8edf51e649856c805bd179c567.zip
Generate OSGi manifest Package-Exports attribute automatically. For #3521.
svn changeset:15674/svn branch:6.5
Diffstat (limited to 'build')
-rw-r--r--build/build.xml19
-rw-r--r--build/buildhelpers/com/vaadin/buildhelpers/GeneratePackageExports.java131
-rw-r--r--build/buildhelpers/com/vaadin/buildhelpers/ManifestWriter.java130
-rw-r--r--build/package/META-INF/MANIFEST.MF1
4 files changed, 276 insertions, 5 deletions
diff --git a/build/build.xml b/build/build.xml
index efc82ae316..5a12ec80c5 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -587,10 +587,12 @@
</javac>
</target>
- <target name="defaulttheme" depends="init">
- <echo>Combining default themes css files</echo>
- <!-- ensure buildhelpers are compiled -->
+ <target name="compile-helpers" depends="init">
<javac source="1.5" target="1.5" srcdir="build/buildhelpers" classpath="build/smartsprites/lib/smartsprites-0.2.3-itmill.jar"/>
+ </target>
+
+ <target name="defaulttheme" depends="init, compile-helpers">
+ <echo>Combining default themes css files</echo>
<java classname="com.vaadin.buildhelpers.CompileDefaultTheme" failonerror="yes" fork="yes">
<arg value="-version" />
<arg value="${version.full}"/>
@@ -773,7 +775,7 @@
<!-- specifically on it, because dependence does not see compiled -->
<!-- individual widgetsets, because antcall does not fulfill -->
<!-- dependencies. -->
- <target name="vaadin.jar" depends="compile-server-side, compile-client-side">
+ <target name="vaadin.jar" depends="compile-server-side, compile-client-side, compile-helpers">
<echo>Creating JAR (server-side) ${lib-jar-name}</echo>
<!-- Create Vaadin JAR -->
<mkdir dir="${output-dir}/META-INF"/>
@@ -813,6 +815,15 @@
</patternset>
</fileset>
</jar>
+
+ <!-- Generate the Package-Exports attribute in the JAR -->
+ <java classname="com.vaadin.buildhelpers.GeneratePackageExports" failonerror="true" fork="yes">
+ <arg value="${output-dir}/WebContent/WEB-INF/lib/${lib-jar-name}"/>
+ <classpath>
+ <pathelement location="build/buildhelpers" />
+ </classpath>
+ </java>
+
<copy file="${output-dir}/WebContent/WEB-INF/lib/${lib-jar-name}" tofile="${output-dir}/WebContent/${lib-jar-name}" />
</target>
diff --git a/build/buildhelpers/com/vaadin/buildhelpers/GeneratePackageExports.java b/build/buildhelpers/com/vaadin/buildhelpers/GeneratePackageExports.java
new file mode 100644
index 0000000000..742450f3d5
--- /dev/null
+++ b/build/buildhelpers/com/vaadin/buildhelpers/GeneratePackageExports.java
@@ -0,0 +1,131 @@
+package com.vaadin.buildhelpers;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.jar.Attributes.Name;
+
+/**
+ * Generates Export-Packages attribute for OSGi compatible manifest.
+ *
+ * Reads the included Java packages in Vaadin JAR, generates a corresponding
+ * MANIFEST.MF file, and replaces the dummy one in the JAR with the
+ * generated one.
+ *
+ * See #3521 for details.
+ *
+ * @author magi
+ */
+public class GeneratePackageExports {
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println("Invalid number of parameters\n"+
+ "Usage: java -cp .. GenerateManifest <package.jar>");
+ System.exit(1);
+ }
+
+ // Open tje JAR
+ String jarFilename = args[0];
+ JarFile jar = null;
+ try {
+ jar = new JarFile(jarFilename);
+ } catch (IOException e) {
+ System.err.println("Unable to open JAR '"+jarFilename+"'");
+ System.exit(1);
+ }
+
+ // List the included Java packages
+ HashSet<String> packages = new HashSet<String>();
+ for (Enumeration<JarEntry> it = jar.entries(); it.hasMoreElements();) {
+ JarEntry entry = it.nextElement();
+ if (entry.getName().startsWith("com") && entry.getName().endsWith(".class")) {
+ int lastSlash = entry.getName().lastIndexOf('/');
+ String pkg = entry.getName().substring(0, lastSlash).replace('/', '.');
+ packages.add(pkg);
+ }
+ }
+
+ // List theme packages
+ for (Enumeration<JarEntry> it = jar.entries(); it.hasMoreElements();) {
+ JarEntry entry = it.nextElement();
+ if (entry.isDirectory() && entry.getName().startsWith("VAADIN/themes")) {
+ // Strip ending slash
+ int lastSlash = entry.getName().lastIndexOf('/');
+ String pkg = entry.getName().substring(0, lastSlash).replace('/', '.');
+ packages.add(pkg);
+ }
+ }
+
+ // Replacement for the "Export-Package" attribute in the manifest
+ String exportPackage = "";
+
+ // Produce an ordered listing of the package names
+ String packageArray[] = new String[packages.size()];
+ packages.toArray(packageArray);
+ Arrays.sort(packageArray);
+ for (int i=0; i<packageArray.length; i++) {
+ if (i == 0)
+ exportPackage = packageArray[i];
+ else
+ exportPackage += ", " + packageArray[i];
+ }
+
+ // Read old manifest
+ Manifest oldMF = null;
+ try {
+ oldMF = jar.getManifest();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ // Read main attributes
+ Attributes mainAtts = oldMF.getMainAttributes();
+ Vector<String> keys = new Vector<String>(mainAtts.size());
+ for (Iterator<Object> attrit = mainAtts.keySet().iterator(); attrit.hasNext();) {
+ Name name = (Name) attrit.next();
+ keys.add(name.toString());
+ }
+
+ // Put the manifest version as the first line
+ String orderedKeys[] = new String[keys.size()];
+ keys.toArray(orderedKeys);
+ Arrays.sort(orderedKeys); // Must sort to be able to search
+ int mvPos = Arrays.binarySearch(orderedKeys, "Manifest-Version");
+ orderedKeys[mvPos] = orderedKeys[0]; // Swap
+ orderedKeys[0] = "Manifest-Version";
+
+ // This final ordering is just for esthetic reasons and
+ // in practice unnecessary and will actually be messed up
+ // when the 'jar' command reads the manifest
+ Arrays.sort(orderedKeys, 1, orderedKeys.length-1);
+
+ // Create the modified manifest
+ ManifestWriter manifest = new ManifestWriter();
+ for (int i=0; i<orderedKeys.length; i++) {
+ // Skip an existing Export-Package attribute
+ if (orderedKeys[i].equals("Export-Package")) {
+ // Copy the attribute to the modified manifest
+ manifest.writeAttribute(orderedKeys[i], mainAtts.getValue(orderedKeys[i]));
+ }
+ }
+
+ // Add the Export-Package attribute at the end of the manifest.
+ // The alternative would be replacing an existing attribute in
+ // the loop above, but it's not guaranteed that it exists.
+ manifest.writeAttribute("Export-Package", exportPackage);
+
+ // Update the manifest in the Jar
+ int status = manifest.updateJar(jarFilename);
+
+ if (status != 0)
+ System.exit(status);
+ }
+
+}
diff --git a/build/buildhelpers/com/vaadin/buildhelpers/ManifestWriter.java b/build/buildhelpers/com/vaadin/buildhelpers/ManifestWriter.java
new file mode 100644
index 0000000000..a6130e2a46
--- /dev/null
+++ b/build/buildhelpers/com/vaadin/buildhelpers/ManifestWriter.java
@@ -0,0 +1,130 @@
+/**
+ *
+ */
+package com.vaadin.buildhelpers;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Date;
+import java.util.jar.Manifest;
+
+public class ManifestWriter {
+ StringBuffer buffer = new StringBuffer();
+
+ public ManifestWriter() {
+ }
+
+ /**
+ * Writes a manifest attribute to a temporary buffer.
+ *
+ * @param name Attribute name
+ * @param value Attribute value
+ */
+ public void writeAttribute(String name, String value) {
+ int linelen = name.length() + 2;
+ buffer.append(name);
+ buffer.append(": ");
+
+ String remainingValue = value;
+ while (linelen + remainingValue.length() > 72) {
+ int fitsLine = 72 - linelen;
+ buffer.append(remainingValue.substring(0, fitsLine) + "\n ");
+ remainingValue = remainingValue.substring(fitsLine);
+ linelen = 1;
+ }
+ buffer.append(remainingValue + "\n");
+ }
+
+ /**
+ * Writes the manifest to given JAR file.
+ *
+ * The manifest must be created with {@code #writeAttribute(String, String)}
+ * before calling this write.
+ *
+ * @param jarFilename File name of the JAR in which the manifest is written
+ * @return 0 on success, nonzero value on error
+ */
+ int updateJar(String jarFilename) {
+ int status = 0;
+
+ // Determine a temporary file name
+ String newMfPrefix = "vaadin-manifest-" + (new Date()).getTime();
+ File newMfFile = null;
+ try {
+ newMfFile = File.createTempFile(newMfPrefix, ".mf");
+ } catch (IOException e) {
+ System.err.println("Creating temp file failed");
+ status = 1;
+ }
+
+ // Write the manifest to the temporary file
+ if (status == 0) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(newMfFile);
+ fos.write(getBytes());
+ fos.close();
+ } catch (IOException e) {
+ System.err.println("Writing to file '"+newMfFile.getAbsolutePath() +"' failed because: " + e.getMessage());
+ status = 1;
+ }
+ }
+
+ // Check that the manifest is OK
+ if (status == 0) {
+ Manifest checkMf = new Manifest();
+ FileInputStream is;
+ try {
+ is = new FileInputStream(newMfFile);
+ checkMf.read(is);
+ } catch (IOException e) {
+ System.err.println("Reading from file '"+newMfFile.getAbsolutePath() +"' failed because: " + e.getMessage());
+ status = 1;
+ }
+ }
+
+ // Update the manifest in the Jar
+ if (status == 0) {
+ System.out.println("Updating manifest in JAR " + jarFilename);
+ try {
+ // The "mf" order must correspond with manifest-jarfile order
+ Process process = Runtime.getRuntime().exec(new String[]{"jar", "umf", newMfFile.getAbsolutePath(), jarFilename});
+ int exitValue = process.waitFor();
+ if (exitValue != 0) {
+ InputStream jarErr = process.getErrorStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(jarErr));
+ while (reader.ready()) {
+ System.err.println("jar: " + reader.readLine());
+ }
+ System.err.println("The 'jar' command returned with exit value " + exitValue);
+ status = 1;
+ }
+ } catch (IOException e) {
+ System.err.println("Failed to execute 'jar' command. " + e.getMessage());
+ status = 1;
+ } catch (InterruptedException e) {
+ System.err.println("Execution of 'jar' command was interrupted. " + e.getMessage());
+ status = 1;
+ }
+ }
+
+ // Remove the temporary file
+ if (newMfFile != null)
+ newMfFile.delete();
+
+ return status;
+ }
+
+ public String toString() {
+ return buffer.toString();
+ }
+
+ public byte[] getBytes() {
+ return buffer.toString().getBytes();
+ }
+} \ No newline at end of file
diff --git a/build/package/META-INF/MANIFEST.MF b/build/package/META-INF/MANIFEST.MF
index b1bbf0b6ad..c787fcba06 100644
--- a/build/package/META-INF/MANIFEST.MF
+++ b/build/package/META-INF/MANIFEST.MF
@@ -2,6 +2,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: Vaadin
Bundle-SymbolicName: com.vaadin
Bundle-Vendor: IT Mill Ltd
-Export-Package: VAADIN.themes, VAADIN.themes.base, VAADIN.themes.base.absolutelayout, VAADIN.themes.base.accordion, VAADIN.themes.base.button, VAADIN.themes.base.caption, VAADIN.themes.base.common, VAADIN.themes.base.common.img, VAADIN.themes.base.csslayout, VAADIN.themes.base.customcomponent, VAADIN.themes.base.customlayout, VAADIN.themes.base.datefield, VAADIN.themes.base.formlayout, VAADIN.themes.base.gridlayout, VAADIN.themes.base.link, VAADIN.themes.base.menubar, VAADIN.themes.base.notification, VAADIN.themes.base.orderedlayout, VAADIN.themes.base.panel, VAADIN.themes.base.popupview, VAADIN.themes.base.progressindicator, VAADIN.themes.base.select, VAADIN.themes.base.shadow, VAADIN.themes.base.shadow.img, VAADIN.themes.base.slider, VAADIN.themes.base.splitpanel, VAADIN.themes.base.table, VAADIN.themes.base.tabsheet, VAADIN.themes.base.textfield, VAADIN.themes.base.tree, VAADIN.themes.base.upload, VAADIN.themes.base.window, VAADIN.themes.base.window.img.shadow, VAADIN.themes.reindeer, VAADIN.themes.reindeer.accordion, VAADIN.themes.reindeer.button, VAADIN.themes.reindeer.button.img, VAADIN.themes.reindeer.button.img.black, VAADIN.themes.reindeer.common, VAADIN.themes.reindeer.common.icons, VAADIN.themes.reindeer.common.img, VAADIN.themes.reindeer.datefield, VAADIN.themes.reindeer.datefield.img, VAADIN.themes.reindeer.formlayout, VAADIN.themes.reindeer.label, VAADIN.themes.reindeer.layouts,VAADIN.themes.reindeer.layouts.img,VAADIN.themes.reindeer.menubar,VAADIN.themes.reindeer.menubar.img,VAADIN.themes.reindeer.notification,VAADIN.themes.reindeer.notification.img,VAADIN.themes.reindeer.panel,VAADIN.themes.reindeer.progressindicator,VAADIN.themes.reindeer.progressindicator.img,VAADIN.themes.reindeer.select,VAADIN.themes.reindeer.select.img,VAADIN.themes.reindeer.select.img.black,VAADIN.themes.reindeer.slider,VAADIN.themes.reindeer.slider.img,VAADIN.themes.reindeer.splitpanel,VAADIN.themes.reindeer.splitpanel.img,VAADIN.themes.reindeer.table,VAADIN.themes.reindeer.table.img,VAADIN.themes.reindeer.tabsheet,VAADIN.themes.reindeer.tabsheet.img,VAADIN.themes.reindeer.tabsheet.img.bar,VAADIN.themes.reindeer.tabsheet.img.framed,VAADIN.themes.reindeer.textfield,VAADIN.themes.reindeer.textfield.img,VAADIN.themes.reindeer.tree,VAADIN.themes.reindeer.tree.img,VAADIN.themes.reindeer.window,VAADIN.themes.reindeer.window.img,VAADIN.themes.reindeer.window.img.black,VAADIN.themes.runo,VAADIN.themes.runo.absolutelayout,VAADIN.themes.runo.accordion,VAADIN.themes.runo.accordion.img,VAADIN.themes.runo.button,VAADIN.themes.runo.button.img,VAADIN.themes.runo.caption,VAADIN.themes.runo.common,VAADIN.themes.runo.common.img,VAADIN.themes.runo.datefield,VAADIN.themes.runo.datefield.img,VAADIN.themes.runo.formlayout,VAADIN.themes.runo.gridlayout,VAADIN.themes.runo.icons,VAADIN.themes.runo.link,VAADIN.themes.runo.menubar,VAADIN.themes.runo.notification,VAADIN.themes.runo.notification.img,VAADIN.themes.runo.orderedlayout,VAADIN.themes.runo.panel,VAADIN.themes.runo.panel.img,VAADIN.themes.runo.popupview,VAADIN.themes.runo.progressindicator,VAADIN.themes.runo.progressindicator.img,VAADIN.themes.runo.select,VAADIN.themes.runo.select.img,VAADIN.themes.runo.shadow,VAADIN.themes.runo.shadow.img,VAADIN.themes.runo.slider,VAADIN.themes.runo.slider.img,VAADIN.themes.runo.splitpanel,VAADIN.themes.runo.splitpanel.img,VAADIN.themes.runo.table,VAADIN.themes.runo.table.img,VAADIN.themes.runo.tabsheet,VAADIN.themes.runo.tabsheet.img,VAADIN.themes.runo.textfield,VAADIN.themes.runo.textfield.img,VAADIN.themes.runo.tree,VAADIN.themes.runo.tree.img,VAADIN.themes.runo.window,VAADIN.themes.runo.window.img,VAADIN.themes.runo.window.img.shadow,VAADIN.widgetsets,VAADIN.widgetsets.com.vaadin.terminal.gwt.DefaultWidgetSet,com.vaadin,com.vaadin.annotations,com.vaadin.data,com.vaadin.data.util,com.vaadin.data.validator,com.vaadin.event,com.vaadin.event.dd,com.vaadin.event.dd.acceptcriteria,com.vaadin.external.org.apache.commons.fileupload,com.vaadin.external.org.apache.commons.fileupload.disk,com.vaadin.external.org.apache.commons.fileupload.portlet,com.vaadin.external.org.apache.commons.fileupload.servlet,com.vaadin.external.org.apache.commons.fileupload.util,com.vaadin.portal.gwt,com.vaadin.portal.gwt.client,com.vaadin.service,com.vaadin.terminal,com.vaadin.terminal.gwt,com.vaadin.terminal.gwt.client,com.vaadin.terminal.gwt.client.ui,com.vaadin.terminal.gwt.client.ui.dd,com.vaadin.terminal.gwt.client.ui.layout,com.vaadin.terminal.gwt.client.ui.richtextarea,com.vaadin.terminal.gwt.server,com.vaadin.tools,com.vaadin.ui,com.vaadin.ui.themes,com.vaadin.util
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: javax.servlet; version="2.3.0",javax.servlet.http; version="2.3.0"