![JAR search and dependency download from the Maven repository](/logo.png)
io.syndesis.project.converter.DefaultProjectGenerator Maven / Gradle / Ivy
/**
* Copyright (C) 2016 Red Hat, Inc.
*
* Licensed 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 io.syndesis.project.converter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import io.syndesis.connector.catalog.ConnectorCatalog;
import io.syndesis.core.MavenProperties;
import io.syndesis.core.Names;
import io.syndesis.integration.model.Flow;
import io.syndesis.integration.model.SyndesisHelpers;
import io.syndesis.integration.model.SyndesisModel;
import io.syndesis.integration.model.steps.Endpoint;
import io.syndesis.integration.support.Strings;
import io.syndesis.model.integration.Integration;
import io.syndesis.model.integration.Step;
import io.syndesis.project.converter.ProjectGeneratorProperties.Templates;
import io.syndesis.project.converter.visitor.GeneratorContext;
import io.syndesis.project.converter.visitor.StepVisitor;
import io.syndesis.project.converter.visitor.StepVisitorContext;
import io.syndesis.project.converter.visitor.StepVisitorFactory;
import io.syndesis.project.converter.visitor.StepVisitorFactoryRegistry;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DefaultProjectGenerator implements ProjectGenerator {
private static final ObjectMapper YAML_OBJECT_MAPPER = SyndesisHelpers.createObjectMapper();
private final MustacheFactory mf = new DefaultMustacheFactory();
/*
Not required for the moment, needed for local forking of a maven process
private Mustache connectorPomMustache = mf.compile(
new InputStreamReader(getClass().getResourceAsStream("templates/connector/pom.xml.mustache")),
"pom.xml"
);
*/
private final ConnectorCatalog connectorCatalog;
private final ProjectGeneratorProperties generatorProperties;
private final StepVisitorFactoryRegistry registry;
private final Mustache applicationJavaMustache;
private final Mustache applicationPropertiesMustache;
private final Mustache pomMustache;
private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectGenerator.class);
public DefaultProjectGenerator(ConnectorCatalog connectorCatalog, ProjectGeneratorProperties generatorProperties, StepVisitorFactoryRegistry registry) throws IOException {
this.connectorCatalog = connectorCatalog;
this.generatorProperties = generatorProperties;
this.registry = registry;
this.applicationJavaMustache = compile(generatorProperties, "Application.java.mustache", "Application.java");
this.applicationPropertiesMustache = compile(generatorProperties, "application.properties.mustache", "application.properties");
this.pomMustache = compile(generatorProperties, "pom.xml.mustache", "pom.xml");
}
private Mustache compile(ProjectGeneratorProperties generatorProperties, String template, String name) throws IOException {
String overridePath = generatorProperties.getTemplates().getOverridePath();
URL resource = null;
if (!Strings.isEmpty(overridePath)) {
resource = getClass().getResource("templates/" + overridePath + "/" + template);
}
if (resource == null) {
resource = getClass().getResource("templates/" + template);
}
if (resource == null) {
throw new IllegalArgumentException(
String.format("Unable to find te required template (overridePath=%s, template=%s)"
, overridePath
, template
)
);
}
try (InputStream stream = resource.openStream()) {
return mf.compile(new InputStreamReader(stream, UTF_8), name);
}
}
@Override
public InputStream generate(GenerateProjectRequest request) throws IOException {
Integration integration = request.getIntegration();
for (Step step : integration.getSteps()) {
LOG.debug("Integration [{}]: Adding step {} ",
Names.sanitize(integration.getName()),
step.getId().orElse(""));
step.getAction().ifPresent(action -> connectorCatalog.addConnector(action.getCamelConnectorGAV()));
}
return createTarInputStream(request);
}
private void addAdditionalResources(TarArchiveOutputStream tos) throws IOException {
for (Templates.Resource additionalResource : generatorProperties.getTemplates().getAdditionalResources()) {
String overridePath = generatorProperties.getTemplates().getOverridePath();
URL resource = null;
if (!Strings.isEmpty(overridePath)) {
resource = getClass().getResource("templates/" + overridePath + "/" + additionalResource.getSource());
}
if (resource == null) {
resource = getClass().getResource("templates/" + additionalResource.getSource());
}
if (resource == null) {
throw new IllegalArgumentException(
String.format("Unable to find te required additional resource (overridePath=%s, source=%s)"
, overridePath
, additionalResource.getSource()
)
);
}
try {
addTarEntry(tos, additionalResource.getDestination(), Files.readAllBytes(Paths.get(resource.toURI())));
} catch (URISyntaxException e) {
throw new IOException(e);
}
}
}
private InputStream createTarInputStream(GenerateProjectRequest request) throws IOException {
PipedInputStream is = new PipedInputStream();
ExecutorService executor = Executors.newSingleThreadExecutor();
PipedOutputStream os = new PipedOutputStream(is);
executor.submit(generateAddProjectTarEntries(request, os));
return is;
}
private Runnable generateAddProjectTarEntries(GenerateProjectRequest request, OutputStream os) {
return () -> {
try (
TarArchiveOutputStream tos = new TarArchiveOutputStream(os)) {
tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
addTarEntry(tos, "src/main/java/io/syndesis/example/Application.java", generateFromRequest(request, applicationJavaMustache));
addTarEntry(tos, "src/main/resources/application.properties", generateFromRequest(request, applicationPropertiesMustache));
addTarEntry(tos, "src/main/resources/syndesis.yml", generateFlowYaml(tos, request));
addTarEntry(tos, "pom.xml", generatePom(request.getIntegration()));
addAdditionalResources(tos);
LOG.info("Integration [{}]: Project files written to output stream",Names.sanitize(request.getIntegration().getName()));
} catch (IOException e) {
if (LOG.isErrorEnabled()) {
LOG.error(String.format("Exception while creating runtime build tar for integration %s : %s",
request.getIntegration().getName(), e.toString()), e);
}
}
};
}
private void addTarEntry(TarArchiveOutputStream tos, String path, byte[] content) throws IOException {
TarArchiveEntry entry = new TarArchiveEntry(path);
entry.setSize(content.length);
tos.putArchiveEntry(entry);
tos.write(content);
tos.closeArchiveEntry();
}
@Override
public byte[] generatePom(Integration integration) throws IOException {
Set connectors = new LinkedHashSet<>();
Set gavsSeen = new HashSet<>();
for (Step step : integration.getSteps()) {
if (!step.getStepKind().equals(Endpoint.KIND)) {
continue;
}
step.getAction().ifPresent(action -> {
String gav = action.getCamelConnectorGAV();
if (gavsSeen.contains(gav)) {
return;
}
String[] splitGav = gav.split(":");
if (splitGav.length == 3) {
connectors.add(new MavenGav(splitGav[0], splitGav[1], splitGav[2]));
}
gavsSeen.add(gav);
});
}
return generateFromPomContext(new PomContext(integration.getId().orElse(""),
integration.getName(),
integration.getDescription().orElse(null),
connectors,
generatorProperties.getMavenProperties()),
pomMustache);
}
@SuppressWarnings("PMD.UnusedPrivateMethod") // PMD false positive
private byte[] generateFlowYaml(TarArchiveOutputStream tos, GenerateProjectRequest request) throws JsonProcessingException {
final Map connectorIdMap = new HashMap<>();
final List extends Step> steps = request.getIntegration().getSteps();
final Flow flow = new Flow();
if (!steps.isEmpty()) {
// Determine connector prefix
request.getIntegration().getSteps().stream()
.filter(s -> s.getStepKind().equals(Endpoint.KIND))
.filter(s -> s.getAction().isPresent())
.filter(s -> s.getConnection().isPresent())
.collect(Collectors.groupingBy(s -> s.getAction().get().getCamelConnectorPrefix()))
.forEach(
(prefix, stepList) -> {
if (stepList.size() > 1) {
for (int i = 0; i < stepList.size(); i++) {
connectorIdMap.put(stepList.get(i), Integer.toString(i + 1));
}
}
}
);
Queue remaining = new LinkedList<>(steps);
Step first = remaining.remove();
if (first != null) {
GeneratorContext generatorContext = new GeneratorContext.Builder()
.connectorCatalog(connectorCatalog)
.generatorProperties(generatorProperties)
.request(request)
.tarArchiveOutputStream(tos)
.flow(flow)
.visitorFactoryRegistry(registry)
.build();
StepVisitorContext stepContext = new StepVisitorContext.Builder()
.index(1)
.step(first)
.remaining(remaining)
.connectorIdSupplier(step -> Optional.ofNullable(connectorIdMap.get(step)))
.build();
visitStep(generatorContext, stepContext);
}
}
SyndesisModel syndesisModel = new SyndesisModel();
syndesisModel.addFlow(flow);
return YAML_OBJECT_MAPPER.writeValueAsBytes(syndesisModel);
}
private void visitStep(GeneratorContext generatorContext, StepVisitorContext stepContext) {
StepVisitorFactory> factory = registry.get(stepContext.getStep().getStepKind());
StepVisitor visitor = factory.create(generatorContext);
generatorContext.getFlow().addStep(visitor.visit(stepContext));
if (stepContext.hasNext()) {
visitStep(generatorContext, stepContext.next());
}
}
private byte[] generateFromRequest(GenerateProjectRequest request, Mustache template) throws IOException {
return generate(request, template);
}
private byte[] generateFromPomContext(PomContext integration, Mustache template) throws IOException {
return generate(integration, template);
}
private byte[] generate(Object scope, Mustache template) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
template.execute(new OutputStreamWriter(bos, UTF_8), scope).flush();
return bos.toByteArray();
}
/* default */ static class MavenGav {
private final String groupId;
private final String artifactId;
private final String version;
/* default */ MavenGav(String groupId, String artifactId, String version) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
}
public String getGroupId() {
return groupId;
}
public String getArtifactId() {
return artifactId;
}
public String getVersion() {
return version;
}
}
/* default */ static class PomContext {
private final String id;
private final String name;
private final String description;
private final Set connectors;
private final MavenProperties mavenProperties;
/* default */ PomContext(String id, String name, String description, Set connectors, MavenProperties mavenProperties) {
this.id = id;
this.name = name;
this.description = description;
this.connectors = connectors;
this.mavenProperties = mavenProperties;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Set getConnectors() {
return connectors;
}
public Set> getMavenRepositories() {
return mavenProperties.getRepositories().entrySet();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy