[NETBEANS-1147,NETBEANS-1298] Autoupdated fragment restarts only if its host is already ON
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 656f929..e70e04c 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -34,6 +34,7 @@
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
@@ -46,8 +47,12 @@
import org.netbeans.api.autoupdate.OperationContainer.OperationInfo;
import org.netbeans.api.autoupdate.OperationSupport.Restarter;
import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.autoupdate.updateprovider.AutoupdateInfoParser;
+import org.netbeans.modules.autoupdate.updateprovider.ModuleItem;
import org.netbeans.modules.autoupdate.updateprovider.NetworkAccess;
import org.netbeans.modules.autoupdate.updateprovider.NetworkAccess.Task;
+import org.netbeans.modules.autoupdate.updateprovider.UpdateItemImpl;
+import org.netbeans.spi.autoupdate.UpdateItem;
import org.netbeans.updater.ModuleDeactivator;
import org.netbeans.updater.ModuleUpdater;
import org.netbeans.updater.UpdateTracking;
@@ -59,6 +64,7 @@
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbCollections;
+import org.xml.sax.SAXException;
/**
*
@@ -1083,6 +1089,8 @@
break;
}
}
+ updateFragmentStatus(impl, nbmFile);
+
} catch (IOException ioe) {
LOG.log (Level.INFO, ioe.getMessage (), ioe);
res = "BAD_DOWNLOAD";
@@ -1099,6 +1107,45 @@
return el.getDownloadSize ();
}
+ private void updateFragmentStatus(UpdateElementImpl el, File nbmFile) throws IOException {
+ UpdateItemImpl impl = el.getInstallInfo().getUpdateItemImpl();
+ if (!(impl instanceof ModuleItem)) {
+ return;
+ }
+ ModuleItem mod = (ModuleItem)impl;
+ if (mod.isFragment()) {
+ String fhost = mod.getFragmentHost();
+ Module m = Utilities.toModule(fhost);
+ if (m != null && m.isEnabled()) {
+ impl.setNeedsRestart(Boolean.TRUE);
+ }
+ }
+
+ Map<String, UpdateItem> items;
+ try {
+ items = AutoupdateInfoParser.getUpdateItems(nbmFile);
+ } catch (SAXException ex) {
+ throw new IOException(ex);
+ }
+ for (UpdateItem realItem : items.values()) {
+ UpdateItemImpl realImpl = Trampoline.SPI.impl(realItem);
+ if (realImpl instanceof ModuleItem) {
+ ModuleItem realMod = (ModuleItem)realImpl;
+ if (!realMod.getCodeName().equals(el.getCodeName())) {
+ continue;
+ }
+ String fhost = realMod.getFragmentHost();
+ if (fhost != null && !impl.isFragment()) {
+ mod.setFragmentHost(fhost);
+ Module m = Utilities.toModule(fhost);
+ if (m != null && m.isEnabled()) {
+ impl.setNeedsRestart(Boolean.TRUE);
+ }
+ }
+ }
+ }
+ }
+
private boolean needsRestart (boolean isUpdate, UpdateElementImpl toUpdateImpl, File dest) {
return InstallManager.needsRestart (isUpdate, toUpdateImpl, dest);
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java
index 06f8797..6cbe539 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/OperationContainerImpl.java
@@ -207,6 +207,8 @@
for (OperationInfo<?> i : operations) {
all.addAll(i.getRequiredElements());
}
+ // TODO: fragment modules are somewhat eager: they need to enable with their hosting module. They are not handled now,
+ // so unless they are also eager, they won't be autoincluded.
for (UpdateElement eagerEl : UpdateManagerImpl.getInstance ().getAvailableEagers ()) {
if(eagerEl.getUpdateUnit().isPending() || eagerEl.getUpdateUnit().getAvailableUpdates().isEmpty()) {
continue;
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
index 8c3c440..7c05dd2 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
@@ -557,6 +557,14 @@
return getModuleInstance(uUnit.getCodeName(), null); // XXX
}
+ public static Module toModule(String codeNameBase) {
+ ModuleInfo mi = ModuleCache.getInstance().find(codeNameBase);
+ if (mi instanceof Module) {
+ return (Module)mi;
+ }
+ return null;
+ }
+
public static Module toModule(String codeNameBase, SpecificationVersion specificationVersion) {
return getModuleInstance(codeNameBase, specificationVersion);
}
@@ -604,6 +612,8 @@
Set<Dependency> deps = new HashSet<Dependency> (el.getModuleInfo ().getDependencies ());
Set<ModuleInfo> availableInfos = new HashSet<ModuleInfo> (infos);
+ maybeAddImplicitHostDependency(element, deps);
+
int max_counter = el.getType().equals(UpdateManager.TYPE.KIT_MODULE) ? 2 : 1;
int counter = max_counter;
boolean aggressive = topAggressive && counter > 0;
@@ -618,8 +628,14 @@
UpdateUnit uu = toUpdateUnit(dep.getName());
if (uu != null && uu.getInstalled() != null) {
ModuleUpdateElementImpl em = (ModuleUpdateElementImpl) Trampoline.API.impl(uu.getInstalled());
- if (em.getInstallInfo().getUpdateItemImpl().isFragment()) {
- el.getInstallInfo().getUpdateItemImpl().setNeedsRestart(true);
+ // fragments which are installed, but not enabled yet, and have live host module will cause
+ // restart
+ if (em.getInstallInfo().getUpdateItemImpl().isFragment() && !uu.getInstalled().isEnabled()) {
+ String fh = em.getInstallInfo().getUpdateItemImpl().getFragmentHost();
+ Module m = Utilities.toModule(fh);
+ if (m != null && m.isEnabled()) {
+ el.getInstallInfo().getUpdateItemImpl().setNeedsRestart(true);
+ }
}
}
}
@@ -736,6 +752,7 @@
Set<Dependency> deps = new HashSet<Dependency>(tryUpdated.getDependencies());
Set<ModuleInfo> availableInfos = new HashSet<ModuleInfo>(forInstall);
Set<Dependency> newones;
+ maybeAddImplicitHostDependency(tryUE, deps);
while (!(newones = processDependencies(deps, moreRequested, availableInfos, brokenDependencies, tryUE, aggressive, null, false)).isEmpty()) {
deps = newones;
}
@@ -784,6 +801,20 @@
return moreRequested;
}
+
+ private static boolean maybeAddImplicitHostDependency(UpdateElement el, Set<Dependency> deps) {
+
+ // check fragment, add implicit dependencies
+ UpdateElementImpl elImpl = Trampoline.API.impl(el);
+ UpdateItemImpl uiImpl = elImpl.getInstallInfo().getUpdateItemImpl();
+ if (!uiImpl.isFragment()) {
+ return false;
+ }
+ String fhost = uiImpl.getFragmentHost();
+ Collection<Dependency> hostDep = Dependency.create(Dependency.TYPE_MODULE, fhost);
+ err.fine(hostDep.toString());
+ return deps.addAll(hostDep);
+ }
private static Set<Dependency> processDependencies (final Set<Dependency> original,
Set<UpdateElement> retval,
@@ -814,6 +845,7 @@
availableInfos.add (reqM.getModuleInfo ());
retval.add (req);
res.addAll (reqM.getModuleInfo ().getDependencies ());
+ maybeAddImplicitHostDependency(req, res);
}
}
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java
index 692fb66..d95e1b4 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java
@@ -34,12 +34,12 @@
import java.util.zip.GZIPInputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+import org.netbeans.Module;
import org.netbeans.modules.autoupdate.services.Trampoline;
import org.netbeans.modules.autoupdate.services.UpdateLicenseImpl;
import org.netbeans.modules.autoupdate.services.Utilities;
import org.netbeans.spi.autoupdate.UpdateItem;
import org.netbeans.spi.autoupdate.UpdateLicense;
-import org.openide.util.Exceptions;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
@@ -510,7 +510,7 @@
private URI base;
private String catalogDate;
- private boolean isFragment = false;
+ private String fragmentHost;
private static ModuleDescriptor md = null;
@@ -545,7 +545,7 @@
String autoload = module.getValue (MODULE_ATTR_AUTOLOAD);
String preferred = module.getValue(MODULE_ATTR_IS_PREFERRED_UPDATE);
- needsRestart = isFragment || needsrestart == null || needsrestart.trim ().length () == 0 ? null : Boolean.valueOf (needsrestart);
+ needsRestart = needsrestart == null || needsrestart.trim ().length () == 0 ? null : Boolean.valueOf (needsrestart);
isGlobal = global == null || global.trim ().length () == 0 ? null : Boolean.valueOf (global);
isEager = Boolean.parseBoolean (eager);
isAutoload = Boolean.parseBoolean (autoload);
@@ -561,10 +561,9 @@
public void appendManifest (Attributes manifest) {
specVersion = manifest.getValue (MANIFEST_ATTR_SPECIFICATION_VERSION);
- String fragmentHost = manifest.getValue(MANIFEST_ATTR_FRAGMENT_HOST);
- isFragment = fragmentHost != null && !fragmentHost.isEmpty();
- if (isFragment) {
- needsRestart = true;
+ fragmentHost = manifest.getValue(MANIFEST_ATTR_FRAGMENT_HOST);
+ if (fragmentHost != null && fragmentHost.isEmpty()) {
+ fragmentHost = null;
}
mf = getManifest (manifest);
id = moduleCodeName + '_' + specVersion; // NOI18N
@@ -600,7 +599,9 @@
// read module notification
UpdateItemImpl impl = Trampoline.SPI.impl(res);
((ModuleItem) impl).setModuleNotification (notification);
-
+ if (fragmentHost != null) {
+ ((ModuleItem) impl).setFragmentHost (fragmentHost);
+ }
// clean-up ModuleDescriptor
cleanUp ();
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateInfoParser.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateInfoParser.java
index a09461a..6082f3a 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateInfoParser.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateInfoParser.java
@@ -145,6 +145,7 @@
private static final String MODULE_ATTR_LICENSE = "license";
private static final String MANIFEST_ATTR_SPECIFICATION_VERSION = "OpenIDE-Module-Specification-Version";
+ private static final String MANIFEST_ATTR_FRAGMENT_HOST = "OpenIDE-Module-Fragment-Host";
private static final String L10N_ATTR_LOCALE = "langcode";
private static final String L10N_ATTR_BRANDING = "brandingcode";
@@ -296,6 +297,7 @@
private String author;
private String publishDate;
private String notification;
+ private String fragmentHost;
private Boolean needsRestart;
private Boolean isGlobal;
@@ -342,6 +344,7 @@
public void appendManifest (Attributes manifest) {
specVersion = manifest.getValue (MANIFEST_ATTR_SPECIFICATION_VERSION);
+ fragmentHost = manifest.getValue(MANIFEST_ATTR_FRAGMENT_HOST);
mf = getManifest (manifest);
}
@@ -381,6 +384,7 @@
// read module notification
UpdateItemImpl impl = Trampoline.SPI.impl(res);
((ModuleItem) impl).setModuleNotification (notification);
+ ((ModuleItem) impl).setFragmentHost(fragmentHost);
return res;
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/InstalledModuleItem.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/InstalledModuleItem.java
index 2aa44c5..99e557a 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/InstalledModuleItem.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/InstalledModuleItem.java
@@ -129,7 +129,8 @@
}
@Override
- public boolean isFragment() {
- return info.getAttribute("OpenIDE-Module-Fragment-Host") != null; // NOI18N
+ public String getFragmentHost() {
+ Object o = info.getAttribute("OpenIDE-Module-Fragment-Host"); // NOI18N
+ return o instanceof String ? (String)o : null;
}
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/ModuleItem.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/ModuleItem.java
index a6ee368..fc4f8b2 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/ModuleItem.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/ModuleItem.java
@@ -49,6 +49,8 @@
private boolean isPreferedUpdate;
private String moduleNotification = null;
+ private String fragmentHost;
+
private URL distribution;
private Manifest manifest;
@@ -182,6 +184,14 @@
void setModuleNotification (String notification) {
this.moduleNotification = notification;
}
+
+ public void setFragmentHost(String fhost) {
+ this.fragmentHost = fhost;
+ }
+
+ public String getFragmentHost() {
+ return fragmentHost;
+ }
@Override
public void setUpdateLicenseImpl (UpdateLicenseImpl licenseImpl) {
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
index eb895f0..0f639dd 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
@@ -58,6 +58,10 @@
public abstract void setNeedsRestart(Boolean needsRestart);
public boolean isFragment(){
- return false;
+ return getFragmentHost() != null;
+ }
+
+ public String getFragmentHost() {
+ return null;
}
}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/DefaultTestCase.java b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/DefaultTestCase.java
index 7f0cb75..5d62d1c 100644
--- a/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/DefaultTestCase.java
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/DefaultTestCase.java
@@ -68,6 +68,10 @@
}
}
+ protected InputStream updateCatalogContents() {
+ return TestUtils.class.getResourceAsStream("data/updates.xml");
+ }
+
protected void setUp() throws Exception {
super.setUp();
this.clearWorkDir ();
@@ -76,7 +80,7 @@
catalogFile.createNewFile();
}
catalogURL = org.openide.util.Utilities.toURI(catalogFile).toURL();
- populateCatalog(TestUtils.class.getResourceAsStream("data/updates.xml"));
+ populateCatalog(updateCatalogContents());
TestUtils.setUserDir (getWorkDirPath ());
TestUtils.testInit();
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/org-yourorghere-fragment.nbm b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/org-yourorghere-fragment.nbm
new file mode 100644
index 0000000..267d0eb
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/org-yourorghere-fragment.nbm
Binary files differ
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates-bad-fragment.xml b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates-bad-fragment.xml
new file mode 100644
index 0000000..0687b72
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates-bad-fragment.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE module_updates PUBLIC "-//NetBeans//DTD Autoupdate Catalog 2.6//EN" "http://www.netbeans.org/dtds/autoupdate-catalog-2_6.dtd">
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<module_updates timestamp="10/28/20/17/11/2017">
+
+ <module codenamebase="org.yourorghere.brokendepending" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-brokendepending.nbm" downloadsize="3208" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.brokendepending" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Module-Dependencies="org.yourorghere.unreachable > 1.0" OpenIDE-Module-Name="brokendepending" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.depending" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-depending.nbm" downloadsize="3186" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.depending" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Module-Dependencies="org.yourorghere.engine > 1.0, org.yourorghere.independent > 1.0" OpenIDE-Module-Name="depending" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.depending_on_new_one_engine" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-depending_on_new_one_engine.nbm" downloadsize="3263" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.depending_on_new_one_engine" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Module-Dependencies="org.yourorghere.engine > 1.0" OpenIDE-Module-Name="depending_on_new_one_engine" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.engine" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-engine.nbm" downloadsize="3136" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.engine" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Module-Dependencies="org.yourorghere.independent > 1.0" OpenIDE-Module-Name="engine" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.engine" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-engine-1-1.nbm" downloadsize="3136" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.engine" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Module-Dependencies="org.yourorghere.independent > 1.0" OpenIDE-Module-Name="engine" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.1"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.independent" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-independent.nbm" downloadsize="3128" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.independent" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Name="independent" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.refresh_providers_test" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-refresh_providers_test.nbm" downloadsize="3206" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="true" releasedate="2017/11/17">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.refresh_providers_test" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Name="refresh_providers_test" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="com.example.testmodule.cluster" distribution="nbresloc:/org/netbeans/api/autoupdate/data/com-example-testmodule-cluster.nbm" downloadsize="0" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2017/11/17" targetcluster="test">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="com.example.testmodule.cluster" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Name="testmodule_cluster" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+
+ </module>
+
+ <module codenamebase="org.yourorghere.fragment" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-fragment.nbm" downloadsize="0" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2018/10/01">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.fragment" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Name="fragment" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+ </module>
+
+<license name="AD9FBBC9">[NO LICENSE SPECIFIED]
+</license>
+</module_updates>
+
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates.xml b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates.xml
index f9c9fac..fe4783d 100644
--- a/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates.xml
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/api/autoupdate/data/updates.xml
@@ -63,6 +63,10 @@
</module>
+ <module codenamebase="org.yourorghere.fragment" distribution="nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-fragment.nbm" downloadsize="0" homepage="" license="AD9FBBC9" moduleauthor="Steffen Dietz" needsrestart="false" releasedate="2018/10/01">
+ <manifest AutoUpdate-Show-In-Client="true" OpenIDE-Module="org.yourorghere.fragment" OpenIDE-Module-Implementation-Version="171117" OpenIDE-Module-Java-Dependencies="Java > 1.7" OpenIDE-Module-Fragment-Host="org.yourorghere.engine" OpenIDE-Module-Name="fragment" OpenIDE-Module-Requires="org.openide.modules.ModuleFormat1" OpenIDE-Module-Specification-Version="1.0"/>
+ </module>
+
<license name="AD9FBBC9">[NO LICENSE SPECIFIED]
</license>
</module_updates>
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentDisabledNoRestartTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentDisabledNoRestartTest.java
new file mode 100644
index 0000000..8c83863
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentDisabledNoRestartTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.netbeans.modules.autoupdate.services;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicReference;
+import org.netbeans.api.autoupdate.OperationContainer;
+import org.netbeans.api.autoupdate.OperationSupport;
+import org.netbeans.api.autoupdate.UpdateUnit;
+
+/**
+ * Checks that a fragment installed on top of already enabled module will
+ * cause a restart.
+ *
+ * @author sdedic
+ */
+public class FragmentDisabledNoRestartTest extends FragmentModuleTestBase {
+
+ public FragmentDisabledNoRestartTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ public void testSelf() throws Exception {
+ UpdateUnit hostUnit = UpdateManagerImpl.getInstance().getUpdateUnit("org.yourorghere.engine");
+ installModule(hostUnit, null);
+
+ OperationContainer<OperationSupport> container = OperationContainer.createForDirectDisable ();
+ container.add(hostUnit.getInstalled());
+ OperationSupport support = container.getSupport ();
+ support.doOperation (null);
+
+ UpdateUnit toInstall = UpdateManagerImpl.getInstance().getUpdateUnit(moduleCodeNameBaseForTest());
+
+ AtomicReference<OperationSupport.Restarter> restarter = new AtomicReference<>();
+ installModuleWithRestart(toInstall, null, restarter);
+
+ assertNull ("Module must not cause restart, host is disabled", restarter.get());
+ }
+
+}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentIEnabledRestartTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentIEnabledRestartTest.java
new file mode 100644
index 0000000..55cd3b4
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentIEnabledRestartTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.netbeans.modules.autoupdate.services;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicReference;
+import org.netbeans.api.autoupdate.OperationSupport;
+import org.netbeans.api.autoupdate.UpdateUnit;
+
+/**
+ * Checks that a fragment installed on top of already enabled module will
+ * cause a restart.
+ *
+ * @author sdedic
+ */
+public class FragmentIEnabledRestartTest extends FragmentModuleTestBase {
+
+ public FragmentIEnabledRestartTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ public void testSelf() throws Exception {
+ installModule(UpdateManagerImpl.getInstance().getUpdateUnit("org.yourorghere.engine"), null);
+
+ UpdateUnit toInstall = UpdateManagerImpl.getInstance().getUpdateUnit(moduleCodeNameBaseForTest());
+
+ AtomicReference<OperationSupport.Restarter> restarter = new AtomicReference<>();
+ installModuleWithRestart(toInstall, null, restarter);
+ assertNotNull(restarter.get());
+ }
+
+}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentInstallHostModuleTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentInstallHostModuleTest.java
new file mode 100644
index 0000000..d104697
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentInstallHostModuleTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.netbeans.modules.autoupdate.services;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicReference;
+import org.netbeans.api.autoupdate.OperationSupport;
+import org.netbeans.api.autoupdate.UpdateUnit;
+import org.openide.modules.ModuleInfo;
+
+/**
+ * Checks that a fragment module will force install its host as a dependency
+ * even though the dependency is not declared
+ *
+ * @author sdedic
+ */
+public class FragmentInstallHostModuleTest extends FragmentModuleTestBase {
+
+ public FragmentInstallHostModuleTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ public void testSelf() throws Exception {
+ UpdateUnit toInstall = UpdateManagerImpl.getInstance().getUpdateUnit(moduleCodeNameBaseForTest());
+ AtomicReference<OperationSupport.Restarter> restarter = new AtomicReference<>();
+ installModuleWithRestart(toInstall, null, restarter);
+ assertNull("Fragment host will be newly installed, no restart is needed", restarter.get());
+
+ ModuleInfo transitiveMod = Utilities.toModule("org.yourorghere.independent");
+ ModuleInfo hostMod = Utilities.toModule("org.yourorghere.engine");
+
+ assertNotNull(transitiveMod);
+ assertNotNull(hostMod);
+ }
+
+}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentMissingInCatalogRestartTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentMissingInCatalogRestartTest.java
new file mode 100644
index 0000000..c685acf
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentMissingInCatalogRestartTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.netbeans.modules.autoupdate.services;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicReference;
+import org.netbeans.api.autoupdate.OperationSupport;
+import org.netbeans.api.autoupdate.TestUtils;
+import org.netbeans.api.autoupdate.UpdateUnit;
+
+/**
+ * Checks that a fragment on top of enabled module causes restart although
+ * the catalog XML does not list its Fragment-Host: attribute.
+ *
+ * @author sdedic
+ */
+public class FragmentMissingInCatalogRestartTest extends FragmentModuleTestBase {
+
+ public FragmentMissingInCatalogRestartTest(String testName) {
+ super(testName);
+ }
+
+ protected InputStream updateCatalogContents() {
+ return TestUtils.class.getResourceAsStream("data/updates-bad-fragment.xml");
+ }
+
+ @Override
+ public void testSelf() throws Exception {
+ installModule(UpdateManagerImpl.getInstance().getUpdateUnit("org.yourorghere.engine"), null);
+
+ UpdateUnit toInstall = UpdateManagerImpl.getInstance().getUpdateUnit(moduleCodeNameBaseForTest());
+
+ AtomicReference<OperationSupport.Restarter> restarter = new AtomicReference<>();
+ installModuleWithRestart(toInstall, null, restarter);
+ assertNotNull(restarter.get());
+ }
+
+}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentModuleTestBase.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentModuleTestBase.java
new file mode 100644
index 0000000..e82c529
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/FragmentModuleTestBase.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.netbeans.modules.autoupdate.services;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.fail;
+import org.netbeans.api.autoupdate.InstallSupport;
+import org.netbeans.api.autoupdate.OperationContainer;
+import org.netbeans.api.autoupdate.OperationException;
+import org.netbeans.api.autoupdate.OperationSupport;
+import org.netbeans.api.autoupdate.UpdateElement;
+import org.netbeans.api.autoupdate.UpdateUnit;
+import org.netbeans.modules.autoupdate.updateprovider.InstalledModuleProvider;
+import org.openide.modules.ModuleInfo;
+
+/**
+ *
+ * @author sdedic
+ */
+public abstract class FragmentModuleTestBase extends OperationsTestImpl {
+
+ public FragmentModuleTestBase(String testName) {
+ super(testName);
+ }
+
+ protected String moduleCodeNameBaseForTest() {
+ return "org.yourorghere.fragment";//NOI18N
+ }
+
+ protected Map<String, ModuleInfo> getModuleInfos () {
+ return InstalledModuleProvider.getInstalledModules ();
+ }
+
+ protected UpdateElement installModuleWithRestart(UpdateUnit toInstall, UpdateElement installElement, AtomicReference<OperationSupport.Restarter> restarterOut) throws Exception {
+ installElement = (installElement != null) ? installElement : toInstall.getAvailableUpdates ().get (0);
+ assertNull (getModuleInfos ().get (toInstall.getCodeName ()));
+ assertNotNull (toInstall);
+
+ OperationSupport.Restarter r = null;
+
+ OperationContainer<InstallSupport> container = OperationContainer.createForInstall ();
+ OperationContainer.OperationInfo<InstallSupport> info = container.add (installElement);
+ assertNotNull (info);
+ container.add (info.getRequiredElements ());
+
+ InstallSupport support = container.getSupport ();
+ assertNotNull (support);
+
+ InstallSupport.Validator v = support.doDownload (null, false);
+ assertNotNull (v);
+ InstallSupport.Installer i = support.doValidate (v, null);
+ assertNotNull (i);
+ assertNull (support.getCertificate (i, installElement)); // Test NBM is not signed nor certificate
+ assertFalse (support.isTrusted (i, installElement));
+ assertFalse (support.isSigned (i, installElement));
+ 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 ());
+ }
+ }
+ if (restarterOut != null) {
+ restarterOut.set(r);
+ }
+ return installElement;
+ }
+
+
+}