diff --git a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/artifacts/artifacts.module.ts b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/artifacts/artifacts.module.ts
index 5040c376cf..7c2bb83007 100644
--- a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/artifacts/artifacts.module.ts
+++ b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/artifacts/artifacts.module.ts
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ * Copyright (c) 2020-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -24,7 +24,7 @@ import { WineryModalModule } from '../../../wineryModalModule/winery.modal.modul
import { WineryNamespaceSelectorModule } from '../../../wineryNamespaceSelector/wineryNamespaceSelector.module';
import { WineryDuplicateValidatorModule } from '../../../wineryValidators/wineryDuplicateValidator.module';
import { WineryPipesModule } from '../../../wineryPipes/wineryPipes.module';
-import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.moudle';
+import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.module';
import { ArtifactsComponent } from './artifacts.component';
import { WineryQNameSelectorModule } from '../../../wineryQNameSelector/wineryQNameSelector.module';
import { ArtifactsService } from './artifacts.service';
diff --git a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/implementations/implementations.module.ts b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/implementations/implementations.module.ts
index 17b5829de0..4c02e67449 100644
--- a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/implementations/implementations.module.ts
+++ b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/implementations/implementations.module.ts
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 Contributors to the Eclipse Foundation
+ * Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -26,7 +26,7 @@ import { WineryModalModule } from '../../../wineryModalModule/winery.modal.modul
import { WineryTableModule } from '../../../wineryTableModule/wineryTable.module';
import { ImplementationsComponent } from './implementations.component';
import { WineryPipesModule } from '../../../wineryPipes/wineryPipes.module';
-import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.moudle';
+import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.module';
@NgModule({
imports: [
diff --git a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/inheritance/inheritance.module.ts b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/inheritance/inheritance.module.ts
index 808c0dd18e..583b5795c6 100644
--- a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/inheritance/inheritance.module.ts
+++ b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/inheritance/inheritance.module.ts
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 Contributors to the Eclipse Foundation
+ * Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -22,7 +22,7 @@ import { WineryQNameSelectorModule } from '../../../wineryQNameSelector/wineryQN
import { SelectModule } from 'ng2-select';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
-import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.moudle';
+import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.module';
@NgModule({
imports: [
diff --git a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/generateArtifactApiData.ts b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/generateArtifactApiData.ts
index 5805ff9ca0..866485a675 100644
--- a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/generateArtifactApiData.ts
+++ b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/generateArtifactApiData.ts
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 Contributors to the Eclipse Foundation
+ * Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -20,9 +20,9 @@ export class GenerateArtifactApiData {
autoCreateArtifactTemplate: string;
autoGenerateIA: string;
// MUST be set
- artifactType = '{http://opentosca.org/artifacttypes}WAR';
+ // = '{http://opentosca.org/artifacttypes}WAR';
+ artifactType: string;
artifactSpecificContent: string;
interfaceName: string;
operationName: string;
- javaPackage: string;
}
diff --git a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/interfaces.component.html b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/interfaces.component.html
index 3f35ba5cc3..8c8b9706a8 100644
--- a/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/interfaces.component.html
+++ b/org.eclipse.winery.frontends/app/tosca-management/src/app/instance/sharedComponents/interfaces/interfaces.component.html
@@ -1,5 +1,5 @@
+
+
+
+
+
-
+
Inputs
- *
- * generateData
This input of type {@link GenerateData} is mandatory and must contain all
- * necessary
- * information for generating the url, such as the resource and resource type.
- *
- * modalRef
The modalRef is optional. You can give the reference to the modal which this component
- * is a part of. The reference is used to update the values each time the modal is shown.
- *
- *
- */
@Component({
selector: 'winery-component-exists',
templateUrl: './wineryComponentExists.component.html',
})
-export class WineryComponentExistsComponent implements OnInit {
+export class WineryComponentExistsComponent implements OnInit, OnChanges {
+ /**
+ * This component is for checking whether a given component already exists in the repository and displays it
+ * accordingly.
+ *
+ *
+ * generateData
This input of type {@link GenerateData} is mandatory and must contain all
+ * necessary
+ * information for generating the url, such as the resource and resource type.
+ *
+ * modalRef
The modalRef is optional. You can give the reference to the modal which this component
+ * is a part of. The reference is used to update the values each time the modal is shown.
+ *
+ *
+ */
@Input() generateData: GenerateData;
@Input() modalRef: ModalDirective;
+ @Input() artifactTypes: ArtifactTypeSelectData[];
+ artifactTemplate: String = ToscaTypes.ArtifactTemplate;
+ selectedArtifactType: ArtifactTypeSelectData;
+ implementAllOperations = new InterfaceOperationApiData('all');
randomIdSuffix = Math.random();
@@ -52,6 +60,26 @@ export class WineryComponentExistsComponent implements OnInit {
if (this.modalRef) {
this.modalRef.onShow.subscribe(() => this.checkImplementationExists());
}
+ if (this.generateData.toscaType === ToscaTypes.ArtifactTemplate) {
+ for (const value of this.artifactTypes) {
+ value.text = value.name;
+ }
+ this.implementAllOperations = new InterfaceOperationApiData(this.getInterfaceNameWithoutNS());
+ if (!this.generateData.selectedOperation) {
+ this.generateData.selectedOperation = this.implementAllOperations;
+ }
+ if (this.generateData.selectedInterface.operations.length === 1) {
+ this.generateData.selectedOperation = this.generateData.selectedInterface.operations[0];
+ }
+ this.selectedArtifactType = this.artifactTypes[0];
+ this.generateData.artifactTypeQName = this.selectedArtifactType.qName;
+ }
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.generateData && this.generateData.toscaType === ToscaTypes.ArtifactTemplate) {
+ this.implementAllOperations = new InterfaceOperationApiData(this.getInterfaceNameWithoutNS());
+ }
}
checkImplementationExists(): void {
@@ -76,6 +104,27 @@ export class WineryComponentExistsComponent implements OnInit {
);
}
}
+
+ typeSelected(type) {
+ this.generateData.artifactTypeQName = this.artifactTypes.find(value => value.name === type.id).qName;
+ }
+
+ handleRadioButton(operation: InterfaceOperationApiData) {
+ const searchValue = RegExp(this.generateData.selectedOperation.name + '-IA$');
+ if (operation.name === this.implementAllOperations.name) {
+ const interfaceNameWithoutNS: string = this.getInterfaceNameWithoutNS();
+ this.generateData.name = this.generateData.name.replace(searchValue, interfaceNameWithoutNS + '-IA');
+ this.generateData.selectedOperation = operation;
+ return;
+ }
+ this.generateData.name = this.generateData.name.replace(searchValue, operation.name + '-IA');
+ this.generateData.selectedOperation = operation;
+ }
+
+ private getInterfaceNameWithoutNS() {
+ return this.generateData.selectedInterface.name
+ .substr(this.generateData.selectedInterface.name.lastIndexOf('/') + 1);
+ }
}
export class GenerateData {
@@ -85,4 +134,7 @@ export class GenerateData {
name: string;
url: string;
version: WineryVersion;
+ artifactTypeQName: string;
+ selectedInterface: InterfacesApiData;
+ selectedOperation: InterfaceOperationApiData;
}
diff --git a/org.eclipse.winery.frontends/app/tosca-management/src/app/wineryComponentExists/wineryComponentExists.module.ts b/org.eclipse.winery.frontends/app/tosca-management/src/app/wineryComponentExists/wineryComponentExists.module.ts
index 8562ab8475..202edca320 100644
--- a/org.eclipse.winery.frontends/app/tosca-management/src/app/wineryComponentExists/wineryComponentExists.module.ts
+++ b/org.eclipse.winery.frontends/app/tosca-management/src/app/wineryComponentExists/wineryComponentExists.module.ts
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 Contributors to the Eclipse Foundation
+ * Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -11,15 +11,16 @@
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*******************************************************************************/
-import {NgModule} from '@angular/core';
+import { NgModule } from '@angular/core';
-import {WineryComponentExistsComponent} from './wineryComponentExists.component';
-import {CommonModule} from '@angular/common';
-import {FormsModule} from '@angular/forms';
-import {BrowserModule} from '@angular/platform-browser';
-import {ExistService} from '../wineryUtils/existService';
-import {WineryNamespaceSelectorModule} from '../wineryNamespaceSelector/wineryNamespaceSelector.module';
-import {WineryPipesModule} from '../wineryPipes/wineryPipes.module';
+import { WineryComponentExistsComponent } from './wineryComponentExists.component';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { BrowserModule } from '@angular/platform-browser';
+import { ExistService } from '../wineryUtils/existService';
+import { WineryNamespaceSelectorModule } from '../wineryNamespaceSelector/wineryNamespaceSelector.module';
+import { WineryPipesModule } from '../wineryPipes/wineryPipes.module';
+import { SelectModule } from 'ng2-select';
@NgModule({
imports: [
@@ -28,6 +29,7 @@ import {WineryPipesModule} from '../wineryPipes/wineryPipes.module';
CommonModule,
WineryNamespaceSelectorModule,
WineryPipesModule,
+ SelectModule,
],
exports: [WineryComponentExistsComponent],
declarations: [WineryComponentExistsComponent],
diff --git a/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/BashGenerator.java b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/BashGenerator.java
new file mode 100644
index 0000000000..4d4d35af7e
--- /dev/null
+++ b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/BashGenerator.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ *******************************************************************************/
+
+package org.eclipse.winery.generators.ia;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Collectors;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.model.tosca.TParameter;
+
+public class BashGenerator extends Generator {
+
+ public BashGenerator(TInterface tInterface, String operationName, Path workingDir) {
+ super(tInterface, operationName, workingDir);
+ }
+
+ @Override
+ public void generateImplementationArtifact() throws IOException {
+ if (operationName.equals("interface")) {
+ throw new IllegalArgumentException("The whole interface cannot be generated for bash as artifact type!");
+ } else {
+ StringBuilder sb = new StringBuilder();
+ TOperation operationToImplement = tInterface.getOperations().stream().parallel().filter(operation1 -> operation1.getName().equals(operationName)).findAny().orElseThrow(IllegalArgumentException::new);
+ String content = generateBashFileContent(sb, tInterface.getName(), operationToImplement);
+ Files.write(Paths.get(this.workingDirectory.toString(), operationName + ".sh"), content.getBytes());
+ }
+ }
+
+ /**
+ * Generates the bash file for the implementation of the provided operation of the provided interface.
+ *
+ * @return The contents of the bash file
+ */
+ private String generateBashFileContent(StringBuilder sb, String interfaceName, TOperation operation) {
+ sb.append("#!/bin/bash\n");
+ sb.append("# Implements the ").append(operation.getName()).append(" operation of the ").append(interfaceName).append(" interface\n");
+ // Add example call:
+ sb.append("# Example call: ");
+ if (operation.getInputParameters() != null) {
+ operation.getInputParameters().forEach(tParameter -> sb.append(tParameter.getName()).append("=test").append(tParameter.getName()).append(" "));
+ }
+ sb.append("./").append(operationName).append(".sh\n\n");
+
+ // Add input parameters and assign them to the positional arguments
+ if (operation.getInputParameters() != null) {
+ sb.append("# Print input parameters:\n");
+ operation.getInputParameters().forEach(tParameter -> sb.append("echo $").append(tParameter.getName()).append(" # Type: ").append(tParameter.getName().replace("xsd:", "")).append("\n"));
+ }
+ // Add output parameters
+ if (operation.getOutputParameters() != null) {
+ sb.append("\n# The Output parameters and their expected types:\n");
+ String outputParametersAndType = operation.getOutputParameters().stream().map(tParameter -> tParameter.getName() + " # Type: " + tParameter.getType().replace("xsd:", "")).collect(Collectors.joining(",\n"));
+ sb.append(outputParametersAndType);
+ sb.append("\n");
+ }
+
+ sb.append("\n# Your Code here\n\n");
+
+ if (operation.getOutputParameters() != null) {
+ sb.append("# Return\n");
+ for (TParameter output : operation.getOutputParameters()) {
+ sb.append("echo \"").append(output.getName()).append("=${").append(output.getName()).append("}\"\n");
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/DefaultGenerator.java b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/DefaultGenerator.java
new file mode 100644
index 0000000000..ff961d2d7a
--- /dev/null
+++ b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/DefaultGenerator.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ *******************************************************************************/
+
+package org.eclipse.winery.generators.ia;
+
+import java.nio.file.Path;
+
+import org.eclipse.winery.model.tosca.TInterface;
+
+/**
+ * Used if no generator for the given artifact type exists.
+ * Does not create any files.
+ */
+public class DefaultGenerator extends Generator {
+
+ public DefaultGenerator(TInterface tInterface, String operationName, Path workingDir) {
+ super(tInterface, operationName, workingDir);
+ }
+
+ @Override
+ public void generateImplementationArtifact() {
+
+ }
+}
diff --git a/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/Generator.java b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/Generator.java
index 95061522a4..8bb32b1242 100644
--- a/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/Generator.java
+++ b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/Generator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013-2017 Contributors to the Eclipse Foundation
+ * Copyright (c) 2022-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -11,368 +11,67 @@
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*******************************************************************************/
+
package org.eclipse.winery.generators.ia;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
import java.net.URL;
-import java.nio.charset.Charset;
import java.nio.file.Files;
-import java.nio.file.OpenOption;
import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
+import java.nio.file.Paths;
import org.eclipse.winery.model.tosca.TInterface;
-import org.eclipse.winery.model.tosca.TOperation;
-import org.eclipse.winery.model.tosca.TParameter;
-import org.apache.commons.compress.archivers.ArchiveEntry;
-import org.apache.commons.compress.archivers.ArchiveOutputStream;
-import org.apache.commons.compress.archivers.ArchiveStreamFactory;
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.utils.IOUtils;
-import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class Generator {
+/**
+ * Used if no generator for the given artifact type exists.
+ * Does not create any files.
+ */
+public abstract class Generator {
private static final Logger LOGGER = LoggerFactory.getLogger(Generator.class);
-
- // Placeholder applicable for all files
- private static final String PLACEHOLDER_JAVA_PACKAGE = "IA_PACKAGE";
- private static final String PLACEHOLDER_NAMESPACE = "IA_NAMESPACE";
- private static final String PLACEHOLDER_CLASS_NAME = "IA_CLASS_NAME";
- private static final String PLACEHOLDER_IA_ARTIFACT_TEMPLATE_UPLOAD_URL = "IA_ARTIFACT_TEMPLATE_UPLOAD_URL";
-
- // Placeholders in Java Service Files
- private static final String PLACEHOLDER_GENERATED_WEBSERVICE_METHODS = "GENERATED_WEBSERVICE_METHODS";
-
- // Template folder relative to resources folder in this project
- private static final String TEMPLATE_PROJECT_FOLDER = "template/project";
- private static final String TEMPLATE_JAVA_FOLDER = "template/java";
-
- private static final String TEMPLATE_JAVA_ABSTRACT_IA_SERVICE = "AbstractIAService.java.template";
- private static final String TEMPLATE_JAVA_TEMPLATE_SERVICE = "TemplateService.java.template";
-
- private final TInterface tInterface;
- private final File workingDir;
- private final File outDir;
- private final String name;
- private final String javaPackage;
- private final String namespace;
- private final URL iaArtifactTemplateUploadUrl;
-
- /**
- * Creates a new IA Generator instance for the given {@link TInterface}.
- *
- * @param tInterface TOSCA interface to generate the IA for
- * @param packageAndNamespace Package to be used for the generated Java code, e.g. 'org.opentosca.ia'. To
- * generate the respective Namespace for the Web Service the components of the
- * package are reverted, prepended with 'http://' and appended with '/'. This is
- * provided by the user in a textfield in the Winery UI.
- * @param iaArtifactTemplateUploadUrl The URL to which the generated IA should be posted.
- * @param name unique and valid name to be used for the generated maven project name, java
- * project name, class name, port type name.
- * @param workingDir working directory to generate the files. This directory also will contain the
- * ZIP file with the Eclipse project after generating it.
- */
- public Generator(TInterface tInterface, String packageAndNamespace, URL iaArtifactTemplateUploadUrl, String name, File workingDir) {
- super();
+
+ // The name of the operation that an ImplementationArtifact should be generated for, if the name is "interface" an
+ // ImplementationArtifact for each operation will be generated
+ final String operationName;
+ final TInterface tInterface;
+ final Path workingDirectory;
+
+ public Generator(TInterface tInterface, String operationName, Path workingDir) {
+ this.workingDirectory = workingDir;
+ this.operationName = operationName;
this.tInterface = tInterface;
- this.javaPackage = packageAndNamespace;
- this.iaArtifactTemplateUploadUrl = iaArtifactTemplateUploadUrl;
- this.name = name;
- this.workingDir = new File(workingDir.getAbsolutePath() + File.separator + this.name);
- this.outDir = new File(workingDir.getAbsolutePath());
-
- if (this.workingDir.exists()) {
- Generator.LOGGER.error("Workdir " + this.workingDir + " already exits. This might lead to corrupted results if it is not empty!");
- }
-
- // Generate Namespace
- String[] splitPkg = this.javaPackage.split("\\.");
- String tmpNamespace = "http://";
- for (int i = splitPkg.length - 1; i >= 0; i--) {
- tmpNamespace += splitPkg[i];
- // Add '.' if it is not the last iterations
- if (i != 0) {
- tmpNamespace += ".";
- }
- }
- this.namespace = tmpNamespace += "/";
- }
-
- /**
- * Generates the project and puts the files into a subdirectory of working dir
- *
- * @return the folder where the generated files are contained in
- */
- public Path generateProject() throws Exception {
- Path workingDirPath = this.workingDir.toPath();
- Files.createDirectories(workingDirPath);
-
- // directory to store the template files to generate the java files from
- Path javaTemplateDir = workingDirPath.resolve("../java");
- Files.createDirectories(javaTemplateDir);
-
- // Copy template project and template java files
- String s = this.getClass().getResource("").getPath();
- if (s.contains("jar!")) {
- Generator.LOGGER.trace("we work on a jar file");
- Generator.LOGGER.trace("Location of the current class: {}", s);
-
- // we have a jar file
- // format: file:/location...jar!...path-in-the-jar
- // we only want to have location :)
- int excl = s.lastIndexOf("!");
- s = s.substring(0, excl);
- s = s.substring("file:".length());
-
- try (JarFile jf = new JarFile(s);) {
- Enumeration entries = jf.entries();
- while (entries.hasMoreElements()) {
- JarEntry je = entries.nextElement();
- String name = je.getName();
- if (name.startsWith(Generator.TEMPLATE_PROJECT_FOLDER + "/") && (name.length() > (Generator.TEMPLATE_PROJECT_FOLDER.length() + 1))) {
- // strip "template/" from the beginning to have paths without "template" starting relatively from the working dir
- name = name.substring(Generator.TEMPLATE_PROJECT_FOLDER.length() + 1);
- if (je.isDirectory()) {
- // directory found
- Path dir = workingDirPath.resolve(name);
- Files.createDirectory(dir);
- } else {
- Path file = workingDirPath.resolve(name);
- try (InputStream is = jf.getInputStream(je);) {
- Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
- }
- }
- } else if (name.startsWith(Generator.TEMPLATE_JAVA_FOLDER + "/") && (name.length() > (Generator.TEMPLATE_JAVA_FOLDER.length() + 1))) {
- if (!je.isDirectory()) {
- // we copy the file directly into javaTemplateDir
- File f = new File(name);
- Path file = javaTemplateDir.resolve(f.getName());
- try (InputStream is = jf.getInputStream(je);) {
- Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
- }
- }
- }
- }
- }
- } else {
- // we're running in debug mode, we can work on the plain file system
- File templateProjectDir = new File(this.getClass().getResource("/" + Generator.TEMPLATE_PROJECT_FOLDER).getFile());
- FileUtils.copyDirectory(templateProjectDir, this.workingDir);
-
- File javaTemplatesDir = new File(this.getClass().getResource("/" + Generator.TEMPLATE_JAVA_FOLDER).getFile());
- FileUtils.copyDirectory(javaTemplatesDir, javaTemplateDir.toFile());
- }
-
- // Create Java Code Folder
- String[] splitPkg = this.javaPackage.split("\\.");
- StringBuilder javaFolderString = new StringBuilder(this.workingDir.getAbsolutePath() + File.separator + "src" + File.separator + "main" + File.separator + "java");
- for (String value : splitPkg) {
- javaFolderString.append(File.separator).append(value);
+
+ if (Files.exists(this.workingDirectory)) {
+ LOGGER.error("Workdir " + this.workingDirectory + " already exits. This might lead to corrupted results if it is not empty!");
}
-
- // Copy and rename TEMPLATE_JAVA_TEMPLATE_SERVICE
- Path templateJavaService = javaTemplateDir.resolve(Generator.TEMPLATE_JAVA_TEMPLATE_SERVICE);
- File javaService = new File(javaFolderString + File.separator + this.name + ".java");
- Files.createDirectories(javaService.toPath().getParent());
- Files.copy(templateJavaService, javaService.toPath(), StandardCopyOption.REPLACE_EXISTING);
-
- this.generateJavaFile(javaService);
- this.updateFilesRecursively(this.workingDir);
-
- return this.workingDir.toPath();
- }
-
- /**
- * Generates the IA project into the working dir and zipps it
- *
- * @return The ZIP file containing the maven/eclipse project to be downloaded by the user.
- */
- public File generateAndZipProject() throws Exception {
- final Path path = this.generateProject();
- return this.packageProject(path);
}
- private void generateJavaFile(File javaService) throws IOException {
-
- // Generate methods
- StringBuilder sb = new StringBuilder();
-
- for (TOperation op : this.tInterface.getOperations()) {
- // Annotations
- sb.append("\t@WebMethod\n");
- sb.append("\t@SOAPBinding\n");
- sb.append("\t@Oneway\n");
-
- // Signatur
- String operationReturn = "void";
- sb.append("\tpublic ").append(operationReturn).append(" ").append(op.getName()).append("(\n");
-
- // Parameter
- boolean first = true;
- if (op.getInputParameters() != null) {
- for (TParameter parameter : op.getInputParameters()) {
- String parameterName = parameter.getName();
-
- if (first) {
- first = false;
- sb.append("\t\t");
- } else {
- sb.append(",\n\t\t");
- }
-
- // Generate @WebParam
- sb.append("@WebParam(name=\"").append(parameterName).append("\", targetNamespace=\"").append(this.namespace).append("\") ");
-
- sb.append("String ").append(parameterName);
- }
- }
- sb.append("\n\t) {\n");
-
- // If there are output parameters we generate the respective HashMap
- boolean outputParamsExist = (op.getOutputParameters() != null) && (!op.getOutputParameters().isEmpty());
- if (outputParamsExist) {
- sb.append("\t\t// This HashMap holds the return parameters of this operation.\n");
- sb.append("\t\tfinal HashMap returnParameters = new HashMap();\n\n");
- }
-
- sb.append("\t\t// TODO: Implement your operation here.\n");
-
- // Generate code to set output parameters
- if (outputParamsExist) {
- for (TParameter outputParam : op.getOutputParameters()) {
- sb.append("\n\n\t\t// Output Parameter '").append(outputParam.getName()).append("' ");
- if (outputParam.getRequired()) {
- sb.append("(required)");
- } else {
- sb.append("(optional)");
- }
- sb.append("\n\t\t// TODO: Set ").append(outputParam.getName()).append(" parameter here.");
- sb.append("\n\t\t// Do NOT delete the next line of code. Set \"\" as value if you want to return nothing or an empty result!");
- sb.append("\n\t\treturnParameters.put(\"").append(outputParam.getName()).append("\", \"TODO\");");
- }
- sb.append("\n\n\t\tsendResponse(returnParameters);\n");
- }
-
- sb.append("\t}\n\n");
- }
-
- // Read file and replace placeholders
- Charset cs = Charset.defaultCharset();
- List lines = new ArrayList<>();
- for (String line : Files.readAllLines(javaService.toPath(), cs)) {
- // Replace web service method
- line = line.replaceAll(Generator.PLACEHOLDER_GENERATED_WEBSERVICE_METHODS, sb.toString());
- lines.add(line);
- }
-
- // Write file
- OpenOption[] options = new OpenOption[] {StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING};
- Files.write(javaService.toPath(), lines, cs, options);
- }
-
- /**
- * Iterates recursively through all the files in the project working directory and tries to replace the global
- * placeholders.
- *
- * @param folderOrFile to start with
- */
- private void updateFilesRecursively(File folderOrFile) {
- if (folderOrFile.isFile()) {
-
- if (folderOrFile.getAbsolutePath().endsWith(".jar")) {
- return;
- }
-
- Generator.LOGGER.trace("Updating file " + folderOrFile);
-
- try {
- // Read file and replace placeholders
- Charset cs = Charset.defaultCharset();
- List lines = new ArrayList<>();
- for (String line : Files.readAllLines(folderOrFile.toPath(), cs)) {
- line = line.replaceAll(Generator.PLACEHOLDER_CLASS_NAME, this.name);
- line = line.replaceAll(Generator.PLACEHOLDER_JAVA_PACKAGE, this.javaPackage);
- line = line.replaceAll(Generator.PLACEHOLDER_NAMESPACE, this.namespace);
- line = line.replaceAll(Generator.PLACEHOLDER_IA_ARTIFACT_TEMPLATE_UPLOAD_URL, this.iaArtifactTemplateUploadUrl.toString());
- lines.add(line);
- }
-
- // Write file
- OpenOption[] options = new OpenOption[] {StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING};
- Files.write(folderOrFile.toPath(), lines, cs, options);
- } catch (IOException e) {
- e.printStackTrace();
- }
- } else {
- Generator.LOGGER.trace("Updating folder " + folderOrFile);
- for (File childFile : folderOrFile.listFiles()) {
- this.updateFilesRecursively(childFile);
- }
- }
- }
-
- /**
- * Packages the generated project into a ZIP file which is stored in outDir and has the name of the Project.
- *
- * @param projectDir the dir where the generated files reside in
- * @return ZIP file
- */
- private File packageProject(Path projectDir) {
- try {
- File packagedProject = new File(this.outDir.getAbsoluteFile() + File.separator + this.name + ".zip");
- FileOutputStream fileOutputStream = new FileOutputStream(packagedProject);
- final ArchiveOutputStream zos = new ArchiveStreamFactory().createArchiveOutputStream("zip", fileOutputStream);
-
- this.addFilesRecursively(projectDir.toAbsolutePath().toFile(), projectDir.toAbsolutePath() + File.separator, zos);
-
- zos.finish();
- zos.close();
-
- return packagedProject;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
+ public Path generateArtifact() throws Exception {
+ Files.createDirectories(this.workingDirectory);
+ Files.createFile(Paths.get(this.workingDirectory.toString(), "README.md"));
+ generateImplementationArtifact();
+ return this.workingDirectory;
}
/**
- * Recursive Helper function for packageProject()
- *
- * @param folderOrFile to add into the archive
- * @param baseDir the base directory, which is to be stripped from the file name
- * @param zos ArchiveOutputStream to add the files to
+ * Hook used for the generation of the actual artifacts within the created working directory
*/
- private void addFilesRecursively(File folderOrFile, String baseDir, ArchiveOutputStream zos) {
- if (folderOrFile.isFile()) {
- String nameOfFileInZip = folderOrFile.getAbsolutePath().replace(baseDir, "");
- Generator.LOGGER.trace("Adding " + folderOrFile + " as " + nameOfFileInZip);
- ArchiveEntry archiveEntry = new ZipArchiveEntry(nameOfFileInZip);
- try (InputStream is = new FileInputStream(folderOrFile)) {
- zos.putArchiveEntry(archiveEntry);
- IOUtils.copy(is, zos);
- zos.closeArchiveEntry();
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- Generator.LOGGER.trace("Adding folder " + folderOrFile);
- for (File childFile : folderOrFile.listFiles()) {
- this.addFilesRecursively(childFile, baseDir, zos);
- }
+ public abstract void generateImplementationArtifact() throws Exception;
+
+ public static Generator getGenerator(String artifactType, TInterface tInterface, String packageAndNamespace, URL iaArtifactTemplateUploadUrl, String name, Path workingDir, String operation) {
+ artifactType = artifactType.substring(artifactType.lastIndexOf("}") + 1);
+ switch (artifactType) {
+ case "Bash":
+ return new BashGenerator(tInterface, operation, workingDir);
+ case "Python":
+ return new PythonGenerator(tInterface, operation, workingDir);
+ case "WAR":
+ case "JAR":
+ return new JarAndWarGenerator(tInterface, packageAndNamespace, iaArtifactTemplateUploadUrl, name, workingDir);
+ default:
+ return new DefaultGenerator(tInterface, operation, workingDir);
}
}
}
diff --git a/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/JarAndWarGenerator.java b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/JarAndWarGenerator.java
new file mode 100644
index 0000000000..3fec340950
--- /dev/null
+++ b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/JarAndWarGenerator.java
@@ -0,0 +1,372 @@
+/*******************************************************************************
+ * Copyright (c) 2013-2017 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ *******************************************************************************/
+package org.eclipse.winery.generators.ia;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.model.tosca.TParameter;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JarAndWarGenerator extends Generator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JarAndWarGenerator.class);
+
+ // Placeholder applicable for all files
+ private static final String PLACEHOLDER_JAVA_PACKAGE = "IA_PACKAGE";
+ private static final String PLACEHOLDER_NAMESPACE = "IA_NAMESPACE";
+ private static final String PLACEHOLDER_CLASS_NAME = "IA_CLASS_NAME";
+ private static final String PLACEHOLDER_IA_ARTIFACT_TEMPLATE_UPLOAD_URL = "IA_ARTIFACT_TEMPLATE_UPLOAD_URL";
+
+ // Placeholders in Java Service Files
+ private static final String PLACEHOLDER_GENERATED_WEBSERVICE_METHODS = "GENERATED_WEBSERVICE_METHODS";
+
+ // Template folder relative to resources folder in this project
+ private static final String TEMPLATE_PROJECT_FOLDER = "template/project";
+ private static final String TEMPLATE_JAVA_FOLDER = "template/java";
+
+ private static final String TEMPLATE_JAVA_ABSTRACT_IA_SERVICE = "AbstractIAService.java.template";
+ private static final String TEMPLATE_JAVA_TEMPLATE_SERVICE = "TemplateService.java.template";
+
+ private final TInterface tInterface;
+ private final File outDir;
+ private final String name;
+ private final String javaPackage;
+ private final String namespace;
+ private final URL iaArtifactTemplateUploadUrl;
+
+ /**
+ * Creates a new IA Generator instance for the given {@link TInterface}.
+ *
+ * @param tInterface TOSCA interface to generate the IA for
+ * @param packageAndNamespace Package to be used for the generated Java code, e.g. 'org.opentosca.ia'. To
+ * generate the respective Namespace for the Web Service the components of the
+ * package are reverted, prepended with 'http://' and appended with '/'. This is
+ * provided by the user in a textfield in the Winery UI.
+ * @param iaArtifactTemplateUploadUrl The URL to which the generated IA should be posted.
+ * @param name unique and valid name to be used for the generated maven project name, java
+ * project name, class name, port type name.
+ * @param workingDir working directory to generate the files. This directory also will contain the
+ * ZIP file with the Eclipse project after generating it.
+ */
+ public JarAndWarGenerator(TInterface tInterface, String packageAndNamespace, URL iaArtifactTemplateUploadUrl, String name, Path workingDir) {
+ super(tInterface, "", Paths.get(workingDir.toString(), name));
+ this.tInterface = tInterface;
+ this.javaPackage = packageAndNamespace;
+ this.name = name;
+ this.iaArtifactTemplateUploadUrl = iaArtifactTemplateUploadUrl;
+ this.outDir = workingDirectory.toAbsolutePath().toFile();
+
+ if (Files.exists(this.workingDirectory)) {
+ LOGGER.error("Workdir " + this.workingDirectory + " already exits. This might lead to corrupted results if it is not empty!");
+ }
+
+ if (javaPackage == null) {
+ this.namespace = null;
+ } else {
+ // Generate Namespace
+ String[] splitPkg = this.javaPackage.split("\\.");
+ StringBuilder tmpNamespace = new StringBuilder("http://");
+ for (int i = splitPkg.length - 1; i >= 0; i--) {
+ tmpNamespace.append(splitPkg[i]);
+ // Add '.' if it is not the last iterations
+ if (i != 0) {
+ tmpNamespace.append(".");
+ }
+ }
+ this.namespace = tmpNamespace.append("/").toString();
+ }
+ }
+
+ @Override
+ public void generateImplementationArtifact() throws IOException {
+ // directory to store the template files to generate the java files from
+ Path javaTemplateDir = workingDirectory.resolve("../java");
+ Files.createDirectories(javaTemplateDir);
+
+ // Copy template project and template java files
+ String s = this.getClass().getResource("").getPath();
+ if (s.contains("jar!")) {
+ JarAndWarGenerator.LOGGER.trace("we work on a jar file");
+ JarAndWarGenerator.LOGGER.trace("Location of the current class: {}", s);
+
+ // we have a jar file
+ // format: file:/location...jar!...path-in-the-jar
+ // we only want to have location :)
+ int excl = s.lastIndexOf("!");
+ s = s.substring(0, excl);
+ s = s.substring("file:".length());
+
+ try (JarFile jf = new JarFile(s)) {
+ Enumeration entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry je = entries.nextElement();
+ String name = je.getName();
+ if (name.startsWith(JarAndWarGenerator.TEMPLATE_PROJECT_FOLDER + "/") && (name.length() > (JarAndWarGenerator.TEMPLATE_PROJECT_FOLDER.length() + 1))) {
+ // strip "template/" from the beginning to have paths without "template" starting relatively from the working dir
+ name = name.substring(JarAndWarGenerator.TEMPLATE_PROJECT_FOLDER.length() + 1);
+ if (je.isDirectory()) {
+ // directory found
+ Path dir = workingDirectory.resolve(name);
+ Files.createDirectory(dir);
+ } else {
+ Path file = workingDirectory.resolve(name);
+ try (InputStream is = jf.getInputStream(je)) {
+ Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+ } else if (name.startsWith(JarAndWarGenerator.TEMPLATE_JAVA_FOLDER + "/") && (name.length() > (JarAndWarGenerator.TEMPLATE_JAVA_FOLDER.length() + 1))) {
+ if (!je.isDirectory()) {
+ // we copy the file directly into javaTemplateDir
+ File f = new File(name);
+ Path file = javaTemplateDir.resolve(f.getName());
+ try (InputStream is = jf.getInputStream(je)) {
+ Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // we're running in debug mode, we can work on the plain file system
+ File templateProjectDir = new File(this.getClass().getResource("/" + JarAndWarGenerator.TEMPLATE_PROJECT_FOLDER).getFile());
+ FileUtils.copyDirectory(templateProjectDir, this.workingDirectory.toFile());
+
+ File javaTemplatesDir = new File(this.getClass().getResource("/" + JarAndWarGenerator.TEMPLATE_JAVA_FOLDER).getFile());
+ FileUtils.copyDirectory(javaTemplatesDir, javaTemplateDir.toFile());
+ }
+
+ // Create Java Code Folder
+ String[] splitPkg = this.javaPackage.split("\\.");
+ StringBuilder javaFolderString = new StringBuilder(this.workingDirectory.toAbsolutePath() + File.separator + "src" + File.separator + "main" + File.separator + "java");
+ for (String value : splitPkg) {
+ javaFolderString.append(File.separator).append(value);
+ }
+
+ // Copy and rename TEMPLATE_JAVA_TEMPLATE_SERVICE
+ Path templateJavaService = javaTemplateDir.resolve(JarAndWarGenerator.TEMPLATE_JAVA_TEMPLATE_SERVICE);
+ File javaService = new File(javaFolderString + File.separator + this.name + ".java");
+ Files.createDirectories(javaService.toPath().getParent());
+ Files.copy(templateJavaService, javaService.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ this.generateJavaFile(javaService);
+
+ this.updateFilesRecursively(this.workingDirectory.toFile());
+ }
+
+ /**
+ * Generates the IA project into the working dir and zipps it
+ *
+ * @return The ZIP file containing the maven/eclipse project to be downloaded by the user.
+ */
+ public File generateAndZipProject() throws Exception {
+ final Path path = this.generateArtifact();
+ return this.packageProject(path);
+ }
+
+ private void generateJavaFile(File javaService) throws IOException {
+
+ // Generate methods
+ StringBuilder sb = new StringBuilder();
+
+ for (TOperation op : this.tInterface.getOperations()) {
+ // Annotations
+ sb.append("\t@WebMethod\n");
+ sb.append("\t@SOAPBinding\n");
+ sb.append("\t@Oneway\n");
+
+ // Signatur
+ String operationReturn = "void";
+ sb.append("\tpublic ").append(operationReturn).append(" ").append(op.getName()).append("(\n");
+
+ // Parameter
+ boolean first = true;
+ if (op.getInputParameters() != null) {
+ for (TParameter parameter : op.getInputParameters()) {
+ String parameterName = parameter.getName();
+
+ if (first) {
+ first = false;
+ sb.append("\t\t");
+ } else {
+ sb.append(",\n\t\t");
+ }
+
+ // Generate @WebParam
+ sb.append("@WebParam(name=\"").append(parameterName).append("\", targetNamespace=\"").append(this.namespace).append("\") ");
+
+ sb.append("String ").append(parameterName);
+ }
+ }
+ sb.append("\n\t) {\n");
+
+ // If there are output parameters we generate the respective HashMap
+ boolean outputParamsExist = (op.getOutputParameters() != null) && (!op.getOutputParameters().isEmpty());
+ if (outputParamsExist) {
+ sb.append("\t\t// This HashMap holds the return parameters of this operation.\n");
+ sb.append("\t\tfinal HashMap returnParameters = new HashMap();\n\n");
+ }
+
+ sb.append("\t\t// TODO: Implement your operation here.\n");
+
+ // Generate code to set output parameters
+ if (outputParamsExist) {
+ for (TParameter outputParam : op.getOutputParameters()) {
+ sb.append("\n\n\t\t// Output Parameter '").append(outputParam.getName()).append("' ");
+ if (outputParam.getRequired()) {
+ sb.append("(required)");
+ } else {
+ sb.append("(optional)");
+ }
+ sb.append("\n\t\t// TODO: Set ").append(outputParam.getName()).append(" parameter here.");
+ sb.append("\n\t\t// Do NOT delete the next line of code. Set \"\" as value if you want to return nothing or an empty result!");
+ sb.append("\n\t\treturnParameters.put(\"").append(outputParam.getName()).append("\", \"TODO\");");
+ }
+ sb.append("\n\n\t\tsendResponse(returnParameters);\n");
+ }
+
+ sb.append("\t}\n\n");
+ }
+
+ // Read file and replace placeholders
+ Charset cs = Charset.defaultCharset();
+ List lines = new ArrayList<>();
+ for (String line : Files.readAllLines(javaService.toPath(), cs)) {
+ // Replace web service method
+ line = line.replaceAll(JarAndWarGenerator.PLACEHOLDER_GENERATED_WEBSERVICE_METHODS, sb.toString());
+ lines.add(line);
+ }
+
+ // Write file
+ OpenOption[] options = new OpenOption[] {StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING};
+ Files.write(javaService.toPath(), lines, cs, options);
+ }
+
+ /**
+ * Iterates recursively through all the files in the project working directory and tries to replace the global
+ * placeholders.
+ *
+ * @param folderOrFile to start with
+ */
+ private void updateFilesRecursively(File folderOrFile) {
+ if (folderOrFile.isFile()) {
+
+ if (folderOrFile.getAbsolutePath().endsWith(".jar")) {
+ return;
+ }
+
+ JarAndWarGenerator.LOGGER.trace("Updating file " + folderOrFile);
+
+ try {
+ // Read file and replace placeholders
+ Charset cs = Charset.defaultCharset();
+ List lines = new ArrayList<>();
+ for (String line : Files.readAllLines(folderOrFile.toPath(), cs)) {
+ line = line.replaceAll(JarAndWarGenerator.PLACEHOLDER_CLASS_NAME, this.name);
+ line = line.replaceAll(JarAndWarGenerator.PLACEHOLDER_JAVA_PACKAGE, this.javaPackage);
+ line = line.replaceAll(JarAndWarGenerator.PLACEHOLDER_NAMESPACE, this.namespace);
+ line = line.replaceAll(JarAndWarGenerator.PLACEHOLDER_IA_ARTIFACT_TEMPLATE_UPLOAD_URL, this.iaArtifactTemplateUploadUrl.toString());
+ lines.add(line);
+ }
+
+ // Write file
+ OpenOption[] options = new OpenOption[] {StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING};
+ Files.write(folderOrFile.toPath(), lines, cs, options);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ JarAndWarGenerator.LOGGER.trace("Updating folder " + folderOrFile);
+ for (File childFile : folderOrFile.listFiles()) {
+ this.updateFilesRecursively(childFile);
+ }
+ }
+ }
+
+ /**
+ * Packages the generated project into a ZIP file which is stored in outDir and has the name of the Project.
+ *
+ * @param projectDir the dir where the generated files reside in
+ * @return ZIP file
+ */
+ private File packageProject(Path projectDir) {
+ try {
+ File packagedProject = new File(this.outDir.getAbsoluteFile() + File.separator + this.name + ".zip");
+ FileOutputStream fileOutputStream = new FileOutputStream(packagedProject);
+ final ArchiveOutputStream zos = new ArchiveStreamFactory().createArchiveOutputStream("zip", fileOutputStream);
+
+ this.addFilesRecursively(projectDir.toAbsolutePath().toFile(), projectDir.toAbsolutePath() + File.separator, zos);
+
+ zos.finish();
+ zos.close();
+
+ return packagedProject;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Recursive Helper function for packageProject()
+ *
+ * @param folderOrFile to add into the archive
+ * @param baseDir the base directory, which is to be stripped from the file name
+ * @param zos ArchiveOutputStream to add the files to
+ */
+ private void addFilesRecursively(File folderOrFile, String baseDir, ArchiveOutputStream zos) {
+ if (folderOrFile.isFile()) {
+ String nameOfFileInZip = folderOrFile.getAbsolutePath().replace(baseDir, "");
+ JarAndWarGenerator.LOGGER.trace("Adding " + folderOrFile + " as " + nameOfFileInZip);
+ ArchiveEntry archiveEntry = new ZipArchiveEntry(nameOfFileInZip);
+ try (InputStream is = new FileInputStream(folderOrFile)) {
+ zos.putArchiveEntry(archiveEntry);
+ IOUtils.copy(is, zos);
+ zos.closeArchiveEntry();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ JarAndWarGenerator.LOGGER.trace("Adding folder " + folderOrFile);
+ for (File childFile : folderOrFile.listFiles()) {
+ this.addFilesRecursively(childFile, baseDir, zos);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/PythonGenerator.java b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/PythonGenerator.java
new file mode 100644
index 0000000000..6903e7cf9a
--- /dev/null
+++ b/org.eclipse.winery.generators.ia/src/main/java/org/eclipse/winery/generators/ia/PythonGenerator.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ *******************************************************************************/
+
+package org.eclipse.winery.generators.ia;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Collectors;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.model.tosca.TParameter;
+
+public class PythonGenerator extends Generator {
+ // According to https://peps.python.org/pep-0008/#indentation
+ private static final String indentation = " ";
+
+ public PythonGenerator(TInterface tInterface, String operationName, Path workingDir) {
+ super(tInterface, operationName, workingDir);
+ }
+
+ @Override
+ public void generateImplementationArtifact() throws IOException {
+ if (operationName.equals("interface")) {
+ throw new IllegalArgumentException("The whole interface cannot be generated for bash as artifact type!");
+ } else {
+ StringBuilder sb = new StringBuilder();
+ TOperation operationToImplement = tInterface.getOperations().stream().parallel().filter(operation1 -> operation1.getName().equals(operationName)).findAny().orElseThrow(IllegalArgumentException::new);
+ String content = generatePythonFileContent(sb, tInterface.getName(), operationToImplement);
+ Files.write(Paths.get(this.workingDirectory.toString(), operationName + ".py"), content.getBytes());
+ }
+ }
+
+ private String generatePythonFileContent(StringBuilder sb, String interfaceName, TOperation operation) {
+ sb.append("#!/usr/bin/env python\n");
+
+ // Import statements:
+ if (operation.getInputParameters() != null) {
+ sb.append("from argparse import ArgumentParser\n");
+ }
+ sb.append("\n");
+ sb.append("# Implements the ").append(operation.getName()).append(" operation of the ").append(interfaceName).append(" interface\n");
+ // Add example call:
+ sb.append("# Example call: ");
+ sb.append("python ").append(operationName).append(".py ");
+ if (operation.getInputParameters() != null) {
+ operation.getInputParameters().forEach(tParameter -> sb.append("-").append(tParameter.getName()).append(" test").append(tParameter.getName()).append(" "));
+ }
+ sb.append("\n\n");
+
+ // define operation as method
+ String params = "";
+ if (operation.getInputParameters() != null) {
+ params = operation.getInputParameters().stream().map(tParameter -> tParameter.getName() + "=None").collect(Collectors.joining(", "));
+ }
+ sb.append("def ").append(operation.getName()).append("(");
+ sb.append(params);
+ sb.append("):\n");
+ // Print inputs and provide types as comments
+ if (operation.getInputParameters() != null) {
+ sb.append(indentation).append("# Print input parameters:\n");
+ operation.getInputParameters().forEach(tParameter -> sb.append(indentation).append("print(").append(tParameter.getName()).append(")").append(" # Type: ").append(tParameter.getType().replace("xsd:", "")).append("\n"));
+ sb.append("\n");
+ }
+ sb.append(indentation).append("# Your code here\n");
+ sb.append("\n");
+
+ // define main method
+ sb.append("def main():\n");
+
+ if (operation.getInputParameters() != null) {
+ // handle args parsing
+ sb.append(indentation).append("parser = ArgumentParser()\n");
+ operation.getInputParameters().forEach(tParameter -> sb.append(indentation)
+ .append("parser.add_argument('-")
+ .append(tParameter.getName())
+ .append("', '--")
+ .append(tParameter.getName())
+ .append("', type=")
+ // Todo: add lookup for the argument type from winery to argparse type (currently default: string)
+ .append("str")
+ .append(", dest='")
+ .append(tParameter.getName())
+ .append("')\n")
+ );
+ sb.append(indentation).append("args = parser.parse_args()\n\n");
+
+ // TODO: Should we check for non-none args if they are required or set the required flag in argparse???
+ }
+
+ // call operation method
+ // Add output parameters
+ sb.append(indentation);
+ if (operation.getOutputParameters() != null) {
+ sb.append(operation.getOutputParameters().stream().map(TParameter::getName).collect(Collectors.joining(", ")));
+ sb.append(" = ");
+ }
+ sb.append(operation.getName()).append("(");
+ if (operation.getInputParameters() != null) {
+ sb.append(operation.getInputParameters().stream().map(tParameter -> tParameter.getName() + "=args." + tParameter.getName()).collect(Collectors.joining(", ")));
+ }
+ sb.append(")\n");
+
+ // Print output
+ if (operation.getOutputParameters() != null) {
+ sb.append(indentation).append("# Return\n");
+ operation.getOutputParameters().forEach(tParameter -> sb.append(indentation).append("print('").append(tParameter.getName()).append("='").append(" + ").append("str(").append(tParameter.getName()).append("))\n"));
+ }
+
+ sb.append(indentation).append("quit()\n\n");
+
+ sb.append("if __name__ == \"__main__\":\n").append(indentation).append("main()");
+
+ return sb.toString();
+ }
+}
diff --git a/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/BashGeneratorTest.java b/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/BashGeneratorTest.java
new file mode 100644
index 0000000000..d911f62e2e
--- /dev/null
+++ b/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/BashGeneratorTest.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2013-2017 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ *******************************************************************************/
+package org.eclipse.winery.generators.ia;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.model.tosca.TParameter;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+public class BashGeneratorTest {
+
+ @TempDir
+
+ private Path wd;
+
+ @Test
+ public void testMultipleOpsWithInOutParams() {
+ TOperation install = new TOperation.Builder("install")
+ .addInputParameter(
+ new TParameter.Builder("VMIP", "xs:string").build()
+ )
+ .addInputParameter(
+ new TParameter.Builder("DBMSUsername", "xs:string").build()
+ )
+ .addOutputParameter(
+ new TParameter.Builder("Output", "xs:string").build()
+ )
+ .build();
+
+ TOperation uninstall = new TOperation.Builder("uninstall")
+ .addInputParameter(
+ new TParameter.Builder("SomeLongParameterName", "xs:string").build()
+ )
+ .addInputParameter(
+ new TParameter.Builder("Port", "xs:string").build()
+ )
+ .addOutputParameter(
+ new TParameter.Builder("Output", "xs:string").build()
+ )
+ .build();
+
+ TInterface iFace = new TInterface.Builder(
+ "http://www.example.org/interfaces/lifecycle",
+ Arrays.asList(
+ install,
+ uninstall
+ )
+ ).build();
+
+ BashGenerator gen = new BashGenerator(iFace,
+ "interface",
+ wd
+ );
+ Assertions.assertThrows(IllegalArgumentException.class, gen::generateArtifact);
+ }
+
+ @Test
+ public void testOneOpNoParams() throws Exception {
+ TInterface iFace = new TInterface.Builder(
+ "http://www.example.org/interfaces/lifecycle",
+ Collections.singletonList(
+ new TOperation.Builder("install").build()
+ )
+ ).build();
+
+ BashGenerator gen = new BashGenerator(iFace,
+ "install",
+ wd);
+ gen.generateArtifact();
+ Assertions.assertTrue(Files.exists(wd.resolve("README.md")));
+ Assertions.assertTrue(Files.exists(wd.resolve("install.sh")));
+ }
+}
diff --git a/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/GeneratorTest.java b/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/JarAndWarGeneratorTest.java
similarity index 80%
rename from org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/GeneratorTest.java
rename to org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/JarAndWarGeneratorTest.java
index 0822441471..5c69747ed3 100644
--- a/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/GeneratorTest.java
+++ b/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/JarAndWarGeneratorTest.java
@@ -14,7 +14,6 @@
package org.eclipse.winery.generators.ia;
import java.net.URL;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
@@ -23,24 +22,13 @@
import org.eclipse.winery.model.tosca.TOperation;
import org.eclipse.winery.model.tosca.TParameter;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
-public class GeneratorTest {
+public class JarAndWarGeneratorTest {
- private static Path wd;
-
- @BeforeAll
- public static void initialize() throws Exception {
- wd = Files.createTempDirectory("IAGenerator");
- }
-
- @AfterAll
- public static void destroy() throws Exception {
- FileUtils.forceDelete(wd.toFile());
- }
+ @TempDir
+ private Path wd;
@Test
public void testMultipleOpsWithInOutParams() throws Exception {
@@ -76,13 +64,12 @@ public void testMultipleOpsWithInOutParams() throws Exception {
)
).build();
- Generator gen = new Generator(iFace,
+ JarAndWarGenerator gen = new JarAndWarGenerator(iFace,
"org.opentosca.ia.test",
new URL("http://test.com"),
"TestMultipleOpsWithInOutParams",
- wd.toFile()
- );
- gen.generateProject();
+ wd);
+ gen.generateArtifact();
}
@Test
@@ -94,12 +81,11 @@ public void testOneOpNoParams() throws Exception {
)
).build();
- Generator gen = new Generator(iFace,
+ JarAndWarGenerator gen = new JarAndWarGenerator(iFace,
"org.opentosca.ia.test",
new URL("http://test.com"),
"TestOneOpNoParams",
- wd.toFile()
- );
- gen.generateProject();
+ wd);
+ gen.generateArtifact();
}
}
diff --git a/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/PythonGeneratorTest.java b/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/PythonGeneratorTest.java
new file mode 100644
index 0000000000..998d30757d
--- /dev/null
+++ b/org.eclipse.winery.generators.ia/src/test/java/org/eclipse/winery/generators/ia/PythonGeneratorTest.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2013-2017 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ *******************************************************************************/
+package org.eclipse.winery.generators.ia;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.model.tosca.TParameter;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+public class PythonGeneratorTest {
+
+ @TempDir
+
+ private Path wd;
+
+ @Test
+ public void testMultipleOpsWithInOutParams() throws Exception {
+ TOperation install = new TOperation.Builder("install")
+ .addInputParameter(
+ new TParameter.Builder("VMIP", "xs:string").build()
+ )
+ .addInputParameter(
+ new TParameter.Builder("DBMSUsername", "xs:string").build()
+ )
+ .addOutputParameter(
+ new TParameter.Builder("Output", "xs:string").build()
+ )
+ .build();
+
+ TOperation uninstall = new TOperation.Builder("uninstall")
+ .addInputParameter(
+ new TParameter.Builder("SomeLongParameterName", "xs:string").build()
+ )
+ .addInputParameter(
+ new TParameter.Builder("Port", "xs:string").build()
+ )
+ .addOutputParameter(
+ new TParameter.Builder("Output", "xs:string").build()
+ )
+ .build();
+
+ TInterface iFace = new TInterface.Builder(
+ "http://www.example.org/interfaces/lifecycle",
+ Arrays.asList(
+ install,
+ uninstall
+ )
+ ).build();
+
+ PythonGenerator gen = new PythonGenerator(iFace,
+ "interface",
+ wd);
+ Assertions.assertThrows(IllegalArgumentException.class, gen::generateArtifact);
+ }
+
+ @Test
+ public void testOneOpNoParams() throws Exception {
+ TInterface iFace = new TInterface.Builder(
+ "http://www.example.org/interfaces/lifecycle",
+ Collections.singletonList(
+ new TOperation.Builder("install").build()
+ )
+ ).build();
+
+ PythonGenerator gen = new PythonGenerator(iFace,
+ "install",
+ wd);
+ gen.generateArtifact();
+ Assertions.assertTrue(Files.exists(wd.resolve("README.md")));
+ Assertions.assertTrue(Files.exists(wd.resolve("install.py")));
+ }
+}
diff --git a/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/artifacts/GenericArtifactsResource.java b/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/artifacts/GenericArtifactsResource.java
index df99066714..76fbd0806c 100644
--- a/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/artifacts/GenericArtifactsResource.java
+++ b/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/artifacts/GenericArtifactsResource.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012-2018 Contributors to the Eclipse Foundation
+ * Copyright (c) 2012-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -27,12 +27,12 @@
import java.util.List;
import java.util.Optional;
+import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.xml.namespace.QName;
@@ -103,35 +103,28 @@ public GenericArtifactsResource(Class entityResourceTClazz, Cl
this.resWithNamespace = res;
}
- /**
- * @return TImplementationArtifact | TDeploymentArtifact (XML) | URL of generated IA zip (in case of autoGenerateIA)
- */
@POST
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Creates a new implementation/deployment artifact. If an implementation artifact with the same name already exists, it is overridden.")
@SuppressWarnings("unchecked")
- public Response generateArtifact(GenerateArtifactApiData apiData, @Context UriInfo uriInfo) {
+ public IAGenerationReport generateArtifact(GenerateArtifactApiData apiData, @Context UriInfo uriInfo, @Context final HttpServletResponse response) throws Exception {
// we assume that the parent ComponentInstance container exists
final IRepository repository = RepositoryFactory.getRepository();
-
if (StringUtils.isEmpty(apiData.artifactName)) {
- return Response.status(Status.BAD_REQUEST).entity("Empty artifactName").build();
+ throw new IllegalArgumentException("Empty artifactName");
}
if (StringUtils.isEmpty(apiData.artifactType)) {
if (StringUtils.isEmpty(apiData.artifactTemplateName) || StringUtils.isEmpty(apiData.artifactTemplateNamespace)) {
if (StringUtils.isEmpty(apiData.artifactTemplate)) {
- return Response.status(Status.BAD_REQUEST).entity("No artifact type given and no template given. Cannot guess artifact type").build();
+ throw new IllegalArgumentException("No artifact type given and no template given. Cannot guess artifact type");
}
}
}
if (!StringUtils.isEmpty(apiData.autoGenerateIA)) {
- if (StringUtils.isEmpty(apiData.javaPackage)) {
- return Response.status(Status.BAD_REQUEST).entity("no java package name supplied for IA auto generation.").build();
- }
if (StringUtils.isEmpty(apiData.interfaceName)) {
- return Response.status(Status.BAD_REQUEST).entity("no interface name supplied for IA auto generation.").build();
+ throw new IllegalArgumentException("No interface name supplied for IA auto generation.");
}
}
@@ -156,7 +149,7 @@ public Response generateArtifact(GenerateArtifactApiData apiData, @Context UriIn
} catch (Exception e) {
// FIXME: currently we allow a single element only. However, the content should be internally wrapped by an (arbitrary) XML element as the content will be nested in the artifact element, too
LOGGER.debug("Invalid content", e);
- return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ throw e;
}
}
@@ -175,7 +168,7 @@ public Response generateArtifact(GenerateArtifactApiData apiData, @Context UriIn
if (StringUtils.isEmpty(apiData.artifactType)) {
// derive the type from the artifact template
if (artifactTemplateId == null) {
- return Response.status(Status.NOT_ACCEPTABLE).entity("No artifactTemplate and no artifactType provided. Deriving the artifactType is not possible.").build();
+ throw new IllegalArgumentException("No artifactTemplate and no artifactType provided. Deriving the artifactType is not possible.");
}
@NonNull final QName type = repository.getElement(artifactTemplateId).getType();
artifactTypeId = BackendUtils.getDefinitionsChildId(ArtifactTypeId.class, type);
@@ -187,7 +180,7 @@ public Response generateArtifact(GenerateArtifactApiData apiData, @Context UriIn
// do the artifact template auto creation magic
if (StringUtils.isEmpty(apiData.artifactType)) {
- return Response.status(Status.BAD_REQUEST).entity("Artifact template auto creation requested, but no artifact type supplied.").build();
+ throw new IllegalArgumentException("Artifact template auto creation requested, but no artifact type supplied.");
}
artifactTypeId = BackendUtils.getDefinitionsChildId(ArtifactTypeId.class, apiData.artifactType);
@@ -272,12 +265,18 @@ public Response generateArtifact(GenerateArtifactApiData apiData, @Context UriIn
// TODO: Check for error, and in case one found return it
RestUtils.persist(super.res);
+ response.setStatus(Status.CREATED.getStatusCode());
+ try {
+ response.flushBuffer();
+ } catch (Exception e) {
+ }
if (StringUtils.isEmpty(apiData.autoGenerateIA)) {
// No IA generation
- return Response.created(URI.create(EncodingUtil.URLencode(apiData.artifactName))).entity(resultingArtifact).build();
+ return new IAGenerationReport(URI.create(EncodingUtil.URLencode(apiData.artifactName)).toURL());
} else {
+ LOGGER.debug("\nArtifact API Data: ArtifactName:{},\nArtifactTemplate: {},\n ArtifactTemplateName: {}\n ArtifactType: {},\n InterfaceName: {},\nOperationName: {}", apiData.artifactName, apiData.artifactTemplate, apiData.artifactTemplateName, apiData.artifactType, apiData.interfaceName, apiData.operationName);
// after everything was created, we fire up the artifact generation
- return this.generateImplementationArtifact(apiData.interfaceName, apiData.javaPackage, uriInfo, artifactTemplateId);
+ return this.generateImplementationArtifact(apiData.interfaceName, apiData.javaPackage, uriInfo, artifactTemplateId, apiData.artifactType, apiData.operationName);
}
}
@@ -307,21 +306,20 @@ private String generateName(EntityTypeId typeId, String interfaceName) {
* Generates the implementation artifact using the implementation artifact generator. Also sets the properties
* according to the requirements of OpenTOSCA.
*/
- private Response generateImplementationArtifact(String interfaceName, String javaPackage, UriInfo uriInfo, ArtifactTemplateId artifactTemplateId) {
-
+ private IAGenerationReport generateImplementationArtifact(String interfaceName, String javaPackage, UriInfo uriInfo, ArtifactTemplateId artifactTemplateId, String artifactType, String operation) throws Exception {
assert (this instanceof ImplementationArtifactsResource);
IRepository repository = RepositoryFactory.getRepository();
QName type = RestUtils.getType(this.res);
EntityTypeId typeId = getTypeId(type).orElseThrow(IllegalStateException::new);
- TInterface i = findInterface(typeId, interfaceName).orElseThrow(IllegalStateException::new);
+ TInterface tInterface = findInterface(typeId, interfaceName).orElseThrow(IllegalStateException::new);
Path workingDir;
try {
workingDir = Files.createTempDirectory("winery");
} catch (IOException e2) {
LOGGER.debug("Could not create temporary directory", e2);
- return Response.serverError().entity("Could not create temporary directory").build();
+ throw new IOException("Could not create temporary directory");
}
URI artifactTemplateFilesUri = uriInfo.getBaseUri().resolve(RestUtils.getAbsoluteURL(artifactTemplateId)).resolve("files");
@@ -330,33 +328,42 @@ private Response generateImplementationArtifact(String interfaceName, String jav
artifactTemplateFilesUrl = artifactTemplateFilesUri.toURL();
} catch (MalformedURLException e2) {
LOGGER.debug("Could not convert URI to URL", e2);
- return Response.serverError().entity("Could not convert URI to URL").build();
+ throw new MalformedURLException("Could not convert URI to URL");
}
-
+
+ IAGenerationReport result = new IAGenerationReport();
String name = this.generateName(typeId, interfaceName);
- Generator gen = new Generator(i, javaPackage, artifactTemplateFilesUrl, name, workingDir.toFile());
+ Generator gen = Generator.getGenerator(artifactType, tInterface, javaPackage, artifactTemplateFilesUrl, name, workingDir, operation);
Path targetPath;
try {
- targetPath = gen.generateProject();
- } catch (Exception e) {
- LOGGER.debug("IA generator failed", e);
- return Response.serverError().entity("IA generator failed").build();
- }
-
- DirectoryId fileDir = new ArtifactTemplateSourceDirectoryId(artifactTemplateId);
- try {
+ targetPath = gen.generateArtifact();
+ DirectoryId fileDir = new ArtifactTemplateSourceDirectoryId(artifactTemplateId);
BackendUtils.importDirectory(targetPath, repository, fileDir);
- } catch (IOException e) {
+ } catch (IllegalArgumentException iaEx) {
+ LOGGER.debug("IA stub generation failed", iaEx);
+ result.warning = "IA stub generation failed, as selected artifact type does not support interface level generation.";
+ } catch (Exception e) {
throw new WebApplicationException(e);
}
-
+
// clean up
FileUtils.forceDelete(workingDir);
this.storeProperties(artifactTemplateId, typeId, name);
- URI url = uriInfo.getBaseUri().resolve(Util.getUrlPath(artifactTemplateId));
- return Response.created(url).build();
+ result.artifactTemplate = uriInfo.getBaseUri().resolve(Util.getUrlPath(artifactTemplateId)).toURL();
+ return result;
+ }
+
+ private static class IAGenerationReport {
+ public String warning = "";
+ public URL artifactTemplate;
+
+ public IAGenerationReport() {
+ }
+ public IAGenerationReport(URL artifactTemplate) {
+ this.artifactTemplate = artifactTemplate;
+ }
}
private Optional getTypeId(QName type) {
diff --git a/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/edmm/EdmmResource.java b/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/edmm/EdmmResource.java
index 1dc6142322..92126f20c3 100644
--- a/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/edmm/EdmmResource.java
+++ b/org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/edmm/EdmmResource.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2021 Contributors to the Eclipse Foundation
+ * Copyright (c) 2021-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
@@ -15,7 +15,6 @@
import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -25,6 +24,7 @@
import java.util.UUID;
import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -185,7 +185,7 @@ public Response getOneToOneMap() {
@POST
@Consumes(MediaType.TEXT_PLAIN)
@Path("create-placeholders-scripts")
- public Response createPlaceholders(String componentType, @Context UriInfo uriInfo) throws IOException {
+ public Response createPlaceholders(String componentType, @Context UriInfo uriInfo, @Context HttpServletResponse response) throws Exception {
// adding the interface to the component node type
NodeTypeResource nodeTypeResource = new NodeTypesResource().getComponentInstanceResource(EncodingUtil.URLencode(NODE_TYPES), componentType);
@@ -251,7 +251,7 @@ public Response createPlaceholders(String componentType, @Context UriInfo uriInf
artifactApiData.artifactTemplate.equals(implementationArtifact.getArtifactRef().toString());
});
if (!implementationResourceExists) {
- nodeTypeImplementationResource.getImplementationArtifacts().generateArtifact(artifactApiData, uriInfo);
+ nodeTypeImplementationResource.getImplementationArtifacts().generateArtifact(artifactApiData, uriInfo, response);
}
}
return Response.status(Response.Status.CREATED).build();