Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue #95, Introduce a rule for a layer to express that it requires some user selected add-ons #96

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions core/src/main/java/org/wildfly/glow/AddOnSelectionMode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.wildfly.glow;

/**
* A layer expects add-ons from a given family to be explicitly selected.
* @author jdenise
*/
public class AddOnSelectionMode {
private final Layer targetLayer;
private final String family;
private final int maxNumber;

/**
* AddOnSelectionMode constructor.
* @param targetLayer The layer that contains the rule.
* @param family The family that the targetlayer expect add-ons from.
* @param maxNumber The max number of expected add-ons. Can be 1 or -1 (unbounded).
*/
public AddOnSelectionMode(Layer targetLayer, String family, int maxNumber) throws Exception {
this.targetLayer = targetLayer;
this.family = family;
if (maxNumber != 1 && maxNumber != -1) {
throw new Exception("The max number of add-on selection rule can only be 1 or -1 (unbounded)");
}
this.maxNumber = maxNumber;
}

/**
* Is the expected number of add-ons unbounded.
* @return true if the number of expected add-ons is unbounded.
*/
public boolean isUnBounded() {
return maxNumber < 0;
}
/**
* Is the expected number of add-ons exactly one.
* @return true if the number of expected add-ons is one.
*/
public boolean isExactlyOne() {
return maxNumber == 1;
}

/**
* @return the maxNumber of add-ons a user can select. -1 means unbounded.
*/
public boolean isOne() {
return maxNumber == 1;
}

/**
* @return the targetLayer
*/
public Layer getTargetLayer() {
return targetLayer;
}

/**
* @return the family
*/
public String getFamily() {
return family;
}
}
94 changes: 93 additions & 1 deletion core/src/main/java/org/wildfly/glow/GlowSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ public ScanResults scan() throws Exception {
}
// Fix addOns
Map<AddOn, String> disabledAddOns = new TreeMap<>();
fixAddOns(errorSession, layers, mapping, allEnabledAddOns, possibleAddOns, disabledAddOns, arguments);
fixAddOns(errorSession, layers, decorators, mapping, allEnabledAddOns, possibleAddOns, disabledAddOns, arguments);
// END ADD-ON

// DECORATORS CLEANUP
Expand Down Expand Up @@ -819,6 +819,7 @@ public void close() throws Exception {

private static void fixAddOns(ErrorIdentificationSession errorSession,
Set<Layer> layers,
Set<Layer> decorators,
LayerMapping mapping,
Set<AddOn> allEnabledAddOns,
Set<AddOn> possibleAddOns,
Expand All @@ -828,6 +829,97 @@ private static void fixAddOns(ErrorIdentificationSession errorSession,
Set<String> familyOfAddOnsComplete = new TreeSet<>();
Map<String, Set<AddOn>> membersInFamily = new HashMap<>();
Map<String, Set<AddOn>> defaultMembersInFamily = new HashMap<>();
// Handle inclusion mode
Map<String, Set<AddOn>> selectedAddOnsForFamily = new HashMap<>();
Map<String, Set<AddOn>> candidatesForFamily = new HashMap<>();
Set<AddOn> toBeRemoved = new HashSet<>();
for(AddOn ao : allEnabledAddOns) {
AddOnSelectionMode mode = mapping.getFamilySelectionMode().get(ao.getFamily());
// We have a selection mode for this family
// A selection means that such add-ons must be included by the user and not automatically discovered.
if (mode != null) {
Set<AddOn> selectedAddOns = selectedAddOnsForFamily.computeIfAbsent(ao.getFamily(), s -> new HashSet<>());
if (!arguments.getUserEnabledAddOns().contains(ao.getName())) {
toBeRemoved.add(ao);
for(Layer l : ao.getLayers()) {
for(Layer dep : l.getDependencies()) {
AddOn addOn = dep.getAddOn();
if (addOn != null) {
if(!arguments.getUserEnabledAddOns().contains(addOn.getName())) {
toBeRemoved.add(addOn);
}
}
}
}
Set<AddOn> candidates = candidatesForFamily.computeIfAbsent(ao.getFamily(), s -> new HashSet<>());
candidates.add(ao);
} else {
selectedAddOns.add(ao);
}
}
}
// At this point we know the addOn that have been included by the user
// and the one that should be removed because not explicitly included.
for(String k : selectedAddOnsForFamily.keySet()) {
// Empty selection...
if (selectedAddOnsForFamily.get(k).isEmpty()) {
Set<AddOn> candidates = candidatesForFamily.get(k);
// None have been selected but we found candidates in the set of discovered ones
// Or we remove them and create an error, asking user to select somes.
if (candidates != null) {
if(candidates.size() == 1) {
// Simply keep it, we have a match
// The add-on will be not removed.
toBeRemoved.remove(candidates.iterator().next());
} else {
AddOnSelectionMode mode = mapping.getFamilySelectionMode().get(k);
StringBuilder errorBuilder = new StringBuilder();
if (mode.isExactlyOne()) {
errorBuilder.append("one ");
} else {
errorBuilder.append("At least one ");
}
errorBuilder.append("add-on of the " + k + " family is expected by the " +
mode.getTargetLayer() + " layer\n"
+ " To correct this error, enable one of the following add-ons:\n");
Iterator<AddOn> it = candidates.iterator();
while(it.hasNext()) {
AddOn ao = it.next();
errorBuilder.append(" - ").append(ao.getName());
if(it.hasNext()) {
errorBuilder.append("\n");
}
}
IdentifiedError error = new IdentifiedError("missing-add-on", errorBuilder.toString(), ERROR);
errorSession.addError(error);
}
}
} else {
// We have a selection of add-ons, is it in the boundaries of the max number?
AddOnSelectionMode mode = mapping.getFamilySelectionMode().get(k);
if (!mode.isUnBounded() && selectedAddOnsForFamily.get(k).size() > 1) {
StringBuilder errorBuilder = new StringBuilder();
errorBuilder.append("Only one add-on of the " + k + " family is expected by the "
+ mode.getTargetLayer() + " layer\n"
+ " To correct this error, remove some of the following add-ons:\n");
Iterator<AddOn> it = selectedAddOnsForFamily.get(k).iterator();
while (it.hasNext()) {
AddOn ao = it.next();
errorBuilder.append(" - ").append(ao.getName());
if (it.hasNext()) {
errorBuilder.append("\n");
}
}
IdentifiedError error = new IdentifiedError("too-many-add-on", errorBuilder.toString(), ERROR);
errorSession.addError(error);
}
}
}
for(AddOn ao : toBeRemoved) {
allEnabledAddOns.remove(ao);
layers.removeAll(ao.getLayers());
decorators.removeAll(ao.getLayers());
}
for (AddOn addOn : allEnabledAddOns) {
if (addOn.isDefault()) {
Set<AddOn> members = defaultMembersInFamily.get(addOn.getFamily());
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/org/wildfly/glow/LayerMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public enum RULE {

private final Map<Layer, String> noConfigurationConditions = new HashMap<>();
private final Map<Layer, String> hiddenConditions = new HashMap<>();
private final Map<String, AddOnSelectionMode> familySelectionMode = new HashMap<>();
/**
* @return the constantPoolClassInfos
*/
Expand All @@ -85,6 +86,13 @@ public Map<String, Layer> getActiveProfilesLayers() {
return activeProfilesLayers;
}

/**
* @return the selectionModes
*/
public Map<String, AddOnSelectionMode> getFamilySelectionMode() {
return familySelectionMode;
}

/**
* @return the allProfilesLayers
*/
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/wildfly/glow/LayerMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public abstract class LayerMetadata {
public static final String CLASS = PREFIX + "class";
public static final String CONFIGURATION = PREFIX + "configuration";
public static final String EXPECT_ADD_ON_FAMILY = PREFIX + "expect-add-on-family";
public static final String SELECT_ADD_ON_FAMILY = PREFIX + "select-add-on-family-";
public static final String EXPECTED_FILE = PREFIX + "expected-file";
public static final String HIDDEN_IF = PREFIX + "hidden-if";
public static final String INCLUSION_MODE = PREFIX + "inclusion-mode";
Expand Down Expand Up @@ -72,6 +73,7 @@ public abstract class LayerMetadata {
RULES_WITH_SUFFIX.add(PROFILE);
RULES_WITH_SUFFIX.add(PROPERTIES_FILE_MATCH);
RULES_WITH_SUFFIX.add(XML_PATH);
RULES_WITH_SUFFIX.add(SELECT_ADD_ON_FAMILY);

CONDITION_RULES.add(HIDDEN_IF);
CONDITION_RULES.add(NO_CONFIGURATION_IF);
Expand Down
14 changes: 13 additions & 1 deletion core/src/main/java/org/wildfly/glow/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public static boolean isPattern(String s) {
return s.contains("*");
}

public static LayerMapping buildMapping(Map<String, Layer> layers, Set<String> profiles) {
public static LayerMapping buildMapping(Map<String, Layer> layers, Set<String> profiles) throws Exception {
LayerMapping mapping = new LayerMapping();
for (Layer l : layers.values()) {
for (String k : l.getProperties().keySet()) {
Expand Down Expand Up @@ -455,6 +455,18 @@ public static LayerMapping buildMapping(Map<String, Layer> layers, Set<String> p
l.setExpectFamily(l.getProperties().get(k));
continue;
}
if (k.startsWith(LayerMetadata.SELECT_ADD_ON_FAMILY)) {
int i = LayerMetadata.SELECT_ADD_ON_FAMILY.length();
String family = k.substring(i);
AddOnSelectionMode mode = mapping.getFamilySelectionMode().get(family);
if (mode != null) {
throw new Exception("More than one layer defines a selection mode for the family " +
family + " : " + mode.getTargetLayer().getName() + " and " + l.getName());
}
mode = new AddOnSelectionMode(l, family, Integer.parseInt(l.getProperties().get(k)));
mapping.getFamilySelectionMode().put(family, mode);
continue;
}
if (LayerMetadata.ADD_ON.equals(k)) {
String familyAndName = l.getProperties().get(k);
String[] split = familyAndName.split(",");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
~ Copyright The WildFly Authors
~ SPDX-License-Identifier: Apache-2.0
-->

<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="f1-add-on">
<props>
<prop name="org.wildfly.rule.inclusion-mode" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on-depends-on" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on" value="f1,add-on1"/>
<prop name="org.wildfly.rule.add-on-description" value="F1 family add-on1"/>
</props>
<dependencies>
<layer name="select-family-consumer"/>
</dependencies>
</layer-spec>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
~ Copyright The WildFly Authors
~ SPDX-License-Identifier: Apache-2.0
-->

<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="f1-add-on2">
<props>
<prop name="org.wildfly.rule.inclusion-mode" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on-depends-on" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on" value="f1,add-on2"/>
<prop name="org.wildfly.rule.add-on-description" value="F1 family add-on2"/>
</props>
<dependencies>
<layer name="select-family-consumer"/>
</dependencies>
</layer-spec>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
~ Copyright The WildFly Authors
~ SPDX-License-Identifier: Apache-2.0
-->

<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="f2-add-on">
<props>
<prop name="org.wildfly.rule.inclusion-mode" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on-depends-on" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on" value="f2,f2-add-on"/>
<prop name="org.wildfly.rule.add-on-description" value="F2 family add-on1"/>
</props>
<dependencies>
<layer name="select-only-one-family-consumer"/>
</dependencies>
</layer-spec>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
~ Copyright The WildFly Authors
~ SPDX-License-Identifier: Apache-2.0
-->

<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="f2-add-on2">
<props>
<prop name="org.wildfly.rule.inclusion-mode" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on-depends-on" value="all-dependencies"/>
<prop name="org.wildfly.rule.add-on" value="f2,f2-add-on2"/>
<prop name="org.wildfly.rule.add-on-description" value="F2 family add-on2"/>
</props>
<dependencies>
<layer name="select-only-one-family-consumer"/>
</dependencies>
</layer-spec>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!--
~ Copyright The WildFly Authors
~ SPDX-License-Identifier: Apache-2.0
-->

<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="select-family-consumer">
<props>
<prop name="org.wildfly.rule.select-add-on-family-f1" value="-1"/>
</props>
</layer-spec>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!--
~ Copyright The WildFly Authors
~ SPDX-License-Identifier: Apache-2.0
-->

<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="select-only-one-family-consumer">
<props>
<prop name="org.wildfly.rule.select-add-on-family-f2" value="1"/>
</props>
</layer-spec>
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ protected static String createXmlElementWithContent(String content, String... pa
return sb.toString();
}

protected void manualCheck() {
checkMethodCalled = true;
}
protected Set<String> checkLayersForArchive(Path archivePath, String...expectedLayers) {
return checkLayersForArchive(archivePath, null, expectedLayers);
}
Expand Down
Loading
Loading