diff -r 73039bf235f9 -r c14eff0412a5 apisupport.harness/nbproject/project.properties
--- a/apisupport.harness/nbproject/project.properties Mon Nov 23 00:52:40 2009 +0100
+++ b/apisupport.harness/nbproject/project.properties Mon Nov 23 06:41:44 2009 +0100
@@ -68,6 +68,7 @@
org/netbeans/nbbuild/Arch-fake-xhtml.dtd,\
org/netbeans/nbbuild/Arch.xsl,\
org/netbeans/nbbuild/Arch-api-questions.xml,\
+ org/netbeans/nbbuild/AutoUpdate*,\
org/netbeans/nbbuild/Branding*.class,\
org/netbeans/nbbuild/CreateModuleXML*.class,\
org/netbeans/nbbuild/CustomJavac*.class,\
diff -r 73039bf235f9 -r c14eff0412a5 apisupport.harness/release/suite.xml
--- a/apisupport.harness/release/suite.xml Mon Nov 23 00:52:40 2009 +0100
+++ b/apisupport.harness/release/suite.xml Mon Nov 23 06:41:44 2009 +0100
@@ -519,6 +519,14 @@
+
+
+
+
+
+
+
+
diff -r 73039bf235f9 -r c14eff0412a5 apisupport.harness/taskdefs.properties
--- a/apisupport.harness/taskdefs.properties Mon Nov 23 00:52:40 2009 +0100
+++ b/apisupport.harness/taskdefs.properties Mon Nov 23 06:41:44 2009 +0100
@@ -55,3 +55,4 @@
shorterpaths=org.netbeans.nbbuild.ShorterPaths
custom-javac=org.netbeans.nbbuild.CustomJavac
convertclusterpath=org.netbeans.nbbuild.ConvertClusterPath
+autoupdate=org.netbeans.nbbuild.AutoUpdate
diff -r 73039bf235f9 -r c14eff0412a5 nbbuild/antsrc/org/netbeans/nbbuild/AutoUpdate.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/AutoUpdate.java Mon Nov 23 06:41:44 2009 +0100
@@ -0,0 +1,267 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2009 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.nbbuild;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Get;
+import org.netbeans.nbbuild.AutoUpdateCatalogParser.ModuleItem;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class AutoUpdate extends Task {
+ private List modules = new ArrayList();
+ private File dir;
+ private URL catalog;
+
+ public void setUpdateCenter(URL u) {
+ catalog = u;
+ }
+
+ public void setNetBeansDestDir(File dir) {
+ this.dir = dir;
+ }
+
+ public Modules createModules() {
+ final Modules m = new Modules();
+ modules.add(m);
+ return m;
+ }
+
+ @Override
+ public void execute() throws BuildException {
+ File[] arr = dir == null ? null : dir.listFiles();
+ if (arr == null) {
+ throw new BuildException("netbeans.dest.dir must be existing directory: " + dir);
+ }
+
+ Map> installed = findExistingModules(dir);
+
+ // no userdir
+ Map units = AutoUpdateCatalogParser.getUpdateItems(catalog, catalog, this);
+ for (ModuleItem uu : units.values()) {
+ if (!matches(uu.getCodeName())) {
+ continue;
+ }
+ log("found module: " + uu, Project.MSG_VERBOSE);
+ List info = installed.get(uu.getCodeName());
+ if (info != null && !uu.isNewerThan(info.get(0))) {
+ log("Version " + info.get(0) + " of " + uu.getCodeName() + " is up to date", Project.MSG_VERBOSE);
+ continue;
+ }
+ if (info == null) {
+ log(uu.getCodeName() + " is not present, downloading version " + uu.getSpecVersion(), Project.MSG_INFO);
+ } else {
+ log("Version " + info.get(0) + " of " + uu.getCodeName() + " needs update to " + uu.getSpecVersion(), Project.MSG_INFO);
+ }
+
+ byte[] bytes = new byte[4096];
+ File tmp = null;
+ try {
+ final String dash = uu.getCodeName().replace('.', '-');
+ tmp = File.createTempFile(dash, ".nbm");
+ tmp.deleteOnExit();
+ Get get = new Get();
+ get.setProject(getProject());
+ get.setTaskName("get:" + uu.getCodeName());
+ get.setSrc(uu.getURL());
+ get.setDest(tmp);
+ get.setVerbose(true);
+ get.execute();
+
+ File cluster = new File(dir, uu.targetcluster);
+
+ if (info != null) {
+ for (int i = 1; i < info.size(); i++) {
+ File oldFile = new File(cluster, info.get(i).replace('/', File.separatorChar));
+ oldFile.delete();
+ }
+ }
+
+ File tracking = new File(new File(cluster, "update_tracking"), dash + ".xml");
+ tracking.getParentFile().mkdirs();
+ OutputStream config = new BufferedOutputStream(new FileOutputStream(tracking));
+ config.write(("\n" +
+ "\n").getBytes("UTF-8"));
+ config.write((" \n").getBytes("UTF-8"));
+
+ ZipFile zf = new ZipFile(tmp);
+ Enumeration extends ZipEntry> en = zf.entries();
+ while (en.hasMoreElements()) {
+ ZipEntry zipEntry = en.nextElement();
+ if (!zipEntry.getName().startsWith("netbeans/")) {
+ continue;
+ }
+ if (zipEntry.getName().endsWith("/")) {
+ continue;
+ }
+ final String relName = zipEntry.getName().substring(9);
+ File trgt = new File(cluster, relName.replace('/', File.separatorChar));
+ trgt.getParentFile().mkdirs();
+ log("Writing " + trgt, Project.MSG_VERBOSE);
+
+ InputStream is = zf.getInputStream(zipEntry);
+ OutputStream os = new FileOutputStream(trgt);
+ CRC32 crc = new CRC32();
+ for (;;) {
+ int len = is.read(bytes);
+ if (len == -1) {
+ break;
+ }
+ crc.update(bytes, 0, len);
+ os.write(bytes, 0, len);
+ }
+ is.close();
+ os.close();
+ config.write(("\n").getBytes("UTF-8"));
+ }
+ config.write(" \n\n".getBytes("UTF-8"));
+ config.close();
+ } catch (IOException ex) {
+ throw new BuildException(ex);
+ } finally {
+ if (tmp != null) {
+ tmp.delete();
+ }
+ }
+ }
+ }
+
+ private boolean matches(String cnb) {
+ String dash = cnb.replace('.', '-');
+ for (Modules ps : modules) {
+ if (ps.pattern.matcher(dash).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Map> findExistingModules(File dir) {
+ Map> all = new HashMap>();
+ for (File cluster : dir.listFiles()) {
+ File mc = new File(cluster, "update_tracking");
+ final File[] arr = mc.listFiles();
+ if (arr == null) {
+ continue;
+ }
+ for (File m : arr) {
+ try {
+ parseVersion(m, all);
+ } catch (Exception ex) {
+ log("Cannot parse " + m, ex, Project.MSG_WARN);
+ }
+ }
+ }
+ return all;
+ }
+
+ private void parseVersion(final File config, final Map> toAdd) throws Exception {
+ class P extends DefaultHandler {
+ String name;
+ List arr;
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if ("module".equals(qName)) {
+ name = attributes.getValue("codename");
+ return;
+ }
+ if ("module_version".equals(qName)) {
+ String version = attributes.getValue("specification_version");
+ if (name == null || version == null) {
+ throw new BuildException("Cannot find version in " + config);
+ }
+ arr = new ArrayList();
+ arr.add(version);
+ toAdd.put(name, arr);
+ return;
+ }
+ if ("file".equals(qName)) {
+ arr.add(attributes.getValue("name"));
+ }
+ }
+
+ @Override
+ public InputSource resolveEntity(String string, String string1) throws IOException, SAXException {
+ return new InputSource(new ByteArrayInputStream(new byte[0]));
+ }
+ }
+ P p = new P();
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ parser.parse(config, p);
+ }
+
+ public static final class Modules {
+ Pattern pattern;
+
+ public void setIncludes(String regExp) {
+ pattern = Pattern.compile(regExp);
+ }
+ }
+}
diff -r 73039bf235f9 -r c14eff0412a5 nbbuild/antsrc/org/netbeans/nbbuild/AutoUpdateCatalogParser.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/AutoUpdateCatalogParser.java Mon Nov 23 06:41:44 2009 +0100
@@ -0,0 +1,625 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+
+package org.netbeans.nbbuild;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.jar.Manifest;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ *
+ * @author Jiri Rechtacek
+ */
+class AutoUpdateCatalogParser extends DefaultHandler {
+ private final Map items;
+ private final URL provider;
+ private final EntityResolver entityResolver;
+ private final URI baseUri;
+
+ private AutoUpdateCatalogParser (Map items, URL provider, URI base) {
+ this.items = items;
+ this.provider = provider;
+ this.entityResolver = newEntityResolver();
+ this.baseUri = base;
+ }
+
+ private EntityResolver newEntityResolver () {
+ return new EntityResolver() {
+ public InputSource resolveEntity(String string, String string1) throws SAXException, IOException {
+ return new InputSource(new ByteArrayInputStream(new byte[0]));
+ }
+ };
+ }
+
+
+ private static final Logger ERR = Logger.getLogger (AutoUpdateCatalogParser.class.getName ());
+
+ private static enum ELEMENTS {
+ module_updates, module_group, notification, module, description,
+ module_notification, external_package, manifest, l10n, license
+ }
+
+ private static final String MODULE_UPDATES_ATTR_TIMESTAMP = "timestamp"; // NOI18N
+
+ private static final String MODULE_GROUP_ATTR_NAME = "name"; // NOI18N
+
+ private static final String NOTIFICATION_ATTR_URL = "url"; // NOI18N
+
+ private static final String LICENSE_ATTR_NAME = "name"; // NOI18N
+
+ private static final String MODULE_ATTR_CODE_NAME_BASE = "codenamebase"; // NOI18N
+ private static final String MODULE_ATTR_HOMEPAGE = "homepage"; // NOI18N
+ private static final String MODULE_ATTR_DISTRIBUTION = "distribution"; // NOI18N
+ private static final String MODULE_ATTR_DOWNLOAD_SIZE = "downloadsize"; // NOI18N
+ private static final String MODULE_ATTR_NEEDS_RESTART = "needsrestart"; // NOI18N
+ private static final String MODULE_ATTR_MODULE_AUTHOR = "moduleauthor"; // NOI18N
+ private static final String MODULE_ATTR_RELEASE_DATE = "releasedate"; // NOI18N
+ private static final String MODULE_ATTR_IS_GLOBAL = "global"; // NOI18N
+ private static final String MODULE_ATTR_TARGET_CLUSTER = "targetcluster"; // NOI18N
+ private static final String MODULE_ATTR_EAGER = "eager"; // NOI18N
+ private static final String MODULE_ATTR_AUTOLOAD = "autoload"; // NOI18N
+ private static final String MODULE_ATTR_LICENSE = "license"; // NOI18N
+ private static final String LICENSE_ATTR_URL = "url"; // NOI18N
+
+ private static final String MANIFEST_ATTR_SPECIFICATION_VERSION = "OpenIDE-Module-Specification-Version"; // NOI18N
+
+ private static final String TIME_STAMP_FORMAT = "ss/mm/hh/dd/MM/yyyy"; // NOI18N
+
+ private static final String L10N_ATTR_LOCALE = "langcode"; // NOI18N
+ private static final String L10N_ATTR_BRANDING = "brandingcode"; // NOI18N
+ private static final String L10N_ATTR_MODULE_SPECIFICATION = "module_spec_version"; // NOI18N
+ private static final String L10N_ATTR_MODULE_MAJOR_VERSION = "module_major_version"; // NOI18N
+ private static final String L10N_ATTR_LOCALIZED_MODULE_NAME = "OpenIDE-Module-Name"; // NOI18N
+ private static final String L10N_ATTR_LOCALIZED_MODULE_DESCRIPTION = "OpenIDE-Module-Long-Description"; // NOI18N
+
+ private static String GZIP_EXTENSION = ".gz"; // NOI18N
+
+ private static Map cache;
+ private static URI cacheURI;
+ synchronized static Map getUpdateItems (URL url, URL provider, Task task) {
+
+ Map items = new HashMap ();
+ URI base;
+ try {
+ if (provider != null) {
+ base = provider.toURI();
+ } else {
+ base = url.toURI();
+ }
+ if (cache != null && cacheURI.equals(base)) {
+ task.log("Using existing module item cache " + base, Project.MSG_INFO);
+ return cache;
+ }
+ task.log("Downloading " + base, Project.MSG_INFO);
+ InputSource is = null;
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(false);
+ SAXParser saxParser = factory.newSAXParser();
+ is = getInputSource(url, provider, base);
+ saxParser.parse(is, new AutoUpdateCatalogParser(items, provider, base));
+ cacheURI = base;
+ cache = items;
+ } catch (Exception ex) {
+ ERR.log(Level.INFO, "Failed to parse " + base, ex);
+ } finally {
+ if (is != null && is.getByteStream() != null) {
+ try {
+ is.getByteStream().close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ } catch (URISyntaxException ex) {
+ ERR.log(Level.INFO, null, ex);
+ }
+ return items;
+ }
+
+ private static boolean isGzip (URL url) {
+ boolean res = false;
+ if (url != null) {
+ res = url.getPath ().toLowerCase ().endsWith (GZIP_EXTENSION);
+ ERR.log (Level.FINER, "Is GZIP " + url + " ? " + res);
+ } else {
+ ERR.log (Level.WARNING, "AutoupdateCatalogProvider has not URL.");
+ }
+ return res;
+ }
+
+ private static InputSource getInputSource(URL toParse, URL p, URI base) {
+ InputStream is = null;
+ try {
+ is = toParse.openStream ();
+ if (isGzip (p)) {
+ try {
+ is = new GZIPInputStream(is);
+ } catch (IOException e) {
+ ERR.log (Level.INFO,
+ "The file at " + toParse +
+ ", corresponding to the catalog at " + p +
+ ", does not look like the gzip file, trying to parse it as the pure xml" , e);
+ //#150034
+ // Sometimes the .xml.gz file is downloaded as the pure .xml file due to the strange content-encoding processing
+ is.close();
+ is = null;
+ is = toParse.openStream();
+ }
+ }
+ InputSource src = new InputSource(new BufferedInputStream (is));
+ src.setSystemId(base.toString());
+ return src;
+ } catch (IOException ex) {
+ if(is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ }
+ ERR.log (Level.SEVERE, "Cannot estabilish input stream for " + toParse , ex);
+ return new InputSource();
+ }
+ }
+
+ private Stack currentGroup = new Stack ();
+ private String catalogDate;
+ private Stack currentModule = new Stack ();
+ private Stack