All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.guixer.maven.SendToGuixerMojo Maven / Gradle / Ivy

There is a newer version: 0.0.25
Show newest version
package io.guixer.maven;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.newArrayList;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.substringBeforeLast;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.annotation.Nullable;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.FileUtils;
import org.joda.time.DateTime;
import org.json.simple.parser.ParseException;

import io.guixer.maven.ResponseParser.MyUpload;

@Mojo(name = "send", defaultPhase = LifecyclePhase.PACKAGE)
public class SendToGuixerMojo extends AbstractGuixerOutMojo {

	@Parameter(defaultValue = "${project}", required = true, readonly = true)
	private MavenProject project;

	@Parameter(property = "guixer.apiBaseHref", required = true)
	private String guixerApiBaseHref;

	@Parameter(property = "guixer.username", required = true)
	private String guixerUsername;

	@Parameter(property = "guixer.password", required = true)
	private String guixerPassword;

	@Parameter(property = "guixer.projectName", required = false)
	private String guixerProjectName;

//	@Parameter(property = "guixer.token", required = true)
//	private String guixerToken;

	@Parameter(alias = "guixer.attributes")
	@Nullable
	private Map attributes;

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {

		// Ignore race issues
		//
		final MavenProject project = this.project;

		// 1. Check our directory is valid

		// final GuixerOut guixerOut =
		loadGuixerOut(project);

		// 2. Compose the archive file name

		final String mavenProjectName = isBlank(project.getName()) //
				? project.getArtifactId() //
				: project.getName();

		final DateTime now = new DateTime();

		@Nullable
		final String ciJobId = System.getProperty("CI_JOB_ID");

		@Nullable
		final String ciJobIdEnvVariable = System.getenv("CI_JOB_ID");

		getLog().info("CI_JOB_ID (system property): " + ciJobId);
		getLog().info("CI_JOB_ID (env): " + ciJobId);

		final StringBuilder sb = new StringBuilder(mavenProjectName);

		sb.append("-").append(now.toString("yyyy-MM-dd-HH'h'mm"));

		if (ciJobId != null) {

			sb.append("-").append(ciJobId);

		} else if (ciJobIdEnvVariable != null) {

			sb.append("-").append(ciJobIdEnvVariable);
		}

		final String archiveFileName = sb.append(".zip").toString();

		getLog().info("Archive file name: " + archiveFileName);

		// 3. Zip the archive

		final File guixerOutDir = getGuixerOutDirectory(project);

		final File archiveFile = new File(getTargetDir(project), archiveFileName);

		try {

			zipDirectory(guixerOutDir, archiveFile);

		} catch (final IOException e) {

			throw new MojoExecutionException("Error while zipping the directory: " + guixerOutDir.getAbsolutePath(), e);
		}

		// 4. Send the archive

		// final String username = "toto";

		final String projectName = guixerProjectName;

		final String guixerBaseHrefWithTrailingSlash = guixerApiBaseHref.endsWith("/") //
				? (guixerApiBaseHref) //
				: (guixerApiBaseHref + "/");

		final String endpoint = guixerBaseHrefWithTrailingSlash + "api/uploads/new";

		final MyUpload upload;

		try {

			upload = sendArchive(projectName, archiveFile, attributes, endpoint);

		} catch (final IOException e) {

			throw new MojoExecutionException("Error while sending the archive: " + archiveFile.getAbsolutePath(), e);

		} catch (final ParseException e) {

			throw new MojoExecutionException("Error while parsing the JSON response", e);
		}

		final String endpoint2 = substringBeforeLast(endpoint, "/new") + "/" + upload.getId();

		try {

			processUpload(endpoint2);

		} catch (final IOException e) {

			throw new MojoExecutionException("Error while processing the upload: " + upload.getId(), e);
		}

		final String revueUrl = guixerBaseHrefWithTrailingSlash + "uploads/" + upload.getId() + "/revue";

		final String HR = "------------------------------------------------------------------------";

		getLog().info(HR);

		getLog().info("You can browse your upload at:");

		getLog().info("");

		getLog().info("    " + revueUrl);

		getLog().info("");

		getLog().info(HR);
	}

	private void zipDirectory(
		final File dir,
		final File zipFile
	) throws IOException {

		getLog().debug("Zipping into: " + zipFile.getCanonicalPath() + "...");

		try (OutputStream os = new FileOutputStream(zipFile)) {

			try (ZipOutputStream zipOs = new ZipOutputStream(os)) {

				zip(zipOs, "", dir);
			}
		}
	}

	private void zip(
		final ZipOutputStream zipOs,
		final String prefix,
		final File file
	) throws IOException {

		if (file.isHidden()) {

			getLog().warn("Skipping hidden file: " + file.getCanonicalPath());

			return;

		} else if (!file.canRead()) {

			getLog().warn("Skipping non-readable file: " + file.getCanonicalPath());

			return;
		}

		getLog().debug("Adding to archive: " + file.getCanonicalPath());

		final String fileName = file.getName();

		if (file.isDirectory()) {

			zipOs.putNextEntry(new ZipEntry(prefix + fileName + "/"));
			zipOs.closeEntry();

			for (final File childFile : file.listFiles()) {

				zip(zipOs, prefix + fileName + "/", childFile);
			}

		} else {

			zipOs.putNextEntry(new ZipEntry(prefix + fileName));

			try (InputStream is = new FileInputStream(file)) {

				IOUtils.copy(is, zipOs);
			}

			zipOs.closeEntry();
		}
	}

	private MyUpload sendArchive(
		@Nullable final String projectName,
		final File file,
		@Nullable final Map attributes,
		final String endpoint
	) throws IOException, ParseException {

		checkNotNull(file, "file");
		checkNotNull(endpoint, "endpoint");

		if (!file.isFile()) {
			throw new FileNotFoundException(file.getCanonicalPath());
		}

		getLog().info("Sending to: " + endpoint);

		getLog().info("Using username: " + guixerUsername);
		getLog().info("Using projectName: " + projectName);
		getLog().info("Using file: " + file.getName());
		getLog().debug("File full path: " + file.getCanonicalPath());

		// We use a temporary directory, to skip all problems coming from
		// non-ASCII original dir names.
		//
		final File tmpDir = Files.createTempDirectory("og5").toFile();

		final File tmpFile = new File(tmpDir, file.getName());

		FileUtils.copyFile(file, tmpFile);

		final HttpClient httpClient = new DefaultHttpClient();

		try {

			final HttpPost httpPost = new HttpPost(endpoint);

			final FileBody archiveFileBody = new FileBody(tmpFile);

			final MultipartEntity entity = new MultipartEntity();

			entity.addPart("username", new StringBody(guixerUsername));
			entity.addPart("password", new StringBody(guixerPassword));

			if (projectName != null) {
				entity.addPart("projectName", new StringBody(projectName));
			}

			entity.addPart("file", archiveFileBody);

			if (attributes != null) {

				for (final Map.Entry entry : attributes.entrySet()) {

					final String key = entry.getKey();

					@Nullable
					final String value = entry.getValue();

					if (value == null) {

						getLog().warn("Skipping attribute." + key + ": " + value);

					} else {

						getLog().info("Using attribute." + key + ": " + value);

						entity.addPart("attribute." + key, new StringBody(value));
					}
				}
			}

			httpPost.setEntity(entity);

			getLog().info("Sending...");

			final HttpResponse response = httpClient.execute(httpPost);

			final StatusLine statusLine = response.getStatusLine();

			final int statusCode = statusLine.getStatusCode();

			if (statusCode != 200) {

				final String reasonPhrase = statusLine.getReasonPhrase();

				throw new RuntimeException("Expected HTTP status: 200, but was: " + statusCode //
						+ (isBlank(reasonPhrase) ? "" : (", " + reasonPhrase)));
			}

			getLog().info(byteCountSentSuccessfully(file.length()));

			final ByteArrayOutputStream bos = new ByteArrayOutputStream();

			try (InputStream is = response.getEntity().getContent()) {

				IOUtils.copy(is, bos);
			}

			final String json = bos.toString(UTF_8);

			return ResponseParser.toUpload(json);

		} finally {

			httpClient.getConnectionManager().shutdown();

			FileUtils.forceDelete(tmpDir);
		}
	}

	private void processUpload(
		final String endpoint
	) throws IOException {

		getLog().info("Calling to process the upload: " + endpoint + "...");

		final HttpClient httpClient = new DefaultHttpClient();

		try {

			final HttpPost httpPost = new HttpPost(endpoint);

			final List params = newArrayList();

			params.add(new BasicNameValuePair("username", guixerUsername));
			params.add(new BasicNameValuePair("password", guixerPassword));

			httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

			final HttpResponse response = httpClient.execute(httpPost);

			final int statusCode = response.getStatusLine().getStatusCode();

			if (statusCode != 200) {

				throw new RuntimeException("Expected HTTP status: 200, but was: " + statusCode);
			}

		} finally {

			httpClient.getConnectionManager().shutdown();

		}
	}

	private static String byteCountSentSuccessfully(
		final long fileLength
	) {

		final StringBuilder sb = new StringBuilder();

		if (fileLength == 0L) {

			sb.append("0 byte");

		} else if (fileLength == 1L) {

			sb.append("One byte");

		} else {

			sb.append(fileLength + " bytes");
		}

		return sb.append(" sent successfully.").toString();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy