diff -r 1d736701d1bd autoupdate.services/apichanges.xml --- a/autoupdate.services/apichanges.xml Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/apichanges.xml Fri Aug 21 14:44:04 2009 +0400 @@ -71,6 +71,26 @@ + + + + New operation type introduced together with method for create appropriate container + + + + + +

+ New operation type - OperationSupport.OperationType.INTERNAL_UPDATE is introduced. + This operation can be used to find out elements which have updates and + which the particular element has the dependency on. +

+
+ + + +
+ diff -r 1d736701d1bd autoupdate.services/manifest.mf --- a/autoupdate.services/manifest.mf Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/manifest.mf Fri Aug 21 14:44:04 2009 +0400 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.autoupdate.services OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/services/resources/Bundle.properties -OpenIDE-Module-Specification-Version: 1.10 +OpenIDE-Module-Specification-Version: 1.11 AutoUpdate-Show-In-Client: false AutoUpdate-Essential-Module: true diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/api/autoupdate/OperationContainer.java --- a/autoupdate.services/src/org/netbeans/api/autoupdate/OperationContainer.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/api/autoupdate/OperationContainer.java Fri Aug 21 14:44:04 2009 +0400 @@ -97,6 +97,18 @@ } /** + * The factory method to construct instance of OperationContainer for internal update operation + * @return newly constructed instance of OperationContainer for internal update operation + * @since 1.11 + */ + public static OperationContainer createForInternalUpdate() { + OperationContainer retval = + new OperationContainer(OperationContainerImpl.createForInternalUpdate(), new InstallSupport()); + retval.getSupportInner ().setContainer(retval); + return retval; + } + + /** * The factory method to construct instance of OperationContainer for install operation * @return newly constructed instance of OperationContainer for install operation */ diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/api/autoupdate/OperationSupport.java --- a/autoupdate.services/src/org/netbeans/api/autoupdate/OperationSupport.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/api/autoupdate/OperationSupport.java Fri Aug 21 14:44:04 2009 +0400 @@ -151,6 +151,9 @@ case CUSTOM_UNINSTALL: impl = OperationSupportImpl.forCustomUninstall (); break; + case INTERNAL_UPDATE: + impl = OperationSupportImpl.forInternalUpdate (); + break; default: assert false : "Unknown OperationSupport for type " + type; } diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java --- a/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java Fri Aug 21 14:44:04 2009 +0400 @@ -82,6 +82,7 @@ import org.netbeans.api.autoupdate.InstallSupport.Installer; import org.netbeans.api.autoupdate.OperationSupport.Restarter; import org.netbeans.api.autoupdate.InstallSupport.Validator; +import org.netbeans.api.autoupdate.OperationContainer; import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; import org.netbeans.api.autoupdate.OperationException; import org.netbeans.api.autoupdate.UpdateElement; @@ -148,6 +149,31 @@ } infos = support.getContainer ().listAll (); + List > newInfos = new ArrayList >(); + for(OperationInfo i : infos) { + if(i.getUpdateUnit().getInstalled()!=null && + i.getUpdateUnit().getInstalled().equals(i.getUpdateElement()) ) { + //internal update, replace by required elements + for(UpdateElement e : i.getRequiredElements()) { + boolean add = true; + for(OperationInfo in : newInfos) { + if(in.getUpdateElement().equals(e)) { + add = false; + break; + } + } + if(add) { + OperationContainer upd = OperationContainer.createForUpdate(); + OperationInfo ii = upd.add(e); + newInfos.add(ii); + } + } + } else { + newInfos.add(i); + } + } + infos = newInfos; + int size = 0; for (OperationInfo info : infos) { size += info.getUpdateElement().getDownloadSize(); diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java --- a/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java Fri Aug 21 14:44:04 2009 +0400 @@ -68,6 +68,9 @@ public static OperationContainerImpl createForInstall () { return new OperationContainerImpl (OperationType.INSTALL); } + public static OperationContainerImpl createForInternalUpdate () { + return new OperationContainerImpl (OperationType.INTERNAL_UPDATE); + } public static OperationContainerImpl createForUpdate () { return new OperationContainerImpl (OperationType.UPDATE); } @@ -130,6 +133,13 @@ " and " + updateElement + " cannot be same for operation " + type); } break; + case INTERNAL_UPDATE: + /* + if (updateUnit.getInstalled () != updateElement) { + throw new IllegalArgumentException (updateUnit.getInstalled () + + " and " + updateElement + " must be same for operation " + type); + }*/ + break; default: assert false : "Unknown type of operation " + type; } @@ -180,18 +190,19 @@ return false; } - public List> listAll () { + private List> listAll () { return new ArrayList>(operations); } synchronized public List> listAllWithPossibleEager () { if (upToDate) { - return new ArrayList>(operations); + return listAll(); } + clearCache (); // handle eager modules - - if (type == OperationType.INSTALL || type == OperationType.UPDATE) { + + if (type == OperationType.INSTALL || type == OperationType.UPDATE || type==OperationType.INTERNAL_UPDATE) { Collection all = new HashSet (operations.size ()); Collection allModuleInfos = new HashSet (operations.size ()); for (OperationInfo i : operations) { @@ -219,7 +230,7 @@ for(ModuleInfo mi: infos) { Set reqs = new HashSet (); for (Dependency dep : mi.getDependencies ()) { - UpdateElement req = Utilities.handleDependency (dep, Collections.singleton (mi), new HashSet (), false); + UpdateElement req = Utilities.handleDependency (eagerEl, dep, Collections.singleton (mi), new HashSet (), false); if (req != null) { reqs.add (req); } @@ -250,7 +261,7 @@ LOGGER.log (Level.FINE, "== done. =="); } upToDate = true; - return new ArrayList>(operations); + return listAll(); } public List> listInvalid () { @@ -291,6 +302,19 @@ isValid = OperationValidator.isValidOperation (OperationType.INSTALL, updateUnit, updateElement); } break; + case INTERNAL_UPDATE: + isValid = OperationValidator.isValidOperation (type, updateUnit, updateElement); + // at least first add must pass and respect type of operation + if (! isValid && operations.size () > 0) { + // try Update + isValid = OperationValidator.isValidOperation (OperationType.UPDATE, updateUnit, updateElement); + } + if (! isValid && operations.size () > 0) { + // try Install + isValid = OperationValidator.isValidOperation (OperationType.INSTALL, updateUnit, updateElement); + } + break; + default: isValid = OperationValidator.isValidOperation (type, updateUnit, updateElement); } @@ -382,6 +406,8 @@ INSTALL, /** Uninstall UpdateElement */ UNINSTALL, + /** Internally update installed UpdateElement without version increase */ + INTERNAL_UPDATE, /** Uninstall UpdateElement on-the-fly */ DIRECT_UNINSTALL, /** Update installed UpdateElement to newer version. */ diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationSupportImpl.java --- a/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationSupportImpl.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationSupportImpl.java Fri Aug 21 14:44:04 2009 +0400 @@ -79,6 +79,7 @@ private static final OperationSupportImpl FOR_DIRECT_UNINSTALL = new ForDirectUninstall(); private static final OperationSupportImpl FOR_CUSTOM_INSTALL = new ForCustomInstall (); private static final OperationSupportImpl FOR_CUSTOM_UNINSTALL = new ForCustomUninstall (); + private static final OperationSupportImpl FOR_INTERNAL_UPDATE = new ForInternalUpdate(); private static final Logger LOGGER = Logger.getLogger ("org.netbeans.modules.autoupdate.services.OperationSupportImpl"); @@ -109,6 +110,9 @@ public static OperationSupportImpl forCustomUninstall () { return FOR_CUSTOM_UNINSTALL; } + public static OperationSupportImpl forInternalUpdate () { + return FOR_INTERNAL_UPDATE; + } public abstract Boolean doOperation(ProgressHandle progress/*or null*/, OperationContainer container) throws OperationException; public abstract void doCancel () throws OperationException; @@ -551,6 +555,25 @@ } } + + private static class ForInternalUpdate extends OperationSupportImpl { + public synchronized Boolean doOperation(ProgressHandle progress, + OperationContainer container) throws OperationException { + throw new UnsupportedOperationException("Not supported yet."); + } + public void doCancel () throws OperationException { + assert false : "Not supported yet"; + } + + public void doRestart (Restarter restarter, ProgressHandle progress) throws OperationException { + throw new UnsupportedOperationException ("Not supported yet."); + } + + public void doRestartLater (Restarter restarter) { + throw new UnsupportedOperationException ("Not supported yet."); + } + + } private static class ForCustomInstall extends OperationSupportImpl { private Collection affectedModules = null; diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationValidator.java --- a/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationValidator.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationValidator.java Fri Aug 21 14:44:04 2009 +0400 @@ -66,6 +66,7 @@ */ abstract class OperationValidator { private final static OperationValidator FOR_INSTALL = new InstallValidator(); + private final static OperationValidator FOR_INTERNAL_UPDATE = new InternalUpdateValidator(); private final static OperationValidator FOR_UNINSTALL = new UninstallValidator(); private final static OperationValidator FOR_UPDATE = new UpdateValidator(); private final static OperationValidator FOR_ENABLE = new EnableValidator(); @@ -86,6 +87,9 @@ case INSTALL: isValid = FOR_INSTALL.isValidOperationImpl(updateUnit, updateElement); break; + case INTERNAL_UPDATE: + isValid = FOR_INTERNAL_UPDATE.isValidOperationImpl(updateUnit, updateElement); + break; case DIRECT_UNINSTALL: case UNINSTALL: isValid = FOR_UNINSTALL.isValidOperationImpl(updateUnit, updateElement); @@ -141,6 +145,9 @@ case CUSTOM_UNINSTALL: retval = FOR_CUSTOM_UNINSTALL.getRequiredElementsImpl(updateElement, moduleInfos, brokenDependencies); break; + case INTERNAL_UPDATE: + retval = FOR_INTERNAL_UPDATE.getRequiredElementsImpl(updateElement, moduleInfos, brokenDependencies); + break; default: assert false; } @@ -164,6 +171,7 @@ break; case INSTALL : case UPDATE : + case INTERNAL_UPDATE: getRequiredElements (type, updateElement, moduleInfos, broken); break; case UNINSTALL : @@ -185,6 +193,12 @@ List moduleInfos, Collection brokenDependencies); + private static class InternalUpdateValidator extends InstallValidator { + @Override + boolean isValidOperationImpl(UpdateUnit unit, UpdateElement uElement) { + return uElement.equals(unit.getInstalled()) || containsElement (uElement, unit); + } + } private static class InstallValidator extends OperationValidator { boolean isValidOperationImpl(UpdateUnit unit, UpdateElement uElement) { return unit.getInstalled() == null && containsElement (uElement, unit); diff -r 1d736701d1bd autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java --- a/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java Fri Aug 21 14:44:04 2009 +0400 @@ -79,7 +79,11 @@ import java.util.prefs.Preferences; import org.netbeans.Module; import org.netbeans.ModuleManager; +import org.netbeans.api.autoupdate.InstallSupport; +import org.netbeans.api.autoupdate.OperationContainer; +import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; import org.netbeans.api.autoupdate.UpdateElement; +import org.netbeans.api.autoupdate.UpdateManager; import org.netbeans.api.autoupdate.UpdateUnit; import org.netbeans.core.startup.Main; import org.netbeans.core.startup.TopLogging; @@ -474,7 +478,7 @@ Set deps = new HashSet (((ModuleUpdateElementImpl) el).getModuleInfo ().getDependencies ()); Set availableInfos = new HashSet (infos); Set newones; - while (! (newones = processDependencies (deps, retval, availableInfos, brokenDependencies)).isEmpty ()) { + while (! (newones = processDependencies (deps, retval, availableInfos, brokenDependencies, element)).isEmpty ()) { deps = newones; } @@ -570,7 +574,7 @@ Set deps = new HashSet (tryUpdated.getDependencies ()); Set availableInfos = new HashSet (forInstall); Set newones; - while (! (newones = processDependencies (deps, moreRequested, availableInfos, brokenDependencies)).isEmpty ()) { + while (! (newones = processDependencies (deps, moreRequested, availableInfos, brokenDependencies, tryUE)).isEmpty ()) { deps = newones; } moreRequested.add (tryUE); @@ -587,10 +591,11 @@ private static Set processDependencies (final Set original, Set retval, Set availableInfos, - Set brokenDependencies) { + Set brokenDependencies, + UpdateElement el) { Set res = new HashSet (); for (Dependency dep : original) { - UpdateElement req = handleDependency (dep, availableInfos, brokenDependencies, true); + UpdateElement req = handleDependency (el, dep, availableInfos, brokenDependencies, true); if (req != null) { ModuleUpdateElementImpl reqM = (ModuleUpdateElementImpl) Trampoline.API.impl (req); availableInfos.add (reqM.getModuleInfo ()); @@ -602,7 +607,8 @@ return res; } - public static UpdateElement handleDependency (Dependency dep, + public static UpdateElement handleDependency (UpdateElement el, + Dependency dep, Collection availableInfos, Set brokenDependencies, boolean aggressive) { @@ -621,65 +627,6 @@ break; case Dependency.TYPE_MODULE : UpdateUnit u = DependencyAggregator.getRequested (dep); - - - ////////////////////////////////// - /* - boolean matched = false; - if (u == null) { - // last chance - for (ModuleInfo m : availableInfos) { - if (DependencyChecker.checkDependencyModule (dep, m)) { - matched = true; - break; - } - } - if (! matched) { - brokenDependencies.add (dep); - } - } else { - if (u.getInstalled () != null) { - UpdateElementImpl reqElImpl = Trampoline.API.impl (u.getInstalled ()); - matched = DependencyChecker.checkDependencyModule (dep, ((ModuleUpdateElementImpl) reqElImpl).getModuleInfo ()); - } - if (! matched) { - // first chance - for (ModuleInfo m : availableInfos) { - if (DependencyChecker.checkDependencyModule (dep, m)) { - matched = true; - break; - } - } - if (! matched) { - UpdateElement reqEl = u.getAvailableUpdates ().isEmpty () ? null : u.getAvailableUpdates ().get (0); - if (reqEl == null) { - for (ModuleInfo m : availableInfos) { - if (DependencyChecker.checkDependencyModule (dep, m)) { - matched = true; - break; - } - } - if (! matched) { - brokenDependencies.add (dep); - } - } else { - UpdateElementImpl reqElImpl = Trampoline.API.impl (reqEl); - ModuleUpdateElementImpl reqModuleImpl = (ModuleUpdateElementImpl) reqElImpl; - ModuleInfo info = reqModuleImpl.getModuleInfo (); - if (DependencyChecker.checkDependencyModule (dep, info)) { - if (! availableInfos.contains (info)) { - requested = reqEl; - } - } else { - brokenDependencies.add (dep); - } - } - } - } - } - */ - ////////////////////////////////// - boolean updateMatched = false; boolean installMatched = false; boolean availableMatched = false; @@ -714,13 +661,19 @@ if(updateMatched && installMatched && !aggressive) { requested = null; } + if (updateMatched && installMatched && aggressive) { + if (requested.getUpdateUnit().getType().equals(UpdateManager.TYPE.KIT_MODULE)) { + requested = null; + } else if (Trampoline.API.impl(el).isEager() && + !el.getUpdateUnit().getType().equals(UpdateManager.TYPE.KIT_MODULE)) { + requested = null; + } + } if (!installMatched && !availableMatched && !updateMatched) { brokenDependencies.add(dep); } - - ////////////////////////////////// break; case Dependency.TYPE_REQUIRES : case Dependency.TYPE_NEEDS : diff -r 1d736701d1bd autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/InternalUpdatesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/InternalUpdatesTest.java Fri Aug 21 14:44:04 2009 +0400 @@ -0,0 +1,359 @@ +/* + * 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.api.autoupdate; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; +import org.netbeans.api.autoupdate.OperationSupport.Restarter; +import org.netbeans.core.startup.MainLookup; +import org.netbeans.junit.NbTestCase; +import org.netbeans.modules.autoupdate.services.UpdateManagerImpl; +import org.netbeans.modules.autoupdate.updateprovider.AutoupdateCatalogProvider; +import org.openide.filesystems.FileUtil; +import org.openide.util.Lookup; + +/** + * + * @author dlm198383 + */ +public class InternalUpdatesTest extends NbTestCase { + + protected List keepItNotToGC; + private static File catalogFile; + private static URL catalogURL; + private File tmpDirectory; + private List nbms = new ArrayList(); + private List moduleElements = new ArrayList(); + + public InternalUpdatesTest(String testName) { + super(testName); + } + + public static class MyProvider extends AutoupdateCatalogProvider { + + public MyProvider() { + super("test-updates-provider", "test-updates-provider", catalogURL, UpdateUnitProvider.CATEGORY.STANDARD); + } + } + + private String getModuleElement(boolean visible, String codeName, String moduleName, String distr, String specVersion, String dependency) { + return "\n" + + "\n ", ">") + "\" " : "") + + "\n OpenIDE-Module-Requires='org.openide.modules.ModuleFormat1' " + + "\n OpenIDE-Module-Specification-Version='" + specVersion + "'/>" + + "\n [NO LICENSE SPECIFIED]" + + "\n" + + "\n\n"; + } + + private String createInfoXML(boolean visible, String codeName, String moduleName, String distr, String specVersion, String dependency) { + String moduleElement = getModuleElement(visible, codeName, moduleName, distr, specVersion, dependency); + + moduleElements.add(moduleElement); + return "" + + "" + + moduleElement; + } + + private void writeCatalog() throws IOException { + String res = "\n" + + "" + + "\n"; + for (String element : moduleElements) { + res += element; + } + res += "\n"; + if (catalogFile == null) { + catalogFile = File.createTempFile("catalog-", ".xml", tmpDirectory); + catalogURL = catalogFile.toURI().toURL(); + } + PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(catalogFile), "UTF-8")); + pw.write(res); + pw.close(); + } + + private String getConfigXML(String codeName, String moduleFile, String specVersion) { + return "" + + " " + + " " + + " false" + + " false" + + " true" + + " modules/" + moduleFile + ".jar" + + " false" + + " " + specVersion + "" + + " "; + } + + private String getManifest(String codeName, String moduleDir, String specVersion, boolean visible, String dependency) { + return "Manifest-Version: 1.0\n" + + "Ant-Version: Apache Ant 1.7.0\n" + + "Created-By: 1.6.0-b105 (Sun Microsystems Inc.)\n" + + "OpenIDE-Module-Public-Packages: -\n" + + "OpenIDE-Module-Java-Dependencies: Java > 1.4\n" + + "OpenIDE-Module-Implementation-Version: 070130\n" + + (dependency != null ? ("OpenIDE-Module-Module-Dependencies: " + dependency + "\n") : "") + + "OpenIDE-Module: " + codeName + "\n" + + "OpenIDE-Module-Localizing-Bundle: " + moduleDir + "Bundle.properties\n" + + "OpenIDE-Module-Specification-Version: " + specVersion + "\n" + + "OpenIDE-Module-Requires: org.openide.modules.ModuleFormat1\n" + + "AutoUpdate-Show-In-Client: " + visible + "\n" + + "\n"; + } + + private File prepareNBM(String codeName, String specVersion, boolean visible, String dependency) throws Exception { + String moduleName = codeName.substring(codeName.lastIndexOf(".") + 1); + String moduleFile = codeName.replace(".", "-"); + String moduleDir = codeName.replace(".", "/") + "/"; + File nbm = File.createTempFile(moduleFile + "-", ".nbm", tmpDirectory); + + final String MODULE_NAME_PROP = "OpenIDE-Module-Name"; + + File jar = new File(tmpDirectory, "netbeans/modules/" + moduleFile + ".jar"); + jar.getParentFile().mkdirs(); + JarOutputStream jos = new JarOutputStream(new FileOutputStream(jar)); + int idx = moduleDir.indexOf("/"); + while (idx != -1) { + jos.putNextEntry(new ZipEntry(moduleDir.substring(0, idx + 1))); + idx = moduleDir.indexOf("/", idx + 1); + } + + jos.putNextEntry(new ZipEntry(moduleDir + "Bundle.properties")); + jos.write(new String(MODULE_NAME_PROP + "=" + moduleName).getBytes("UTF-8")); + jos.putNextEntry(new ZipEntry("META-INF/")); + jos.putNextEntry(new ZipEntry("META-INF/manifest.mf")); + jos.write(getManifest(codeName, moduleDir, specVersion, visible, dependency).getBytes("UTF-8")); + jos.close(); + + Manifest mf = new Manifest(); + mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + jos = new JarOutputStream(new FileOutputStream(nbm), mf); + jos.putNextEntry(new ZipEntry("Info/")); + jos.putNextEntry(new ZipEntry("Info/info.xml")); + jos.write(createInfoXML(visible, codeName, moduleName, nbm.toURI().toURL().toString(), specVersion, dependency).getBytes("UTF-8")); + + jos.putNextEntry(new ZipEntry("netbeans/")); + jos.putNextEntry(new ZipEntry("netbeans/modules/")); + jos.putNextEntry(new ZipEntry("netbeans/config/")); + jos.putNextEntry(new ZipEntry("netbeans/config/Modules/")); + jos.putNextEntry(new ZipEntry("netbeans/config/Modules/" + moduleFile + ".xml")); + + jos.write(getConfigXML(codeName, moduleFile, specVersion).getBytes("UTF-8")); + + + jos.putNextEntry(new ZipEntry("netbeans/modules/" + moduleFile + ".jar")); + + FileInputStream fis = new FileInputStream(jar); + FileUtil.copy(fis, jos); + fis.close(); + jar.delete(); + jos.close(); + nbms.add(nbm); + + return nbm; + } + + protected void setUp() throws Exception { + super.setUp(); + this.clearWorkDir(); + tmpDirectory = new File(getWorkDirPath(), "tmp"); + tmpDirectory.mkdirs(); + + writeCatalog(); + + TestUtils.setUserDir(getWorkDirPath()); + TestUtils.testInit(); + + MainLookup.register(new MyProvider()); + assert Lookup.getDefault().lookup(MyProvider.class) != null; + UpdateUnitProviderFactory.getDefault().refreshProviders(null, true); + } + + public void testInternalUpdate() throws Exception { + String dep = "org.yourorghere.dep.module"; + String main = "org.yourorghere.main.module"; + + prepareNBM(dep, "1.0", false, null); + prepareNBM(main, "1.0", true, dep + " > 1.0"); + + writeCatalog(); + UpdateUnitProviderFactory.getDefault().refreshProviders(null, true); + + OperationContainer installContainer = OperationContainer.createForInstall(); + + UpdateUnit engineUnit = getUpdateUnit(main); + assertNull("cannot be installed", engineUnit.getInstalled()); + UpdateElement engineElement = getAvailableUpdate(engineUnit, 0); + OperationInfo engineInfo = installContainer.add(engineElement); + assertNotNull(engineInfo); + + + UpdateUnit independentUnit = getUpdateUnit(dep); + + assertNull("cannot be installed", independentUnit.getInstalled()); + UpdateElement independentElement = getAvailableUpdate(independentUnit, 0); + assertEquals(independentElement.getSpecificationVersion(), "1.0"); + + OperationInfo independentInfo = installContainer.add(independentElement); + assertNotNull(independentInfo); + + InstallSupport support = installContainer.getSupport(); + assertNotNull(support); + + InstallSupport.Validator v = support.doDownload(null, false); + assertNotNull(v); + InstallSupport.Installer i = support.doValidate(v, null); + assertNotNull(i); + Restarter r = null; + try { + r = support.doInstall(i, null); + } catch (OperationException ex) { + if (OperationException.ERROR_TYPE.INSTALL == ex.getErrorType()) { + // can ingore + // module system cannot load the module either + } else { + fail(ex.toString()); + } + } + + assertTrue("element " + engineElement + " was not insetalled", engineUnit.getInstalled() != null); + assertNull("Install update " + engineElement + " needs restart.", r); + + + assertTrue("independent module was not installed together with the engine", independentUnit.getInstalled() != null); + String specVersion = independentUnit.getInstalled().getSpecificationVersion(); + + assertTrue("independent version " + specVersion + " was installed together with the engine but 1.0 expected", specVersion.equals("1.0")); + + prepareNBM(dep, "1.1", false, null); + writeCatalog(); + UpdateUnitProviderFactory.getDefault().refreshProviders(null, true); + + independentUnit = getUpdateUnit(dep); + assertEquals(1, independentUnit.getAvailableUpdates().size()); + + OperationContainer internalUpdateContainer = OperationContainer.createForInternalUpdate(); + OperationInfo info = internalUpdateContainer.add(engineUnit.getInstalled()); + assertNotNull("Can`t add element " + engineUnit.getInstalled() + " to internal updates container", info); + + assertFalse("No internal updates available for " + engineUnit, internalUpdateContainer.listAll().isEmpty()); + + Set required = info.getRequiredElements(); + //for(OperationInfo in : internalUpdateContainer.listAll()) { + // required.add(in.getUpdateElement()); + // } + assertFalse("Does not have internal update for " + engineUnit, required.isEmpty()); + assertTrue("Has move than one internal update for " + engineUnit, required.size() == 1); + UpdateElement expectedRequired = independentUnit.getAvailableUpdates().get(0); + assertTrue("Has other internal update than version 1.1 for " + engineUnit, required.contains(expectedRequired)); + + + InstallSupport os = internalUpdateContainer.getSupport(); + assertNotNull(os); + + internalUpdateContainer.add(required); + // internalUpdateContainer.remove(info); + + v = os.doDownload(null, false); + assertNotNull(v); + i = os.doValidate(v, null); + assertNotNull(i); + r = null; + try { + r = os.doInstall(i, null); + } catch (OperationException ex) { + if (OperationException.ERROR_TYPE.INSTALL == ex.getErrorType()) { + // can ingore + // module system cannot load the module either + } else { + fail(ex.toString()); + } + } + + assertNotNull("Installing update require restarting", r); + } + + public UpdateUnit getUpdateUnit(String codeNameBase) { + UpdateUnit uu = UpdateManagerImpl.getInstance().getUpdateUnit(codeNameBase); + assertNotNull(uu); + return uu; + } + + public UpdateElement getAvailableUpdate(UpdateUnit updateUnit, int idx) { + List available = updateUnit.getAvailableUpdates(); + assertTrue(available.size() > idx); + return available.get(idx); + + } + + protected void tearDown() throws Exception { + super.tearDown(); + } +} diff -r 1d736701d1bd autoupdate.ui/manifest.mf --- a/autoupdate.ui/manifest.mf Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/manifest.mf Fri Aug 21 14:44:04 2009 +0400 @@ -3,6 +3,6 @@ OpenIDE-Module-Install: org/netbeans/modules/autoupdate/ui/actions/Installer.class OpenIDE-Module-Layer: org/netbeans/modules/autoupdate/ui/resources/layer.xml OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/ui/resources/Bundle.properties -OpenIDE-Module-Specification-Version: 1.8 +OpenIDE-Module-Specification-Version: 1.9 AutoUpdate-Show-In-Client: false AutoUpdate-Essential-Module: true diff -r 1d736701d1bd autoupdate.ui/nbproject/project.xml --- a/autoupdate.ui/nbproject/project.xml Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/nbproject/project.xml Fri Aug 21 14:44:04 2009 +0400 @@ -28,7 +28,7 @@ - 1.1 + 1.11 diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties Fri Aug 21 14:44:04 2009 +0400 @@ -190,3 +190,5 @@ UnitTab_Splitter_DefaultDividerLocation=390 #NOI18N SettingsTab_Splitter_DefaultDividerLocation=390 +Unit_InternalUpdates_Version=(Internal Updates) +Unit_InternalUpdates_Title=Internal Updates diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Containers.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Containers.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Containers.java Fri Aug 21 14:44:04 2009 +0400 @@ -53,6 +53,7 @@ */ public class Containers { private static Reference> INSTALL; + private static Reference> INTERNAL_UPDATE; private static Reference> UPDATE; private static Reference> INSTALL_FOR_NBMS; private static Reference> UPDATE_FOR_NBMS; @@ -74,6 +75,7 @@ forDisable().removeAll(); forCustomInstall().removeAll(); forCustomUninstall().removeAll(); + forInternalUpdate().removeAll(); } catch (NullPointerException npe) { // doesn't matter, can ignore that } @@ -197,4 +199,17 @@ return container; } } + public static OperationContainer forInternalUpdate () { + synchronized (Containers.class) { + OperationContainer container = null; + if (INTERNAL_UPDATE != null) { + container = INTERNAL_UPDATE.get (); + } + if(container == null) { + container = OperationContainer.createForInternalUpdate(); + INTERNAL_UPDATE = new WeakReference> (container); + } + return container; + } + } } diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Unit.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Unit.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Unit.java Fri Aug 21 14:44:04 2009 +0400 @@ -44,8 +44,10 @@ import java.text.Collator; import java.text.DateFormat; import java.text.ParseException; +import java.util.ArrayList; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Set; import java.util.logging.Level; @@ -59,6 +61,7 @@ import org.netbeans.api.autoupdate.UpdateUnitProvider.CATEGORY; import org.netbeans.modules.autoupdate.ui.UnitCategoryTableModel.Type; import org.openide.modules.SpecificationVersion; +import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; /** @@ -395,12 +398,88 @@ } } + + public static class InternalUpdate extends Unit.Update { + + private List internalUpdates; + + public InternalUpdate(UpdateUnit updateUnit, String categoryName, boolean isNbms) { + super(updateUnit, false, categoryName); + } + + public List getUpdateUnits() { + if(internalUpdates == null) { + internalUpdates = new ArrayList (); + } + return internalUpdates; + } + public UpdateUnit getVisibleUnit() { + return updateUnit; + } + + @Override + public UpdateElement getRelevantElement() { + return updateUnit.getInstalled(); + } + + @Override + public boolean isMarked() { + OperationContainer container = Containers.forUpdate (); + for(UpdateUnit invisible : getUpdateUnits()) { + if(!container.contains(invisible.getAvailableUpdates().get(0))) { + return false; + } + } + return true; + } + + @Override + public String getAvailableVersion () { + return getInstalledVersion() + " " + getBundle("Unit_InternalUpdates_Version"); + } + @Override + public void setMarked(boolean marked) { + assert marked != isMarked(); + OperationContainer container = Containers.forUpdate(); + for (UpdateUnit invisible : getUpdateUnits()) { + if (marked) { + if (container.canBeAdded(invisible, invisible.getAvailableUpdates().get(0))) { + container.add(invisible, invisible.getAvailableUpdates().get(0)); + } + } else { + container.remove(invisible.getAvailableUpdates().get(0)); + } + } + } + + @Override + public int getCompleteSize() { + if (size == -1) { + size = 0; + for (UpdateUnit u : getUpdateUnits()) { + size += u.getAvailableUpdates().get(0).getDownloadSize(); + } + + } + return size; + } + + public String getSize () { + return Utilities.getDownloadSizeAsString (getCompleteSize()); + } + + @Override + public Type getModelType() { + return Type.UPDATE; + } + + } public static class Update extends Unit { private UpdateElement installEl = null; private UpdateElement updateEl = null; private boolean isNbms; - private int size = -1; + protected int size = -1; public Update (UpdateUnit unit, boolean isNbms,String categoryName) { super (categoryName); @@ -408,8 +487,10 @@ this.updateUnit = unit; this.installEl = unit.getInstalled (); assert installEl != null : "Updateable UpdateUnit " + unit + " has Installed UpdateElement."; - this.updateEl = unit.getAvailableUpdates ().get (0); - assert updateEl != null : "Updateable UpdateUnit " + unit + " has UpdateElement for update."; + if(unit.getAvailableUpdates().size() > 0) { + this.updateEl = unit.getAvailableUpdates ().get (0); + assert updateEl != null : "Updateable UpdateUnit " + unit + " has UpdateElement for update."; + } initState(); } @@ -599,5 +680,9 @@ return updateEl.getSourceCategory(); } } + + private static String getBundle (String key) { + return NbBundle.getMessage (Unit.class, key); + } } diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UnitDetails.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UnitDetails.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UnitDetails.java Fri Aug 21 14:44:04 2009 +0400 @@ -45,6 +45,7 @@ import java.io.CharConversionException; import java.net.URL; import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -54,8 +55,10 @@ import org.netbeans.api.autoupdate.InstallSupport; import org.netbeans.api.autoupdate.OperationContainer; import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; +import org.netbeans.api.autoupdate.OperationSupport; import org.netbeans.api.autoupdate.UpdateElement; import org.netbeans.api.autoupdate.UpdateManager; +import org.netbeans.api.autoupdate.UpdateUnit; import org.netbeans.api.autoupdate.UpdateUnitProvider.CATEGORY; import org.openide.util.NbBundle; import org.openide.xml.XMLUtil; @@ -108,16 +111,32 @@ Unit.Update uu = ((Unit.Update) u); text += "" + getBundle ("UnitDetails_Plugin_InstalledVersion") + "" + uu.getInstalledVersion () + "
"; // NOI18N text += "" + getBundle ("UnitDetails_Plugin_AvailableVersion") + "" + uu.getAvailableVersion () + "
"; // NOI18N + if(!(u instanceof Unit.InternalUpdate)) { + OperationContainer container = OperationContainer.createForUpdate(); - OperationContainer container = OperationContainer.createForUpdate(); - OperationInfo info = container.add(u.updateUnit, uu.getRelevantElement()); - Set reqs = info.getRequiredElements(); + container.add(u.updateUnit, uu.getRelevantElement()); Set required = new LinkedHashSet (); - required.addAll(reqs); - for(OperationInfo i : container.listAll()) { + + for (OperationInfo info : container.listAll()) { + Set reqs = info.getRequiredElements(); + for (UpdateElement req : reqs) { + if (req.getUpdateUnit().getInstalled() != null) { + for (UpdateElement e : OperationContainer.createForUpdate().add(req).getRequiredElements()) { + if (!required.contains(e)) { + required.add(e); + } + } + } else { + //OperationContainer.createForInstall(). + } + } + required.addAll(reqs); + } + + for(OperationInfo i : container.listAll()) { if(!required.contains(i.getUpdateElement()) && !i.getUpdateUnit().equals(u.updateUnit)) { required.add(i.getUpdateElement()); - } + } } @@ -128,8 +147,8 @@ visibleRequirements.add(ue); } } - OperationContainer containerForVisibleUpdate = OperationContainer.createForUpdate(); - OperationContainer containerForVisibleInstall = OperationContainer.createForInstall(); + OperationContainer containerForVisibleUpdate = OperationContainer.createForUpdate(); + OperationContainer containerForVisibleInstall = OperationContainer.createForInstall(); List> infoList = new ArrayList>(); for (UpdateElement ue : visibleRequirements) { if (containerForVisibleUpdate.canBeAdded(ue.getUpdateUnit(), ue)) { @@ -166,6 +185,80 @@ } } } + } else { + Unit.InternalUpdate iu = (Unit.InternalUpdate) u; + desc = ""; + + OperationContainer updContainer = OperationContainer.createForUpdate(); + for(UpdateUnit inv : iu.getUpdateUnits()) { + updContainer.add(inv.getAvailableUpdates().get(0)); + } + + OperationContainer reiContainer = OperationContainer.createForInternalUpdate(); + reiContainer.add(iu.getRelevantElement()); + Set internalUpdates = new HashSet (); + + for (OperationInfo info : updContainer.listAll()) { + internalUpdates.add(info.getUpdateElement()); + for(UpdateElement r: info.getRequiredElements()) { + if(r.getUpdateUnit().getInstalled()!=null) { + internalUpdates.add(r); + } + + } + } + for (OperationInfo info : reiContainer.listAll()) { + if(!info.getUpdateElement().equals(iu.updateUnit.getInstalled())) { + internalUpdates.add(info.getUpdateElement()); + } + for(UpdateElement r: info.getRequiredElements()) { + if(r.getUpdateUnit().getInstalled()!=null) { + internalUpdates.add(r); + } + } + } + + + /* + for(UpdateElement e: container.add(u.getRelevantElement()).getRequiredElements()) { + if(!internalUpdates.contains(e.getUpdateUnit())) { + internalUpdates.add(e.getUpdateUnit()); + } + } + for(OperationInfo info: container.listAll()) { + if(info.getUpdateUnit()!=u.updateUnit && !internalUpdates.contains(info.getUpdateUnit())) { + internalUpdates.add(info.getUpdateUnit()); + } + } + */ + /* + + + for (UpdateUnit upd : iu.getUpdateUnits()) { + UpdateElement ue = upd.getAvailableUpdates().get(0); + for(UpdateElement e : OperationContainer.createForUpdate().add(ue).getRequiredElements()) { + if(!internalUpdates.contains(e.getUpdateUnit())) { + internalUpdates.add(e.getUpdateUnit()); + } + } + }*/ + + for (UpdateElement ue : internalUpdates) { + //UpdateElement ue = upd.getUgetAvailableUpdates().get(0); + desc += "    " + + ue.getDisplayName(); + if (ue.getUpdateUnit().getInstalled() != null) { + desc += " [" + ue.getUpdateUnit().getInstalled().getSpecificationVersion() + "->"; + } else { + desc += " new! ["; + } + + + desc += ue.getUpdateUnit().getAvailableUpdates().get(0).getSpecificationVersion(); + desc += "]"; + desc += "
"; + } + } } else { text += "" + getBundle ("UnitDetails_Plugin_Version") + "" + u.getDisplayVersion() + "
"; // NOI18N } @@ -193,7 +286,7 @@ text += u.getDescription (); } if(desc!=null && desc.length() > 0) { - text += "

" + "Internal Updates" + "

"; // NOI18N + text += "

" + getBundle ("Unit_InternalUpdates_Title") + "

"; // NOI18N text += desc; } } catch (CharConversionException e) { diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateTableModel.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateTableModel.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateTableModel.java Fri Aug 21 14:44:04 2009 +0400 @@ -86,7 +86,7 @@ return ; } super.setValueAt(anValue, row, col); - Unit.Update u = (Unit.Update) getUnitAtRow(row); + Unit u = getUnitAtRow(row); assert anValue instanceof Boolean : anValue + " must be instanceof Boolean."; boolean beforeMarked = u.isMarked(); u.setMarked(!beforeMarked); @@ -102,7 +102,7 @@ public Object getValueAt(int row, int col) { Object res = null; if (isExpansionControlAtRow(row)) return "";//NOI18N - Unit.Update u = (Unit.Update) getUnitAtRow(row); + Unit u = getUnitAtRow(row); switch (col) { case 0 : res = u.isMarked() ? Boolean.TRUE : Boolean.FALSE; diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Utilities.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Utilities.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Utilities.java Fri Aug 21 14:44:04 2009 +0400 @@ -52,8 +52,10 @@ import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.StringTokenizer; import java.util.logging.Level; import java.util.logging.Logger; @@ -63,6 +65,10 @@ import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; +import org.netbeans.api.autoupdate.InstallSupport; +import org.netbeans.api.autoupdate.OperationContainer; +import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; +import org.netbeans.api.autoupdate.OperationSupport; import org.netbeans.api.autoupdate.UpdateElement; import org.netbeans.api.autoupdate.UpdateManager; import org.netbeans.api.autoupdate.UpdateUnit; @@ -134,6 +140,7 @@ }; public static List makeUpdateCategories (final List units, boolean isNbms) { + long start = System.currentTimeMillis(); if (! isNbms && ! units.isEmpty ()) { List fcCats = makeFirstClassUpdateCategories (); if (! fcCats.isEmpty ()) { @@ -143,7 +150,13 @@ } } List res = new ArrayList (); + if(units.isEmpty()) { + return res; + } + List names = new ArrayList (); + Set coveredByVisible = new HashSet (); + for (UpdateUnit u : units) { UpdateElement el = u.getInstalled (); if (! u.isPending() && el != null) { @@ -151,6 +164,18 @@ if (updates.isEmpty()) { continue; } + coveredByVisible.add(u); + + OperationContainer container = OperationContainer.createForUpdate(); + OperationInfo info = container.add(updates.get(0)); + Set required = info.getRequiredElements(); + for(UpdateElement ue : required){ + coveredByVisible.add(ue.getUpdateUnit()); + } + for(OperationInfo i : container.listAll()) { + coveredByVisible.add((i.getUpdateUnit())); + } + String catName = el.getCategory(); if (names.contains (catName)) { UnitCategory cat = res.get (names.indexOf (catName)); @@ -163,10 +188,129 @@ } } } - logger.log(Level.FINER, "makeUpdateCategories (" + units.size () + ") returns " + res.size ()); + + // not covered by visible modules + + Collection allUnits = UpdateManager.getDefault ().getUpdateUnits (UpdateManager.TYPE.MODULE); + Set otherUnits = new HashSet (); + for(UpdateUnit u : allUnits) { + if(!coveredByVisible.contains(u) && + u.getAvailableUpdates().size() > 0 && + u.getInstalled()!=null && + !u.isPending()) { + otherUnits.add(u); + } + } + + List internals = new ArrayList (); + HashMap > map = getVisibleModulesDependecyMap(units); + if(otherUnits.size() > 0 && !isNbms) { + for(UpdateUnit uu : otherUnits) { + UpdateUnit u = getVisibleUnitForInvisibleModule(uu, map); + if (u != null) { + boolean exist = false; + for(Unit.InternalUpdate internal : internals) { + if(internal.getVisibleUnit() == u) { + internal.getUpdateUnits().add(uu); + exist = true; + } + } + if(!exist) { + //all already determined "internal" visible updates does not contain just found one + String catName = u.getInstalled().getCategory(); + Unit.InternalUpdate iu = new Unit.InternalUpdate(u, catName, false); + iu.getUpdateUnits().add(uu); + internals.add(iu); + UnitCategory cat = new UnitCategory(catName); + res.add(cat); + names.add(catName); + cat.addUnit(iu); + } + } else { + // fallback, show module itself + String catName = uu.getAvailableUpdates().get(0).getCategory(); + UnitCategory cat = null; + + if (names.contains(catName)) { + cat = res.get(names.indexOf(catName)); + } else { + cat = new UnitCategory(catName); + res.add(cat); + names.add(catName); + } + cat.addUnit(new Unit.Update(uu, isNbms, cat.getCategoryName())); + } + } + } + for(Unit.InternalUpdate iu : internals) { + iu.initState(); + } + logger.log(Level.FINE, "makeUpdateCategories (" + units.size () + ") returns " + res.size () + ", took " + (System.currentTimeMillis()-start) + " ms"); + return res; }; + public static HashMap> getVisibleModulesDependecyMap(Collection allUnits) { + HashMap> result = new HashMap >(); + for (UpdateUnit u : allUnits) { + if (u.getInstalled() != null && !u.isPending()) { + OperationContainer container = OperationContainer.createForInternalUpdate(); + OperationInfo info = container.add(u, u.getInstalled()); + + List list = new ArrayList(); + + for (UpdateElement ur : info.getRequiredElements()) { + list.add(ur); + } + for (OperationInfo in : container.listAll()) { + UpdateUnit unit = in.getUpdateUnit(); + if (unit != u) { + List updates = unit.getAvailableUpdates(); + if (updates.size() > 0 && !list.contains(updates.get(0))) { + list.add(updates.get(0)); + } + } + } + if(!list.isEmpty()) { + result.put(u, list); + } + } + } + return result; + } + + public static UpdateUnit getVisibleUnitForInvisibleModule(UpdateUnit invisible, HashMap> map) { + List candidates = new ArrayList(); + + for(UpdateUnit unit : map.keySet()) { + for (UpdateElement ue : map.get(unit)) { + if (ue.getUpdateUnit().equals(invisible)) { + logger.log(Level.FINE, + "... found candidate visible module " + unit.getCodeName() + " for invisible " + invisible.getCodeName()); + candidates.add(unit); + } + } + } + + UpdateUnit result = null; + if(candidates.size()==0) { + logger.log(Level.FINE, + "Have not found visible module for invisible " + invisible.getCodeName()); + } else { + result = candidates.get(0); + for(UpdateUnit u : candidates) { + if(u.getCodeName().endsWith(".kit")) { + result = u;break; + } + } + logger.log(Level.FINE, + "Found visible module " + candidates.get(0).getCodeName() + " for invisible " + invisible.getCodeName()); + } + + return result; + } + + public static long getTimeOfInitialization () { return getPreferences ().getLong (TIME_OF_MODEL_INITIALIZATION, 0); } diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/actions/AutoupdateCheckScheduler.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/actions/AutoupdateCheckScheduler.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/actions/AutoupdateCheckScheduler.java Fri Aug 21 14:44:04 2009 +0400 @@ -44,6 +44,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -209,12 +210,27 @@ OperationContainer container = handleUpdates ? OperationContainer.createForUpdate () : OperationContainer.createForInstall (); + + + List elements = new ArrayList(); + for (UnitCategory cat : cats) { - for (Unit u : cat.getUnits ()) { - UpdateElement element = handleUpdates ? - ((Unit.Update) u).getRelevantElement () : - ((Unit.Available) u).getRelevantElement (); - if (container.canBeAdded (element.getUpdateUnit (), element) && ! somePendingElements) { + for (Unit u : cat.getUnits ()) { + if(u instanceof Unit.Available) { + elements.add(((Unit.Available) u).getRelevantElement ()); + } else if (u instanceof Unit.InternalUpdate) { + for(UpdateUnit uu :((Unit.InternalUpdate) u).getUpdateUnits()) { + elements.add(uu.getAvailableUpdates().get(0)); + } + } else if (u instanceof Unit.Update) { + elements.add(((Unit.Update) u).getRelevantElement ()); + } + + } + } + for(UpdateElement element : elements) { + if (! somePendingElements) { + if(container.canBeAdded (element.getUpdateUnit (), element)) { OperationInfo operationInfo = container.add (element); if (operationInfo == null) { updates.add (element); @@ -251,14 +267,11 @@ if (! somePendingElements && someBrokenDependencies) { // 2. if some problem then try one by one updates = new HashSet (); - for (UnitCategory cat : cats) { - for (Unit u : cat.getUnits ()) { + for(UpdateElement element : elements) { OperationContainer oc = handleUpdates ? OperationContainer.createForUpdate () : OperationContainer.createForInstall (); - UpdateElement element = handleUpdates ? - ((Unit.Update) u).getRelevantElement () : - ((Unit.Available) u).getRelevantElement (); + UpdateUnit unit = element.getUpdateUnit (); if (oc.canBeAdded (unit, element)) { OperationInfo operationInfo = oc.add (element); @@ -295,8 +308,7 @@ " cannot be installed, Install Container contains invalid elements " + oc.listInvalid ()); // NOI18N } } - } - } + } } } diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/InstallStep.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/InstallStep.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/InstallStep.java Fri Aug 21 14:44:04 2009 +0400 @@ -551,12 +551,13 @@ if (installException == null) { component.setHeadAndContent (getBundle (HEAD_INSTALL_DONE), getBundle (CONTENT_INSTALL_DONE)); panel.setBody (getBundle ("InstallStep_InstallDone_Text"), - InstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + model.getAllVisibleUpdateElements ()); } else { component.setHeadAndContent (getBundle (HEAD_INSTALL_UNSUCCESSFUL), getBundle (CONTENT_INSTALL_UNSUCCESSFUL)); panel.setBody (getBundle ("InstallStep_InstallUnsuccessful_Text", installException.getLocalizedMessage ()), - InstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + model.getAllVisibleUpdateElements ()); } + panel.hideRunInBackground (); } @@ -565,7 +566,7 @@ model.modifyOptionsForDoClose (wd, true); restarter = r; panel.setRestartButtonsVisible (true); - panel.setBody (getBundle ("InstallStep_InstallDone_Text"), InstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("InstallStep_InstallDone_Text"), model.getAllVisibleUpdateElements ()); panel.hideRunInBackground (); if (runInBackground ()) { InstallSupport support = model.getInstallSupport (); diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationDescriptionStep.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationDescriptionStep.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationDescriptionStep.java Fri Aug 21 14:44:04 2009 +0400 @@ -44,6 +44,7 @@ import java.awt.Component; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -55,11 +56,16 @@ import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.netbeans.api.autoupdate.InstallSupport; +import org.netbeans.api.autoupdate.OperationContainer; +import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; import org.netbeans.api.autoupdate.OperationException; +import org.netbeans.api.autoupdate.OperationSupport; import org.netbeans.api.autoupdate.UpdateElement; import org.netbeans.api.autoupdate.UpdateManager; import org.netbeans.api.autoupdate.UpdateUnit; import org.netbeans.modules.autoupdate.ui.Containers; +import org.netbeans.modules.autoupdate.ui.Utilities; import org.netbeans.modules.autoupdate.ui.wizards.OperationWizardModel.OperationType; import org.openide.WizardDescriptor; import org.openide.modules.Dependency; @@ -155,10 +161,7 @@ } body = new OperationDescriptionPanel (tableTitle, preparePluginsForShow ( - OperationWizardModel.getVisibleUpdateElements ( - model.getPrimaryUpdateElements (), - false, - model.getOperation ()), + model.getPrimaryVisibleUpdateElements(), model.getCustomHandledComponents (), model.getOperation ()), "", @@ -192,16 +195,15 @@ } else { body = new OperationDescriptionPanel (tableTitle, preparePluginsForShow ( - OperationWizardModel.getVisibleUpdateElements ( - model.getPrimaryUpdateElements (), false, model.getOperation ()), + model.getPrimaryVisibleUpdateElements(), model.getCustomHandledComponents (), model.getOperation ()), dependenciesTitle, preparePluginsForShow ( - OperationWizardModel.getVisibleUpdateElements (model.getRequiredUpdateElements (), true, model.getOperation ()), + model.getRequiredVisibleUpdateElements(), null, model.getOperation ()), - ! OperationWizardModel.getVisibleUpdateElements (model.getRequiredUpdateElements (), true, model.getOperation ()).isEmpty ()); + ! model.getRequiredVisibleUpdateElements().isEmpty ()); } final JPanel finalPanel = body; readyToGo = model != null && ! hasBrokenDependencies; @@ -357,9 +359,34 @@ return presentationName == null ? dep : presentationName; } - private String preparePluginsForShow (Set plugins, Set customHandled, OperationType type) { + private String preparePluginsForShow (Set allplugins, Set customHandled, OperationType type) { String s = new String (); List names = new ArrayList (); + List invisibleIncluded = new ArrayList (); + List units = new ArrayList (); + List plugins = new ArrayList(); + for(UpdateElement el : allplugins) { + boolean internal = false; + if (OperationWizardModel.OperationType.UPDATE == type && el.getUpdateUnit ().getInstalled () != null) { + String oldVersion = el.getUpdateUnit ().getInstalled ().getSpecificationVersion (); + String newVersion = el.getSpecificationVersion (); + if(oldVersion.equals(newVersion) || !el.getUpdateUnit().getType().equals(UpdateManager.TYPE.KIT_MODULE) ) { + internal = true; + } + } + if(internal) { + plugins.add(el); + } else { + plugins.add(0, el); + } + } + + for(UpdateElement p : plugins) { + units.add(p.getUpdateUnit()); + } + //HashMap > map = Utilities.getVisibleModulesDependecyMap(UpdateManager.getDefault().getUpdateUnits(Utilities.getUnitTypes())); + HashMap > map = Utilities.getVisibleModulesDependecyMap(units); + if (plugins != null && ! plugins.isEmpty ()) { for (UpdateElement el : plugins) { String updatename; @@ -367,7 +394,70 @@ if (OperationWizardModel.OperationType.UPDATE == type && el.getUpdateUnit ().getInstalled () != null) { String oldVersion = el.getUpdateUnit ().getInstalled ().getSpecificationVersion (); String newVersion = el.getSpecificationVersion (); - updatename += getBundle ("OperationDescriptionStep_UpdatePluginVersionFormat", oldVersion, newVersion); + OperationContainer container = OperationContainer.createForUpdate(); + if (oldVersion.equals(newVersion)) { + //internal update + //updatename += getBundle ("OperationDescriptionStep_PluginVersionFormat", oldVersion); + OperationContainer internalUpdate = OperationContainer.createForInternalUpdate(); + internalUpdate.add(el); + for (OperationInfo info : internalUpdate.listAll()) { + if (!info.getUpdateElement().equals(el)) { + if (!container.contains(info.getUpdateElement())) { + container.add(info.getUpdateElement()); + } + } + for (UpdateElement r : info.getRequiredElements()) { + if (!container.contains(r)) { + container.add(r); + } + } + } + } else { + updatename += getBundle("OperationDescriptionStep_UpdatePluginVersionFormat", oldVersion, newVersion); + container.add(el); + } + + + + List list = new ArrayList(); + for (OperationInfo info : container.listAll()) { + + if(!info.getUpdateUnit().equals(el.getUpdateUnit()) && + info.getUpdateUnit().getInstalled() != null) { + list.add(info.getUpdateElement()); + } + for (UpdateElement upd : info.getRequiredElements()) { + if (upd.getUpdateUnit().getInstalled() != null) { + list.add(upd); + } + } + } + + for (UpdateElement upd : list) { + UpdateUnit unit = upd.getUpdateUnit(); + if(unit.getType().equals(UpdateManager.TYPE.KIT_MODULE) || invisibleIncluded.contains(unit)) { + continue; + } + UpdateUnit visibleUnit = Utilities.getVisibleUnitForInvisibleModule(unit, map); + if(visibleUnit!=null && visibleUnit != el.getUpdateUnit()) { + continue; + } + if(!unit.getType().equals(UpdateManager.TYPE.KIT_MODULE)) { + invisibleIncluded.add(unit); + } + if(unit.getInstalled()!=null) { + updatename += "
    " + upd.getDisplayName() + + " [" + + unit.getInstalled().getSpecificationVersion() + " -> " + + unit.getAvailableUpdates().get(0).getSpecificationVersion() + + "]"; + } else { + updatename += "
    " + upd.getDisplayName() + + " [" + + unit.getAvailableUpdates().get(0).getSpecificationVersion() + + "]"; + } + } } else { updatename += getBundle ("OperationDescriptionStep_PluginVersionFormat", // NOI18N el.getSpecificationVersion ()); diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationPanel.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationPanel.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationPanel.java Fri Aug 21 14:44:04 2009 +0400 @@ -190,16 +190,11 @@ } private JComponent getElementsComponent (List elements) { - JTextPane area = new JTextPane (); - area.setEditable (false); - area.setContentType ("text/html"); // NOI18N - String body = new String (); + StringBuilder body = new StringBuilder (); for (UpdateElement el : elements) { - body = body + el.getDisplayName () + "
"; // NOI18N + body.append(el.getDisplayName () + "
"); // NOI18N } - area.setText (body); - area.setOpaque (false); - return area; + return getElementsComponent(body.toString()); } private JComponent getElementsComponent (String msg) { diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationWizardModel.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationWizardModel.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/OperationWizardModel.java Fri Aug 21 14:44:04 2009 +0400 @@ -56,12 +56,14 @@ import java.util.logging.Logger; import javax.swing.JButton; import javax.swing.SwingUtilities; +import org.netbeans.api.autoupdate.InstallSupport; import org.netbeans.api.autoupdate.OperationContainer; import org.netbeans.api.autoupdate.OperationContainer.OperationInfo; import org.netbeans.api.autoupdate.OperationException; import org.netbeans.api.autoupdate.OperationSupport; import org.netbeans.api.autoupdate.UpdateElement; import org.netbeans.api.autoupdate.UpdateManager; +import org.netbeans.api.autoupdate.UpdateUnit; import org.netbeans.modules.autoupdate.ui.Containers; import org.netbeans.modules.autoupdate.ui.Utilities; import org.openide.WizardDescriptor; @@ -256,17 +258,80 @@ } return allElements; } - - public static Set getVisibleUpdateElements (Set all, boolean canBeEmpty, OperationType operationType) { + + + public Set getAllVisibleUpdateElements () { + Set all = getAllUpdateElements(); + Set visible = getVisibleUpdateElements(all, false, getOperation(), true); + return visible; + } + public Set getPrimaryVisibleUpdateElements () { + Set primary = getPrimaryUpdateElements(); + Set visible = getVisibleUpdateElements(primary, false, getOperation(), true); + return visible; + } + public Set getRequiredVisibleUpdateElements () { + Set required = getRequiredUpdateElements(); + Set visible = getVisibleUpdateElements(required, true, getOperation(), false); + return visible; + } + + private static Set getVisibleUpdateElements (Set all, boolean canBeEmpty, OperationType operationType, boolean checkInternalUpdates) { if (Utilities.modulesOnly () || OperationType.LOCAL_DOWNLOAD == operationType) { return all; } else { Set visible = new HashSet (); + Set visibleUnits = new HashSet (); + Set invisible = new HashSet (); for (UpdateElement el : all) { if (UpdateManager.TYPE.KIT_MODULE == el.getUpdateUnit ().getType ()) { visible.add (el); + visibleUnits.add(el.getUpdateUnit()); + } else { + invisible.add(el); } } + //filter out eager invisible modules, which are covered by visible + List realInvisible = new ArrayList (invisible); + for(UpdateElement v : visible) { + OperationContainer container; + if(v.getUpdateUnit().getInstalled()!=null) { + container = OperationContainer.createForUpdate(); + } else { + container = OperationContainer.createForInstall(); + } + container.add(v); + for(OperationInfo info : container.listAll()) { + realInvisible.remove(info.getUpdateElement()); + } + } + //filter out eager invisible modules, which are covered by other invisible + for(UpdateElement v : invisible) { + OperationContainer container = OperationContainer.createForUpdate(); + container.add(v); + for(OperationInfo info : container.listAll()) { + if(info.getUpdateElement()!=v) { + realInvisible.remove(info.getUpdateElement()); + } + } + } + + + if(!realInvisible.isEmpty() && checkInternalUpdates) { + HashMap > map = Utilities.getVisibleModulesDependecyMap(UpdateManager.getDefault().getUpdateUnits(Utilities.getUnitTypes())); + //HashMap > map = Utilities.getVisibleModulesDependecyMap(visibleUnits); + for(UpdateElement el : realInvisible) { + if(el.getUpdateUnit().getInstalled()!=null) { + UpdateUnit visibleUU = Utilities.getVisibleUnitForInvisibleModule(el.getUpdateUnit(), map); + if(visibleUU!=null) { + visible.add(visibleUU.getInstalled()); + } else { + visible.add(el); + } + } + } + } + if (visible.isEmpty () && ! canBeEmpty) { // in Downloaded tab may become all NBMs are hidden visible = all; diff -r 1d736701d1bd autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/UninstallStep.java --- a/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/UninstallStep.java Tue Aug 18 15:24:31 2009 +0400 +++ b/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/UninstallStep.java Fri Aug 21 14:44:04 2009 +0400 @@ -216,13 +216,13 @@ model.modifyOptionsForDoClose (wd); switch (model.getOperation ()) { case UNINSTALL : - panel.setBody (getBundle ("UninstallStep_UninstallDone_Text"), UninstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("UninstallStep_UninstallDone_Text"), model.getAllVisibleUpdateElements ()); break; case ENABLE : - panel.setBody (getBundle ("UninstallStep_ActivateDone_Text"), UninstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("UninstallStep_ActivateDone_Text"), model.getAllVisibleUpdateElements ()); break; case DISABLE : - panel.setBody (getBundle ("UninstallStep_DeactivateDone_Text"), UninstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("UninstallStep_DeactivateDone_Text"), model.getAllVisibleUpdateElements ()); break; default: assert false : "Unknown OperationType " + model.getOperation (); @@ -247,7 +247,7 @@ switch (model.getOperation ()) { case UNINSTALL : panel.setBody (getBundle ("UninstallStep_UninstallFailed_Text", ex.getLocalizedMessage ()), - UninstallUnitWizardModel.getVisibleUpdateElements(model.getAllUpdateElements(), false, model.getOperation())); + model.getAllVisibleUpdateElements ()); break; case ENABLE : panel.setBody (getBundle ("UninstallStep_ActivateFailed_Text", @@ -256,7 +256,7 @@ break; case DISABLE : panel.setBody (getBundle ("UninstallStep_DeactivateFailed_Text", ex.getLocalizedMessage ()), - UninstallUnitWizardModel.getVisibleUpdateElements(model.getAllUpdateElements(), false, model.getOperation())); + model.getAllVisibleUpdateElements ()); break; default: assert false : "Unknown OperationType " + model.getOperation (); @@ -270,13 +270,13 @@ panel.setRestartButtonsVisible (true); switch (model.getOperation ()) { case UNINSTALL : - panel.setBody (getBundle ("UninstallStep_UninstallDone_Text"), UninstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("UninstallStep_UninstallDone_Text"), model.getAllVisibleUpdateElements ()); break; case ENABLE : - panel.setBody (getBundle ("UninstallStep_ActivateDone_Text"), UninstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("UninstallStep_ActivateDone_Text"), model.getAllVisibleUpdateElements ()); break; case DISABLE : - panel.setBody (getBundle ("UninstallStep_DeactivateDone_Text"), UninstallUnitWizardModel.getVisibleUpdateElements (model.getAllUpdateElements (), false, model.getOperation ())); + panel.setBody (getBundle ("UninstallStep_DeactivateDone_Text"), model.getAllVisibleUpdateElements ()); break; default: assert false : "Unknown OperationType " + model.getOperation ();