Solvend maven depenency and added new DDI client functions

Signed-off-by: Jonathan Philip Knoblauch <JonathanPhilip.Knoblauch@bosch-si.com>
This commit is contained in:
Jonathan Philip Knoblauch
2016-04-26 10:56:33 +02:00
parent 0fd2f7200f
commit a065a81aed
17 changed files with 396 additions and 157 deletions

View File

@@ -1,49 +0,0 @@
/**
* Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
*/
package org.eclipse.hawkbit.ddi.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import feign.Contract;
/**
* @author Jonathan Knoblauch
*
*/
@SpringBootApplication
@EnableFeignClients
public class Application {
@Autowired
private DdiExampleClient ddiClient;
public static void main(final String[] args) {
new SpringApplicationBuilder().showBanner(false).sources(Application.class).run(args);
// TODO .encoder(new JacksonEncoder())
// .decoder(new ResponseEntityDecoder(new JacksonDecoder()));
}
// @Bean
// public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
// return new BasicAuthRequestInterceptor(configuration.getUsername(),
// configuration.getPassword());
// }
@Bean
public ApplicationJsonRequestHeaderInterceptor jsonHeaderInterceptor() {
return new ApplicationJsonRequestHeaderInterceptor();
}
@Bean
public Contract feignContract() {
return new IgnoreMultipleConsumersProducersSpringMvcContract();
}
}

View File

@@ -21,10 +21,11 @@ public class ApplicationJsonRequestHeaderInterceptor implements RequestIntercept
@Override
public void apply(final RequestTemplate template) {
template.header("Accept", MediaType.APPLICATION_JSON_VALUE);
// template.header("Accept",
// EnableHypermediaSupport.HypermediaType.HAL);
template.header("Accept", MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_OCTET_STREAM_VALUE,
MediaType.TEXT_PLAIN_VALUE);
// template.header("Accept", MediaType.APPLICATION_OCTET_STREAM_VALUE);
template.header("Content-Type", MediaType.APPLICATION_JSON_VALUE);
}
}

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
import org.springframework.hateoas.hal.Jackson2HalModule;
import org.springframework.http.ResponseEntity;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.FeignException;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.jackson.JacksonDecoder;
/**
* Decoder for DDI client.
*
*/
public class DdiDecoder implements Decoder {
ObjectMapper mapper;
public DdiDecoder() {
mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new Jackson2HalModule());
}
@Override
public Object decode(final Response response, final Type type) throws IOException, DecodeException, FeignException {
final Map<String, Collection<String>> header = response.headers();
final String contentType = String.valueOf(header.get("Content-Type"));
// TODO parameter verwenden
if (contentType.equals("[application/octet-stream]")) {
return ResponseEntity.ok(response.body().asInputStream());
}
final ResponseEntityDecoder responseEntityDecoder = new ResponseEntityDecoder(new JacksonDecoder(mapper));
return responseEntityDecoder.decode(response, type);
}
}

View File

@@ -1,20 +1,19 @@
/**
* Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client;
import org.eclipse.hawkbit.ddi.client.resource.RootControllerResourceClient;
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
import org.springframework.hateoas.hal.Jackson2HalModule;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Feign;
import feign.Feign.Builder;
import feign.Logger;
import feign.Logger.Level;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
/**
@@ -30,15 +29,18 @@ public class DdiDefaultFeignClient {
private final String tenant;
public DdiDefaultFeignClient(final String baseUrl, final String tenant) {
final ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new Jackson2HalModule());
feignBuilder = Feign.builder().contract(new IgnoreMultipleConsumersProducersSpringMvcContract())
.requestInterceptor(new ApplicationJsonRequestHeaderInterceptor()).logLevel(Level.FULL)
.logger(new Logger.ErrorLogger()).encoder(new JacksonEncoder())
.decoder(new ResponseEntityDecoder(new JacksonDecoder(mapper)));
.logger(new Logger.ErrorLogger()).encoder(new JacksonEncoder()).decoder(new DdiDecoder());
if (baseUrl == null) {
throw new IllegalStateException("A baseUrl has to be set");
}
if (tenant == null) {
throw new IllegalStateException("A tenant has to be set");
}
this.baseUrl = baseUrl;
this.tenant = tenant;
@@ -50,10 +52,12 @@ public class DdiDefaultFeignClient {
public RootControllerResourceClient getRootControllerResourceClient() {
String rootControllerResourcePath = this.baseUrl + RootControllerResourceClient.PATH;
rootControllerResourcePath = rootControllerResourcePath.replace("{tenant}", tenant);
// TODO tenant null throw exception
if (rootControllerResourceClient == null) {
String rootControllerResourcePath = this.baseUrl + RootControllerResourceClient.PATH;
rootControllerResourcePath = rootControllerResourcePath.replace("{tenant}", tenant);
rootControllerResourceClient = feignBuilder.target(RootControllerResourceClient.class,
rootControllerResourcePath);
}

View File

@@ -1,26 +1,51 @@
/**
* Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.eclipse.hawkbit.ddi.client.strategy.PersistenceStrategy;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiChunk;
import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase;
import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase;
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiResult.FinalResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus.ExecutionStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.hateoas.Link;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
//@Component
public class DdiExampleClient implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(DdiExampleClient.class);
private final String controllerId;
private Long actionIdOfLastInstalltion;
private final DdiDefaultFeignClient ddiDefaultFeignClient;
private final long pollingIntervalInMillis;
private final PersistenceStrategy persistenceStrategy;
final DdiDefaultFeignClient ddiDefaultFeignClient;
public DdiExampleClient(final String baseUrl, final String controllerId, final String tenant) {
super();
public DdiExampleClient(final String baseUrl, final String controllerId, final String tenant,
final long pollingIntervalInMillis, final PersistenceStrategy persistenceStrategy) {
this.controllerId = controllerId;
ddiDefaultFeignClient = new DdiDefaultFeignClient(baseUrl, tenant);
this.ddiDefaultFeignClient = new DdiDefaultFeignClient(baseUrl, tenant);
this.actionIdOfLastInstalltion = null;
this.pollingIntervalInMillis = pollingIntervalInMillis;
this.persistenceStrategy = persistenceStrategy;
}
@Override
@@ -28,65 +53,139 @@ public class DdiExampleClient implements Runnable {
ResponseEntity<DdiControllerBase> response;
for (int i = 0; i < 20; i++) {
while (!Thread.currentThread().isInterrupted()) {
response = ddiDefaultFeignClient.getRootControllerResourceClient().getControllerBase(controllerId);
final DdiControllerBase controllerBase = response.getBody();
final Link controllerDeploymentBaseLink = controllerBase.getLink("deploymentBase");
if (controllerDeploymentBaseLink != null) {
// TOD actung download nur einmal starten
startDownload(controllerDeploymentBaseLink);
final Long actionId = getActionIdOutOfLink(controllerDeploymentBaseLink);
final Integer resource = getResourceOutOfLink(controllerDeploymentBaseLink);
if (actionId != actionIdOfLastInstalltion) {
startDownload(actionId, resource);
simulateSuccessfulInstallation(actionId);
actionIdOfLastInstalltion = actionId;
}
}
try {
Thread.sleep(2000);
Thread.sleep(pollingIntervalInMillis);
System.out.println("polling ...");
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
LOGGER.error("Error during sleep");
}
}
}
public void startDdiClient() {
//
// TODO notify every 10 seconds on the rollout server
// TODO if new update available -> start download and installation
// process
// report status messages
}
private void startDownload(final Link controllerDeploymentBaseLink) {
// controllerDeploymentBaseLink.
// final List<String> varibles = controllerDeploymentBaseLink.get
final String link = controllerDeploymentBaseLink.getHref();
final String[] segs = link.split(Pattern.quote("/"));
final String[] ending = segs[8].split(Pattern.quote("?"));
final String actionId = ending[0];
final String resource = ending[1].substring(2);
private void startDownload(final Long actionId, final Integer resource) {
// resource has not been downloaded and installed
final ResponseEntity<DdiDeploymentBase> respone = ddiDefaultFeignClient.getRootControllerResourceClient()
.getControllerBasedeploymentAction(controllerId, Long.valueOf(actionId), Integer.valueOf(resource));
final DdiDeploymentBase ddiDeploymentBase = respone.getBody();
final Link downloadLink = ddiDeploymentBase.getDeployment().getChunks().get(0).getArtifacts().get(0)
.getLink("download");
System.out.println("download startet ....");
final List<DdiChunk> chunks = ddiDeploymentBase.getDeployment().getChunks();
for (final DdiChunk chunk : chunks) {
final List<DdiArtifact> artifactList = chunk.getArtifacts();
final Link downloadLink = ddiDeploymentBase.getDeployment().getChunks().get(0).getArtifacts().get(0)
.getLink("download-http");
final String[] downloadLinkSep = downloadLink.getHref().split(Pattern.quote("/"));
final Long softwareModuleId = Long.valueOf(downloadLinkSep[8]);
// download all artifacts
for (final DdiArtifact ddiArtifact : artifactList) {
downloadArtifact(actionId, softwareModuleId, ddiArtifact.getFilename());
}
}
}
private void startSimulatedInstalltion() {
private void downloadArtifact(final Long actionId, final Long softwareModuleId, final String artifact) {
sendFeedBackMessage(actionId, ExecutionStatus.PROCEEDING, FinalResult.NONE,
"Starting download of artifact " + artifact);
System.out.println("Starting download for artifact " + artifact);
final ResponseEntity<InputStream> responseDownloadArtifact = ddiDefaultFeignClient
.getRootControllerResourceClient().downloadArtifact(controllerId, softwareModuleId, artifact);
final HttpStatus statsuCode = responseDownloadArtifact.getStatusCode();
System.out.println("Finished download with stataus " + statsuCode);
persistenceStrategy.handleInputStream(responseDownloadArtifact.getBody(), artifact);
sendFeedBackMessage(actionId, ExecutionStatus.PROCEEDING, FinalResult.NONE, "Downloaded artifact " + artifact);
}
private void sendFeedBackMessage(final Long actionId, final ExecutionStatus executionStatus,
final FinalResult finalResult, final String message) {
final DdiResult result = new DdiResult(finalResult, null);
final List<String> details = new ArrayList<>();
details.add(message);
final DdiStatus ddiStatus = new DdiStatus(executionStatus, result, details);
final String time = null;
final DdiActionFeedback feedback = new DdiActionFeedback(actionId, time, ddiStatus);
final ResponseEntity<Void> response = ddiDefaultFeignClient.getRootControllerResourceClient()
.postBasedeploymentActionFeedback(feedback, controllerId, actionId);
final HttpStatus statsuCode = response.getStatusCode();
System.out.println("Message send with stataus " + statsuCode);
}
private void simulateSuccessfulInstallation(final Long actionId) {
sendFeedBackMessage(actionId, ExecutionStatus.PROCEEDING, FinalResult.SUCESS,
"Simulated installation successful");
}
private Long getActionIdOutOfLink(final Link controllerDeploymentBaseLink) {
final String[] ending = splitControllerDeploymentBaseLinkInActionIdAndResource(controllerDeploymentBaseLink);
return Long.valueOf(ending[0]);
}
private Integer getResourceOutOfLink(final Link controllerDeploymentBaseLink) {
final String[] ending = splitControllerDeploymentBaseLinkInActionIdAndResource(controllerDeploymentBaseLink);
return Integer.valueOf(ending[1].substring(2));
}
private String[] splitControllerDeploymentBaseLinkInActionIdAndResource(final Link controllerDeploymentBaseLink) {
final String link = controllerDeploymentBaseLink.getHref();
final String[] segments = link.split(Pattern.quote("/"));
return segments[8].split(Pattern.quote("?"));
}
// private RootControllerResourceClient getDownloadFeignClient() {
//
// final Builder feignBuilder = Feign.builder().contract(new
// IgnoreMultipleConsumersProducersSpringMvcContract())
// .requestInterceptor(new
// ApplicationJsonRequestHeaderInterceptor()).logLevel(Level.FULL)
// .logger(new Logger.ErrorLogger()).encoder(new
// JacksonEncoder()).decoder(new Decoder() {
// @Override
// public Object decode(final Response response, final Type type)
// throws IOException, DecodeException, FeignException {
//
// // TODO download
// final InputStream stream = response.body().asInputStream();
//
// final FileSystem local = FileSystems.getDefault();
//
// System.out.println("Status is " + response.status());
//
// final ResponseEntity<Void> test = new ResponseEntity<Void>(
// HttpStatus.valueOf(response.status()));
//
// return test;
// }
// });
//
// final RootControllerResourceClient rootControllerResourceClient =
// feignBuilder
// .target(RootControllerResourceClient.class,
// "http://localhost:8080/DEFAULT/controller/v1");
//
// return rootControllerResourceClient;
//
// }
}

View File

@@ -1,5 +1,10 @@
/**
* Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client.resource;

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client.strategy;
import java.io.InputStream;
/**
* @author Jonathan Knoblauch
*
*/
public class DoNotSaveArtifactsStrategy implements PersistenceStrategy {
@Override
public String getPersistenceStrategy() {
return "nosave";
}
@Override
public void handleInputStream(final InputStream in, final String artifactName) {
// down but do not save
}
}

View File

@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client.strategy;
import java.io.InputStream;
/**
* @author Jonathan Knoblauch
*
*/
public interface PersistenceStrategy {
public String getPersistenceStrategy();
public void handleInputStream(InputStream in, String artifactName);
}

View File

@@ -0,0 +1,45 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.client.strategy;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.google.common.io.ByteStreams;
/**
* @author Jonathan Knoblauch
*
*/
public class SaveArtifactsStrategy implements PersistenceStrategy {
@Override
public String getPersistenceStrategy() {
return "save";
}
@Override
public void handleInputStream(final InputStream in, final String artifactName) {
final File file = new File("C:\\testdownload\\" + artifactName);
try {
final OutputStream out = new FileOutputStream(file);
ByteStreams.copy(in, out);
} catch (final IOException e) {
e.printStackTrace();
// TODO throw
}
}
}