/*******************************************************************************
* Copyright (c) 2012-2015 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.runner;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.rest.HttpJsonHelper;
import org.eclipse.che.api.core.rest.HttpOutputMessage;
import org.eclipse.che.api.core.rest.OutputProvider;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.runner.dto.ApplicationProcessDescriptor;
import org.eclipse.che.dto.server.DtoFactory;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import org.eclipse.che.api.runner.internal.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Representation of remote application process.
*
* @author andrew00x
*/
public class RemoteRunnerProcess {
private static final Logger LOG = LoggerFactory.getLogger(RemoteRunnerProcess.class);
private final String baseUrl;
private final String runner;
private final Long processId;
private final long created;
RemoteRunnerProcess(String baseUrl, String runner, Long processId) {
this.baseUrl = baseUrl;
this.runner = runner;
this.processId = processId;
created = System.currentTimeMillis();
}
public Long getProcessId() {
return processId;
}
public long getCreationTime() {
return created;
}
/** URL of server where application was launched. */
public String getServerUrl() {
return baseUrl;
}
/**
* Get actual status of remote application process.
*
* @return status of remote application process
* @throws RunnerException
* if an error occurs
* @throws NotFoundException
* if can't get status of remote process because isn't available anymore, e.g. its already removed on remote server
*/
public ApplicationProcessDescriptor getApplicationProcessDescriptor() throws RunnerException, NotFoundException {
try {
return HttpJsonHelper.get(ApplicationProcessDescriptor.class, baseUrl + "/status/" + runner + '/' + processId);
} catch (IOException e) {
throw new RunnerException(e);
} catch (ServerException | UnauthorizedException | ForbiddenException | ConflictException e) {
throw new RunnerException(e.getServiceError());
}
}
/**
* Stop a remote application process.
*
* @return status of remote application process after the call
* @throws RunnerException
* if an error occurs
* @throws NotFoundException
* if can't stop remote application because isn't available anymore, e.g. its already removed on remote server
*/
public ApplicationProcessDescriptor stop() throws RunnerException, NotFoundException {
final ApplicationProcessDescriptor descriptor = getApplicationProcessDescriptor();
final Link link = descriptor.getLink(Constants.LINK_REL_STOP);
if (link == null) {
switch (descriptor.getStatus()) {
case STOPPED:
case CANCELLED:
LOG.debug("Can't stop process, status is {}", descriptor.getStatus());
return descriptor;
default:
throw new RunnerException("Can't stop application. Link for stop application is not available.");
}
}
try {
return HttpJsonHelper.request(ApplicationProcessDescriptor.class, DtoFactory.getInstance().clone(link));
} catch (IOException e) {
throw new RunnerException(e);
} catch (ServerException | UnauthorizedException | ForbiddenException | ConflictException e) {
throw new RunnerException(e.getServiceError());
}
}
public void readLogs(OutputProvider output) throws IOException, RunnerException, NotFoundException {
final ApplicationProcessDescriptor descriptor = getApplicationProcessDescriptor();
final Link link = descriptor.getLink(Constants.LINK_REL_VIEW_LOG);
if (link == null) {
throw new RunnerException("Logs are not available.");
}
doRequest(link.getHref(), link.getMethod(), output);
}
public void readRecipeFile(OutputProvider output) throws IOException, RunnerException {
doRequest(String.format("%s/recipe/%s/%d", baseUrl, runner, processId), "GET", output);
}
private void doRequest(String url, String method, final OutputProvider output) throws IOException {
final HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();
conn.setConnectTimeout(60 * 1000);
conn.setReadTimeout(60 * 1000);
conn.setRequestMethod(method);
try {
if (output instanceof HttpOutputMessage) {
HttpOutputMessage httpOutput = (HttpOutputMessage)output;
httpOutput.setStatus(conn.getResponseCode());
final String contentType = conn.getContentType();
if (contentType != null) {
httpOutput.addHttpHeader("Content-Type", contentType);
}
// for download files
final String contentDisposition = conn.getHeaderField("Content-Disposition");
if (contentDisposition != null) {
httpOutput.addHttpHeader("Content-Disposition", contentDisposition);
}
}
Closer closer = Closer.create();
try {
ByteStreams.copy(closer.register(conn.getInputStream()), closer.register(output.getOutputStream()));
} catch (Throwable e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
} finally {
conn.disconnect();
}
}
}