Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public Resource setRequiredDependencies(List<RequiredDependency> requiredDepende
@Override
public void accept(ElementContext context, Visitor visitor) {
visitor.visit(context, this);
if (majorSchemaVersion > 3) {
if (majorSchemaVersion > 2) {
for (RequiredDependency requiredDependency : requiredDependencies) {
visitor.visit(new ElementContext(this, context), requiredDependency);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.cloudfoundry.multiapps.mta.resolvers;

import java.util.List;

public class CustomParameterContainer {

private final String parameterOwner;
private final List<String> customParameters;

private final String prefixedName;

public CustomParameterContainer(String parameterOwner, List<String> parameters, String prefixedName) {
this.parameterOwner = parameterOwner;
this.customParameters = parameters;
this.prefixedName = prefixedName;
}

public String getParameterOwner() {
return parameterOwner;
}

public String getPrefixedName() {
return prefixedName;
}

public List<String> getParameters() {
return customParameters;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.cloudfoundry.multiapps.mta.resolvers;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.cloudfoundry.multiapps.mta.helpers.SimplePropertyVisitor;
import org.cloudfoundry.multiapps.mta.helpers.VisitableObject;
import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor;
import org.cloudfoundry.multiapps.mta.model.ElementContext;
import org.cloudfoundry.multiapps.mta.model.Hook;
import org.cloudfoundry.multiapps.mta.model.Module;
import org.cloudfoundry.multiapps.mta.model.ParametersContainer;
import org.cloudfoundry.multiapps.mta.model.ProvidedDependency;
import org.cloudfoundry.multiapps.mta.model.RequiredDependency;
import org.cloudfoundry.multiapps.mta.model.Resource;
import org.cloudfoundry.multiapps.mta.model.Visitor;

public abstract class ParameterChecker extends Visitor implements SimplePropertyVisitor {
private List<CustomParameterContainer> unsupportedParameters;

private Set<String> predefinedParametersForContainer;

protected abstract Set<String> getModuleParametersToMatch();

protected abstract Set<String> getModuleHookParametersToMatch();

protected abstract Set<String> getResourceParametersToMatch();

protected abstract Set<String> getGlobalParametersToMatch();

protected abstract Set<String> getDependencyParametersToMatch();

public List<CustomParameterContainer> getCustomParameters(DeploymentDescriptor descriptor) {
this.unsupportedParameters = new ArrayList<>();
descriptor.accept(this);
return this.unsupportedParameters;
}

@Override
public void visit(ElementContext context, DeploymentDescriptor descriptor) {
matchAndStore(null, getGlobalParametersToMatch(), descriptor, null);
}

@Override
public void visit(ElementContext context, Module module) {
matchAndStore(module.getName(), getModuleParametersToMatch(), module, context.getPrefixedName());
}

@Override
public void visit(ElementContext context, ProvidedDependency providedDependency) {
matchAndStore(providedDependency.getName(), getDependencyParametersToMatch(), providedDependency, context.getPrefixedName());
}

@Override
public void visit(ElementContext context, RequiredDependency requiredDependency) {
matchAndStore(requiredDependency.getName(), getDependencyParametersToMatch(), requiredDependency, context.getPrefixedName());
}

@Override
public void visit(ElementContext context, Resource resource) {
matchAndStore(resource.getName(), getResourceParametersToMatch(), resource, context.getPrefixedName());
}

@Override
public void visit(ElementContext context, Hook hook) {
matchAndStore(hook.getName(), getModuleHookParametersToMatch(), hook, context.getPrefixedName());
}

private void matchAndStore(String name, Set<String> parametersToMatch, ParametersContainer parametersContainer, String prefixedName) {
this.predefinedParametersForContainer = parametersToMatch;
List<String> unmatched = findMatchesInParameters(parametersContainer);
if (!unmatched.isEmpty()) {
unsupportedParameters.add(new CustomParameterContainer(name, unmatched, prefixedName));
}
}

private List<String> findMatchesInParameters(ParametersContainer parametersContainer) {
List<String> matchedKeys = (List<String>) findMatchesInKeySet(parametersContainer.getParameters()
.keySet());
return matchedKeys.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

private Object findMatchesInKeySet(Set<String> keys) {
return new VisitableObject(keys).accept(this);
}

@Override
public Object visit(String key, String value) {
return parameterKeyMatches(value);
}

private String parameterKeyMatches(String valueToMatch) {
if (predefinedParametersForContainer != null && !predefinedParametersForContainer.contains(valueToMatch)) {
return valueToMatch;
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.cloudfoundry.multiapps.mta.resolvers;

import java.util.List;

public class ReferenceContainer {

private final String referenceOwner;
private final List<Reference> references;

public ReferenceContainer(String referenceOwner, List<Reference> references) {
this.referenceOwner = referenceOwner;
this.references = references;
}

public String getReferenceOwner() {
return referenceOwner;
}

public List<Reference> getReferences() {
return references;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
public enum ReferencePattern implements ValueMatcher {

PLACEHOLDER("(?<!\\\\)\\$\\{(.+?)\\}", "${%s}"), SHORT("(?<!\\\\)~\\{(.+?)\\}", "~{%s}"), FULLY_QUALIFIED("(?<!\\\\)~\\{(.+?)/(.+?)\\}",
"~{%s/%s}");
"~{%s/%s}");

private String pattern;
private String patternFormat;

private final Pattern compiledPattern;

ReferencePattern(String pattern, String patternFormat) {
this.pattern = pattern;
this.patternFormat = patternFormat;
this.compiledPattern = Pattern.compile(pattern);
}

protected boolean hasPropertySetSegment() {
Expand All @@ -28,8 +31,7 @@ protected boolean hasDepthOfReference() {

@Override
public List<Reference> match(String line) {
Matcher matcher = Pattern.compile(this.pattern)
.matcher(line);
Matcher matcher = this.compiledPattern.matcher(line);
List<Reference> references = new ArrayList<>();
while (matcher.find()) {
String matchedValue = matcher.group(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package org.cloudfoundry.multiapps.mta.resolvers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.cloudfoundry.multiapps.mta.helpers.SimplePropertyVisitor;
import org.cloudfoundry.multiapps.mta.helpers.VisitableObject;
import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor;
import org.cloudfoundry.multiapps.mta.model.ElementContext;
import org.cloudfoundry.multiapps.mta.model.Hook;
import org.cloudfoundry.multiapps.mta.model.Module;
import org.cloudfoundry.multiapps.mta.model.ProvidedDependency;
import org.cloudfoundry.multiapps.mta.model.RequiredDependency;
import org.cloudfoundry.multiapps.mta.model.Resource;
import org.cloudfoundry.multiapps.mta.model.Visitor;

public class ReferencesFinder extends Visitor implements SimplePropertyVisitor {

private List<ReferenceContainer> foundReferences;

public List<ReferenceContainer> getAllReferences(DeploymentDescriptor descriptor) {
this.foundReferences = new ArrayList<>();
descriptor.accept(this);
return this.foundReferences;
}

@Override
public void visit(ElementContext context, DeploymentDescriptor descriptor) {
collectReferences(null, descriptor.getParameters());
}

@Override
public void visit(ElementContext context, Module module) {
collectReferences(module.getName(), module.getParameters(), module.getProperties());
}

@Override
public void visit(ElementContext context, ProvidedDependency providedDependency) {
collectReferences(context.getPrefixedName(), providedDependency.getParameters(), providedDependency.getProperties());
}

@Override
public void visit(ElementContext context, RequiredDependency requiredDependency) {
collectReferences(context.getPrefixedName(), requiredDependency.getParameters(), requiredDependency.getProperties());
}

@Override
public void visit(ElementContext context, Resource resource) {
collectReferences(resource.getName(), resource.getParameters(), resource.getProperties());
}

@Override
public void visit(ElementContext context, Hook hook) {
collectReferences(context.getPrefixedName(), hook.getParameters());
}

private void collectReferences(String name, Map<String, Object>... maps) {
List<Reference> merged = Arrays.stream(maps)
.flatMap(map -> findReferencesInParameters(map).stream())
.collect(Collectors.toList());

if (!merged.isEmpty()) {
foundReferences.add(new ReferenceContainer(name, merged));
}
}

private List<Reference> findReferencesInParameters(Map<String, Object> map) {
if (map == null) {
return Collections.emptyList();
}

List<Reference> matchedKeys = (List<Reference>) findReferencesInList(new ArrayList(map.values()));
return matchedKeys.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

private Object findReferencesInList(List<String> keys) {
Object result = new VisitableObject(keys).accept(this);
return extractReferences(result);
}

private List<Reference> extractReferences(Object input) {
if (input == null) {
return Collections.emptyList();
}

if (input instanceof Reference) {
return List.of((Reference) input);
}

if (input instanceof List<?>) {
return ((List<?>) input).stream()
.flatMap(item -> extractReferences(item).stream())
.collect(Collectors.toList());
}

if (input instanceof Map<?, ?>) {
return ((Map<?, ?>) input).values()
.stream()
.flatMap(value -> extractReferences(value).stream())
.collect(Collectors.toList());
}

return Collections.emptyList();
}

@Override
public Object visit(String key, String value) {
return referencePatternMatches(value);
}

private List<Reference> referencePatternMatches(String valueToMatch) {
//Not using ReferencePattern.values() in order to have the more specific FULLY_QUALIFIED pattern before SHORT
for (ReferencePattern pattern : List.of(
ReferencePattern.PLACEHOLDER,
ReferencePattern.FULLY_QUALIFIED,
ReferencePattern.SHORT)) {

List<Reference> references = pattern.match(valueToMatch);
if (!references.isEmpty()) {
return references;
}
}
return null;
}

}
Loading