summaryrefslogtreecommitdiffstats
path: root/buildhelpers/src/main/java/com/vaadin
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2016-03-23 11:57:28 +0200
committerTeemu Suo-Anttila <teemusa@vaadin.com>2016-03-24 09:51:59 +0200
commit7b1a91f9ece0d38c74886383df3ee29d354592f8 (patch)
tree071ff5ca5ca7dfb8ee4f50da8788940b046dcf05 /buildhelpers/src/main/java/com/vaadin
parent7abb4b536dc07ed19c7a1942da68fe5bb00ce4fa (diff)
downloadvaadin-framework-7b1a91f9ece0d38c74886383df3ee29d354592f8.tar.gz
vaadin-framework-7b1a91f9ece0d38c74886383df3ee29d354592f8.zip
Build vaadin-buildhelpers with maven
Change-Id: I1b67fdc7d32d57f98bca78dba4fa190950b94507
Diffstat (limited to 'buildhelpers/src/main/java/com/vaadin')
-rw-r--r--buildhelpers/src/main/java/com/vaadin/buildhelpers/CompileTheme.java159
-rw-r--r--buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesAuthors.java101
-rw-r--r--buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java171
-rw-r--r--buildhelpers/src/main/java/com/vaadin/buildhelpers/GeneratePackageExports.java223
-rw-r--r--buildhelpers/src/main/java/com/vaadin/buildhelpers/ManifestWriter.java159
5 files changed, 813 insertions, 0 deletions
diff --git a/buildhelpers/src/main/java/com/vaadin/buildhelpers/CompileTheme.java b/buildhelpers/src/main/java/com/vaadin/buildhelpers/CompileTheme.java
new file mode 100644
index 0000000000..d97025bdb6
--- /dev/null
+++ b/buildhelpers/src/main/java/com/vaadin/buildhelpers/CompileTheme.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.buildhelpers;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+
+import com.vaadin.sass.internal.ScssStylesheet;
+
+/**
+ * Helper to combine css divided into separate per component dirs into one to
+ * optimize http requests.
+ */
+public class CompileTheme {
+
+ /**
+ * @param args
+ * @throws IOException
+ * @throws ParseException
+ */
+ public static void main(String[] args) throws IOException, ParseException {
+ Options options = new Options();
+ options.addOption("t", "theme", true, "the theme to compile");
+ options.addOption("f", "theme-folder", true,
+ "the folder containing the theme");
+ options.addOption("v", "version", true,
+ "the Vaadin version to compile for");
+ CommandLineParser parser = new PosixParser();
+ CommandLine params = parser.parse(options, args);
+ if (!params.hasOption("theme") || !params.hasOption("theme-folder")
+ || !params.hasOption("version")) {
+ // automatically generate the help statement
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp(CompileTheme.class.getName(), options);
+ return;
+ }
+ String themeName = params.getOptionValue("theme");
+ String themeFolder = params.getOptionValue("theme-folder");
+ String version = params.getOptionValue("version");
+
+ // Regular theme
+ try {
+ processSassTheme(themeFolder, themeName, "styles", version);
+ System.out.println("Compiling theme " + themeName
+ + " styles successful");
+ } catch (Exception e) {
+ System.err.println("Compiling theme " + themeName
+ + " styles failed");
+ e.printStackTrace();
+ }
+ // Legacy theme w/o .themename{} wrapping
+ try {
+ String legacyFile = themeFolder + File.separator + themeName
+ + File.separator + "legacy-styles.scss";
+ if (new File(legacyFile).exists()) {
+ processSassTheme(themeFolder, themeName, "legacy-styles",
+ version);
+ System.out.println("Compiling theme " + themeName
+ + " legacy-styles successful");
+ }
+ } catch (Exception e) {
+ System.err.println("Compiling theme " + themeName
+ + " legacy-styles failed");
+ e.printStackTrace();
+ }
+ }
+
+ private static void processSassTheme(String themeFolder, String themeName,
+ String variant, String version) throws Exception {
+
+ StringBuffer cssHeader = new StringBuffer();
+
+ String stylesCssDir = themeFolder + File.separator + themeName
+ + File.separator;
+
+ String stylesCssName = stylesCssDir + variant + ".css";
+
+ // Process as SASS file
+ String sassFile = stylesCssDir + variant + ".scss";
+
+ ScssStylesheet scss = ScssStylesheet.get(sassFile);
+ if (scss == null) {
+ throw new IllegalArgumentException("SASS file: " + sassFile
+ + " not found");
+ }
+ scss.compile();
+ String filteredScss = scss.printState().replace("@version@", version);
+
+ BufferedWriter out = new BufferedWriter(new FileWriter(stylesCssName));
+ out.write(cssHeader.toString());
+ out.write(filteredScss);
+ out.close();
+
+ System.out.println("Compiled CSS to " + stylesCssName + " ("
+ + filteredScss.length() + " bytes)");
+
+ createSprites(themeFolder, themeName);
+ File oldCss = new File(stylesCssName);
+ File newCss = new File(stylesCssDir + variant + "-sprite.css");
+
+ if (newCss.exists()) {
+ // Theme contained sprites. Renamed "styles-sprite.css" ->
+ // "styles.css"
+ oldCss.delete();
+
+ boolean ok = newCss.renameTo(oldCss);
+ if (!ok) {
+ throw new RuntimeException("Rename " + newCss + " -> " + oldCss
+ + " failed");
+ }
+ }
+
+ }
+
+ private static void createSprites(String themeFolder, String themeName)
+ throws FileNotFoundException, IOException {
+ try {
+ // Try loading the class separately from using it to avoid
+ // hiding other classpath issues
+ Class<?> smartSpritesClass = org.carrot2.labs.smartsprites.SmartSprites.class;
+ } catch (NoClassDefFoundError e) {
+ System.err
+ .println("Could not find smartsprites. No sprites were generated. The theme should still work.");
+ return;
+ }
+
+ String[] parameters = new String[] { "--sprite-png-depth", "AUTO",
+ "--css-file-suffix", "-sprite", "--css-file-encoding", "UTF-8",
+ "--root-dir-path", themeFolder + File.separator + themeName,
+ "--log-level", "WARN" };
+
+ org.carrot2.labs.smartsprites.SmartSprites.main(parameters);
+ System.out.println("Generated sprites");
+
+ }
+}
diff --git a/buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesAuthors.java b/buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesAuthors.java
new file mode 100644
index 0000000000..cd85ca6a3f
--- /dev/null
+++ b/buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesAuthors.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.buildhelpers;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+public class FetchReleaseNotesAuthors {
+ private static final String template = "<li class=\"author\">@author@</li>";
+
+ public static void main(String[] args) throws IOException,
+ InterruptedException {
+ Properties authorMap = new Properties();
+
+ String authorsFilename = FetchReleaseNotesAuthors.class.getPackage()
+ .getName().replace(".", "/")
+ + "/authormap.properties";
+ InputStream s = FetchReleaseNotesAuthors.class.getClassLoader()
+ .getResourceAsStream(authorsFilename);
+ if (s == null) {
+ System.err.println("Author mapping file " + authorsFilename
+ + " not found!");
+ }
+ authorMap.load(s);
+
+ String version = System.getProperty("vaadin.version");
+ String previousVersion = getPreviousVersion(version);
+ // System.out.println("Using previous version: " + previousVersion);
+ // List all commits which are in this version but not in
+ // "previousVersion"
+ String cmd = "git log --pretty=%an HEAD ^origin/" + previousVersion;
+ Process p = Runtime.getRuntime().exec(cmd);
+ p.waitFor();
+ if (p.exitValue() != 0) {
+ System.err.println("Exit code: " + p.exitValue());
+ }
+ BufferedReader b = new BufferedReader(new InputStreamReader(
+ p.getInputStream()));
+ String line = "";
+
+ List<String> authors = new ArrayList<String>();
+ while ((line = b.readLine()) != null) {
+ String author = line;
+ if (authorMap.containsKey(author)) {
+ author = authorMap.getProperty(author);
+ }
+ if (author != null && !author.equals("")
+ && !authors.contains(author)) {
+ authors.add(author);
+ }
+ }
+ Collections.sort(authors);
+ for (String author : authors) {
+ System.out.println(template.replace("@author@", author));
+ }
+ }
+
+ private static String getPreviousVersion(String version) {
+ String[] versionNumbers = version.split("\\.");
+ if (versionNumbers.length > 4 || versionNumbers.length < 3) {
+ throw new IllegalArgumentException("Cannot parse version: "
+ + version);
+ }
+ int major = Integer.parseInt(versionNumbers[0]);
+ int minor = Integer.parseInt(versionNumbers[1]);
+ int maintenance = Integer.parseInt(versionNumbers[2]);
+ // String qualifier = versionNumbers[3];
+
+ if (minor == 0) {
+ // Major release, can't know what the previous minor was
+ throw new IllegalArgumentException(
+ "Can't know what previous minor version was");
+ }
+ if (maintenance == 0) {
+ // Minor release, use last minor
+ return major + "." + (minor - 1);
+ } else {
+ // Maintenance, use last maintenance
+ return major + "." + minor + "." + (maintenance - 1);
+ }
+ }
+}
diff --git a/buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java b/buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
new file mode 100644
index 0000000000..0cd06890eb
--- /dev/null
+++ b/buildhelpers/src/main/java/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.buildhelpers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+
+public class FetchReleaseNotesTickets {
+ private static final String queryURL = "https://dev.vaadin.com/query?status=pending-release&amp;status=released&amp;@milestone@&amp;resolution=fixed&amp;col=id&amp;col=summary&amp;col=owner&amp;col=type&amp;col=priority&amp;col=component&amp;col=version&amp;col=bfptime&col=fv&amp;format=tab&amp;order=id";
+ private static final String ticketTemplate = "<tr>"
+ + "@badge@" //
+ + "<td class=\"ticket\"><a href=\"https://dev.vaadin.com/ticket/@ticket@\">#@ticket@</a></td>" //
+ + "<td>@description@</td>" //
+ + "</tr>"; //
+
+ public static void main(String[] args) throws IOException {
+ String versionsProperty = System.getProperty("vaadin.version");
+ if (versionsProperty == null || versionsProperty.equals("")) {
+ usage();
+ }
+ String milestone = "";
+
+ List<String> versions = new ArrayList<String>();
+ for (String version : versionsProperty.split(" ")) {
+ if (version.endsWith(".0") || version.matches(".*\\.rc\\d+")) {
+ // Find all prerelease versions for final or rc
+
+ // Strip potential rc prefix
+ version = version.replaceAll("\\.rc\\d+$", "");
+ versions.addAll(findPrereleaseVersions(version));
+ } else {
+ versions.add(version);
+ }
+ }
+
+ for (String version : versions) {
+ if (!milestone.equals("")) {
+ milestone += "&amp;";
+ }
+ milestone += "milestone=Vaadin+" + version;
+ }
+
+ printMilestone(milestone);
+ }
+
+ private static List<String> findPrereleaseVersions(String baseVersion) {
+ List<String> versions = new ArrayList<String>();
+
+ for (int i = 0; i < 50; i++) {
+ versions.add(baseVersion + ".alpha" + i);
+ }
+ for (int i = 0; i < 10; i++) {
+ versions.add(baseVersion + ".beta" + i);
+ }
+ for (int i = 0; i < 10; i++) {
+ versions.add(baseVersion + ".rc" + i);
+ }
+
+ return versions;
+ }
+
+ private static void printMilestone(String milestone)
+ throws MalformedURLException, IOException {
+
+ URL url = new URL(queryURL.replace("@milestone@", milestone));
+ URLConnection connection = url.openConnection();
+ InputStream urlStream = connection.getInputStream();
+
+ List<String> tickets = IOUtils.readLines(urlStream);
+
+ for (String ticket : tickets) {
+ // Omit BOM
+ if (!ticket.isEmpty() && ticket.charAt(0) == 65279) {
+ ticket = ticket.substring(1);
+ }
+ String[] fields = ticket.split("\t");
+ if ("id".equals(fields[0])) {
+ // This is the header
+ continue;
+ }
+ String summary = fields[1];
+
+ summary = modifySummaryString(summary);
+
+ String badge = "<td></td>";
+ if (fields.length >= 8 && !fields[7].equals("")) {
+ badge = "<td class=\"bfp\"><span class=\"bfp\">Priority</span></td>";
+ } else if (fields.length >= 9 && fields[8].equalsIgnoreCase("true")) {
+ badge = "<td class=\"fv\"><span class=\"fv\">Vote</span></td>";
+ }
+
+ System.out.println(ticketTemplate.replace("@ticket@", fields[0])
+ .replace("@description@", summary)
+ .replace("@badge@", badge));
+ }
+ urlStream.close();
+ }
+
+ private static String modifySummaryString(String summary) {
+
+ if (summary.startsWith("\"") && summary.endsWith("\"")) {
+ // If a summary starts with " and ends with " then all quotes in
+ // the summary are encoded as double quotes
+ summary = summary.substring(1, summary.length() - 1);
+ summary = summary.replace("\"\"", "\"");
+ }
+
+ // this is needed for escaping html
+ summary = escapeHtml(summary);
+
+ return summary;
+ }
+
+ /**
+ * @since 7.4
+ * @param string
+ * the string to be html-escaped
+ * @return string in html-escape format
+ */
+ private static String escapeHtml(String string) {
+
+ StringBuffer buf = new StringBuffer(string.length() * 2);
+
+ // we check the string character by character and escape only special
+ // characters
+ for (int i = 0; i < string.length(); ++i) {
+
+ char ch = string.charAt(i);
+ String charString = ch + "";
+
+ if ((charString).matches("[a-zA-Z0-9., ]")) {
+ // character is letter, digit, dot, comma or whitespace
+ buf.append(ch);
+ } else {
+ int charInt = ch;
+ buf.append("&");
+ buf.append("#");
+ buf.append(charInt);
+ buf.append(";");
+ }
+ }
+ return buf.toString();
+ }
+
+ private static void usage() {
+ System.err.println("Usage: "
+ + FetchReleaseNotesTickets.class.getSimpleName()
+ + " -Dvaadin.version=<version>");
+ System.exit(1);
+ }
+}
diff --git a/buildhelpers/src/main/java/com/vaadin/buildhelpers/GeneratePackageExports.java b/buildhelpers/src/main/java/com/vaadin/buildhelpers/GeneratePackageExports.java
new file mode 100644
index 0000000000..d4ad3f838c
--- /dev/null
+++ b/buildhelpers/src/main/java/com/vaadin/buildhelpers/GeneratePackageExports.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.buildhelpers;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * Generates Export-Packages attribute for OSGi compatible manifest.
+ * <p>
+ * Reads the included Java packages in a jar file, generates a corresponding
+ * Export-Package attribute, and appends it to the jar's MANIFEST.MF.
+ * <p>
+ * See #3521 for details.
+ *
+ * @author magi
+ */
+public class GeneratePackageExports {
+
+ private static final String EXPORT_PACKAGE_ATTRIBUTE = "Export-Package";
+
+ public static void main(String[] args) {
+ if (args.length < 2) {
+ System.err
+ .println("Invalid number of parameters\n"
+ + "Usage: java -cp .. GenerateManifest <package.jar> <accepted package prefixes>\n"
+ + "Use -Dvaadin.version to specify the version to be used for the packages\n"
+ + "Use -DincludeNumberPackages=1 to include package names which start with a number (not 100% OSGi compatible)");
+ System.exit(1);
+ }
+
+ // Open the 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);
+ }
+
+ // Accepted packages
+ List<String> acceptedPackagePrefixes = new ArrayList<String>();
+ for (int i = 1; i < args.length; i++) {
+ acceptedPackagePrefixes.add(args[i]);
+ }
+
+ boolean includeNumberPackages = false;
+ if ("1".equals(System.getProperty("includeNumberPackages"))) {
+ includeNumberPackages = true;
+ }
+
+ // List the included Java packages
+ HashSet<String> packages = getPackages(jar, acceptedPackagePrefixes,
+ includeNumberPackages);
+
+ // Avoid writing empty Export-Package attribute
+ if (packages.isEmpty()) {
+ return;
+ }
+
+ String exportPackage = sortAndJoinPackages(packages);
+
+ // Read old manifest
+ Manifest oldMF = null;
+ try {
+ oldMF = jar.getManifest();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ Attributes mainAttributes = oldMF.getMainAttributes();
+
+ String existingExportPackage = mainAttributes
+ .getValue(EXPORT_PACKAGE_ATTRIBUTE);
+ if (existingExportPackage != null) {
+ exportPackage = existingExportPackage + "," + exportPackage;
+ }
+
+ // Jar must be closed before updating it below, as it's
+ // locked in Windows until closed. (#6045)
+ try {
+ jar.close();
+ } catch (IOException e) {
+ System.err.println("Unable to close JAR '" + jarFilename + "'");
+ }
+
+ // Create the modified manifest
+ ManifestWriter manifest = new ManifestWriter();
+ manifest.writeAttribute(EXPORT_PACKAGE_ATTRIBUTE, exportPackage);
+
+ // Update the manifest in the Jar. The jar must be closed
+ // before this is done.
+ int status = manifest.updateJar(jarFilename);
+
+ if (status != 0) {
+ System.exit(status);
+ }
+ }
+
+ private static String sortAndJoinPackages(HashSet<String> packages) {
+ // Produce an ordered listing of the package names
+ String packageArray[] = new String[packages.size()];
+ packages.toArray(packageArray);
+ Arrays.sort(packageArray);
+ StringBuilder joinedPackages = new StringBuilder();
+ for (int i = 0; i < packageArray.length; i++) {
+ if (i != 0) {
+ joinedPackages.append(",");
+ }
+ String version = getVersion(packageArray[i]);
+ String packageAndVersion = packageArray[i];
+ if (version != null) {
+ packageAndVersion += ";version=\"" + version + "\"";
+ } else {
+ Logger.getLogger(GeneratePackageExports.class.getName())
+ .severe("No version defined for " + packageArray[i]);
+ }
+ joinedPackages.append(packageAndVersion);
+ }
+
+ return joinedPackages.toString();
+ }
+
+ /**
+ * Tries to find version specified using system properties of type
+ * version.<java package>. Searches for the packge and then its parents
+ * recursively. Falls back to the "vaadin.version" system property if no
+ * other properties are found.
+ *
+ * @param javaPackage
+ * The package to determine a version for
+ * @return A version or null if no version has been defined
+ */
+ private static String getVersion(String javaPackage) {
+ String packageVersion = System.getProperty("version." + javaPackage);
+ if (packageVersion != null) {
+ return packageVersion;
+ }
+ String parentPackage = null;
+ if (javaPackage.contains(".")) {
+ parentPackage = javaPackage.substring(0,
+ javaPackage.lastIndexOf('.'));
+ String parentVersion = getVersion(parentPackage);
+ if (parentVersion != null) {
+ return parentVersion;
+ }
+ }
+
+ String vaadinVersion = System.getProperty("vaadin.version");
+ if (vaadinVersion != null) {
+ return vaadinVersion;
+ }
+
+ return null;
+ }
+
+ private static HashSet<String> getPackages(JarFile jar,
+ List<String> acceptedPackagePrefixes, boolean includeNumberPackages) {
+ HashSet<String> packages = new HashSet<String>();
+
+ Pattern startsWithNumber = Pattern.compile("\\.\\d");
+
+ for (Enumeration<JarEntry> it = jar.entries(); it.hasMoreElements();) {
+ JarEntry entry = it.nextElement();
+
+ boolean classFile = entry.getName().endsWith(".class");
+ boolean directory = entry.isDirectory();
+
+ if (!classFile && !directory) {
+ continue;
+ }
+
+ if (!acceptEntry(entry.getName(), acceptedPackagePrefixes)) {
+ continue;
+ }
+
+ int lastSlash = entry.getName().lastIndexOf('/');
+ String pkg = entry.getName().substring(0, lastSlash)
+ .replace('/', '.');
+
+ if (!includeNumberPackages && startsWithNumber.matcher(pkg).find()) {
+ continue;
+ }
+
+ packages.add(pkg);
+ }
+
+ return packages;
+ }
+
+ private static boolean acceptEntry(String name,
+ List<String> acceptedPackagePrefixes) {
+ for (String prefix : acceptedPackagePrefixes) {
+ if (name.startsWith(prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/buildhelpers/src/main/java/com/vaadin/buildhelpers/ManifestWriter.java b/buildhelpers/src/main/java/com/vaadin/buildhelpers/ManifestWriter.java
new file mode 100644
index 0000000000..9e9b29c4a1
--- /dev/null
+++ b/buildhelpers/src/main/java/com/vaadin/buildhelpers/ManifestWriter.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+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;
+ }
+
+ @Override
+ public String toString() {
+ return buffer.toString();
+ }
+
+ public byte[] getBytes() {
+ return buffer.toString().getBytes();
+ }
+}