Fixed error handling and link extraction in manager

Change-Id: I4a17eb475df842b23707b3521451faa893e3c164
Signed-off-by: Dirk Fauth <Dirk.Fauth@de.bosch.com>
diff --git a/manager/src/main/java/org/eclipse/app4mc/cloud/manager/WorkflowController.java b/manager/src/main/java/org/eclipse/app4mc/cloud/manager/WorkflowController.java
index 76507b2..784226d 100644
--- a/manager/src/main/java/org/eclipse/app4mc/cloud/manager/WorkflowController.java
+++ b/manager/src/main/java/org/eclipse/app4mc/cloud/manager/WorkflowController.java
@@ -14,7 +14,6 @@
 package org.eclipse.app4mc.cloud.manager;
 
 import java.io.File;
-import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.file.Files;
@@ -26,7 +25,6 @@
 
 import org.apache.http.HttpStatus;
 import org.eclipse.app4mc.cloud.manager.administration.CloudServiceDefinition;
-import org.eclipse.app4mc.cloud.manager.storage.StorageException;
 import org.eclipse.app4mc.cloud.manager.storage.StorageFileNotFoundException;
 import org.eclipse.app4mc.cloud.manager.storage.StorageService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -345,7 +343,7 @@
 			// trigger status URL until process is finished or error occured
 			if (statusUrl != null) {
 				HttpResponse<?> statusResponse = Unirest.get(statusUrl).asEmpty();
-				List<String> linkHeaders = statusResponse.getHeaders().get("Link");
+				List<String> linkHeaders = getLinkHeaders(statusResponse);
 				
 				// TODO make this asynchronous using websockets
 				long start = System.currentTimeMillis();
@@ -359,12 +357,13 @@
 					}
 
 					statusResponse = Unirest.get(statusUrl).asEmpty();
-					linkHeaders = statusResponse.getHeaders().get("Link");
+					linkHeaders = getLinkHeaders(statusResponse);
 					
 					end = System.currentTimeMillis();
 					
 					// don't request for more than 30 seconds
 					if (end - start > 30_000) {
+						workflowStatus.addMessage(serviceName + " status requested for 30 seconds");
 						break;
 					}
 				}
@@ -450,7 +449,9 @@
 
 						Path migrationError = errorResponse.getBody().toPath();
 						String filename = getFilenameFromHeader(errorResponse.getHeaders().getFirst("Content-Disposition"));
-						migrationError = Files.move(migrationError, migrationSubDir.resolve(filename));
+						if (filename != null) {
+							migrationError = Files.move(migrationError, migrationSubDir.resolve(filename));
+						}
 
 						workflowStatus.addMessage(serviceName + " error result downloaded");
 						
@@ -466,6 +467,8 @@
 						
 						// extract delete
 						deleteUrl = getUrlFromLink(errorResponse.getHeaders().get("Link"), "delete", baseUrl);
+					} else {
+						workflowStatus.addError(serviceName + " has no result and no error");
 					}
 				}
 
@@ -484,8 +487,8 @@
 			
 			return result;
 
-		} catch (StorageException | IOException e) {
-			throw new ProcessingFailedException("Error on file operations in " + serviceName + " workflow", e);
+		} catch (Exception e) {
+			throw new ProcessingFailedException("Error in " + serviceName + " workflow: " + e.getMessage(), e);
 		}
 	}
 	
@@ -509,6 +512,31 @@
 	private static final String LINK_PARAM_DELIMITER = ";";
 
 	/**
+	 * Extract the Link headers from the {@link HttpResponse}. Used to normalize
+	 * different ways of sending the Link header. Typically every Link is sent as
+	 * its own header. But it is also supported to send all Link header in one
+	 * header element.
+	 * 
+	 * @param statusResponse The {@link HttpResponse} from which the Link headers
+	 *                       should be extracted.
+	 * @return The Link entries in the response header.
+	 */
+	private static List<String> getLinkHeaders(HttpResponse<?> statusResponse) {
+		ArrayList<String> result = new ArrayList<>();
+		
+		List<String> linkHeaders = statusResponse.getHeaders().get("Link");
+		for (String linkHeader : linkHeaders) {
+			String[] links = linkHeader.split(LINK_DELIMITER);
+			
+			for (String link : links) {
+				result.add(link.trim());
+			}
+		}
+		
+		return result;
+	}
+	
+	/**
 	 * Extracts the url from the link header and returns the url that has the
 	 * specified rel attribute set.
 	 * 
diff --git a/manager/src/main/resources/services.txt b/manager/src/main/resources/services.txt
index 7bc1d73..33cd2a8 100644
--- a/manager/src/main/resources/services.txt
+++ b/manager/src/main/resources/services.txt
@@ -9,5 +9,5 @@
 Chart Visualizer;http://localhost:8083/app4mc/visualization/barchart/;Chart Visualizer Service
 Amalthea 2 INCHRON;https://am2inc.dev1.inchron.de/projects;Amalthea to INCHRON Transformation Service
 Amalthea 2 SystemC;http://localhost:8282/app4mc/amlt2systemc/;Amalthea to SystemC Transformation Service
-APP4MC.Sim;http://139.30.201.40:2323/app4mc/simulation/;APP4MC SystemC Simulation Service
+APP4MC.Sim;http://139.30.201.29:2323/app4mc/simulation/;APP4MC SystemC Simulation Service
 INCHRON BTF Trace Visualization;https://trace.dev1.inchron.de/traces/;INCHRON BTF Trace Visualization Service