/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.machine.server.util;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.machine.MachineConfig;
import org.eclipse.che.api.core.model.machine.MachineSource;
import org.eclipse.che.api.machine.server.exception.MachineException;
import org.eclipse.che.api.machine.server.recipe.RecipeImpl;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.IoUtil;
import org.slf4j.Logger;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriBuilderException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import static java.lang.String.format;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Downloads machine recipe set in machine source.
*
* <p>Adds user token if target url points to current CHE server.
*
* @author Alexander Garagatyi
*/
public class RecipeDownloader {
private static final Logger LOG = getLogger(RecipeDownloader.class);
private final URI apiEndpoint;
@Inject
public RecipeDownloader(@Named("che.api") URI apiEndpoint) {
this.apiEndpoint = apiEndpoint;
}
/**
* Downloads recipe by location from {@link MachineSource#getLocation()}.
*
* @param machineConfig
* config used to get recipe location
* @return recipe with set content and type
* @throws MachineException
* if any error occurs
*/
public RecipeImpl getRecipe(MachineConfig machineConfig) throws MachineException {
URL recipeUrl;
File file = null;
final String location = machineConfig.getSource().getLocation();
try {
UriBuilder targetUriBuilder = UriBuilder.fromUri(location);
// add user token to be able to download user's private recipe
final URI recipeUri = targetUriBuilder.build();
if (!recipeUri.isAbsolute() && recipeUri.getHost() == null) {
targetUriBuilder.scheme(apiEndpoint.getScheme())
.host(apiEndpoint.getHost())
.port(apiEndpoint.getPort())
.replacePath(apiEndpoint.getPath() + location);
if (EnvironmentContext.getCurrent().getSubject().getToken() != null) {
targetUriBuilder.queryParam("token", EnvironmentContext.getCurrent().getSubject().getToken());
}
}
recipeUrl = targetUriBuilder.build().toURL();
file = IoUtil.downloadFileWithRedirect(null, "recipe", null, recipeUrl);
return new RecipeImpl().withType(machineConfig.getSource().getType())
.withScript(IoUtil.readAndCloseQuietly(new FileInputStream(file)));
} catch (IOException | IllegalArgumentException e) {
throw new MachineException(format("Failed to download recipe for machine %s. Recipe url %s. Error: %s",
machineConfig.getName(),
location,
e.getLocalizedMessage()));
} finally {
if (file != null && !file.delete()) {
LOG.error(String.format("Removal of recipe file %s failed.", file.getAbsolutePath()));
}
}
}
/**
* Downloads recipe by location.
*
* @param location
* location of recipe
* @return recipe with set content and type
* @throws ServerException
* if any error occurs
*/
public String getRecipe(String location) throws ServerException {
URL recipeUrl;
File file = null;
try {
UriBuilder targetUriBuilder = UriBuilder.fromUri(location);
// add user token to be able to download user's private recipe
final URI recipeUri = targetUriBuilder.build();
if (!recipeUri.isAbsolute() && recipeUri.getHost() == null) {
targetUriBuilder.scheme(apiEndpoint.getScheme())
.host(apiEndpoint.getHost())
.port(apiEndpoint.getPort())
.replacePath(apiEndpoint.getPath() + location);
if (EnvironmentContext.getCurrent().getSubject().getToken() != null) {
targetUriBuilder.queryParam("token", EnvironmentContext.getCurrent().getSubject().getToken());
}
}
recipeUrl = targetUriBuilder.build().toURL();
file = IoUtil.downloadFileWithRedirect(null, "recipe", null, recipeUrl);
return IoUtil.readAndCloseQuietly(new FileInputStream(file));
} catch (IOException | IllegalArgumentException | UriBuilderException e) {
throw new MachineException(format("Failed to download recipe %s. Error: %s",
location,
e.getLocalizedMessage()));
} finally {
if (file != null && !file.delete()) {
LOG.error(String.format("Removal of recipe file %s failed.", file.getAbsolutePath()));
}
}
}
}