/******************************************************************************* * Copyright (c) 2013 Atlanmod INRIA LINA Mines Nantes * 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: * Atlanmod INRIA LINA Mines Nantes - initial API and implementation *******************************************************************************/ package fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.internal; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.lang3.StringUtils; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.osgi.util.NLS; import fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.AbstractNeo4jRuntimeInstaller; /** * @author abelgomez * */ public class Neo4jZippedInstaller extends AbstractNeo4jRuntimeInstaller { protected static final int TIMEOUT = 10000; private String id; private String name; private String description; private String licenseText; private URL url; private String version; private List<String> jarFiles = new ArrayList<String>(); private static final int ERROR = -1; private static final int UNDEFINED = -2; private volatile int size = UNDEFINED; public Neo4jZippedInstaller() { Thread checkSizeThread = new Thread() { @Override public void run() { try { URLConnection connection = getUrl().openConnection(); connection.setConnectTimeout(1000); connection.setReadTimeout(1000); size = connection.getContentLength(); } catch (Exception e) { size = ERROR; } notifyListeners(); } }; checkSizeThread.start(); } /** * @return the id */ public String getId() { return id; } /** * @param id the id to set */ public void setId(String id) { this.id = id; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the version */ public String getVersion() { return version; } /** * @param version the version to set */ public void setVersion(String version) { this.version = version; } /** * @return the licenseText */ public String getLicenseText() { return licenseText; } /** * @param licenseText the licenseText to set */ public void setLicenseText(String licenseText) { this.licenseText = licenseText; } /** * @return the url */ public URL getUrl() { return url; } /** * @param url the url to set */ public void setUrl(URL url) { this.url = url; } /** * @return the description */ public String getDescription() { return getDescriptionText(); } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } /** * @return the jarFiles */ public List<String> getJarFiles() { return jarFiles; } public String getDescriptionText() { StringBuilder builder = new StringBuilder(); builder.append(description); int size = getSize(); builder.append("\n"); builder.append("URL: "); builder.append(getUrl().toString()); builder.append("\n"); builder.append("Download size: "); if (size >= 0) { builder.append(FileUtils.byteCountToDisplaySize(size)); } else if (size == UNDEFINED) { builder.append(NLS.bind("Connecting to {0} to get the size...", getUrl().toString())); } else if (size == ERROR){ builder.append(NLS.bind("Unknown (unable to connect to {0})", getUrl().toString())); } return builder.toString(); } protected int getSize() { return size; } /* (non-Javadoc) * @see fr.inria.atlanmod.neo4emf.neo4jresolver.installer.INeo4jInstallerHandler#install(org.eclipse.core.runtime.IProgressMonitor) */ @Override public void performInstall(IProgressMonitor monitor, IPath dirPath) throws IOException { if (monitor == null) { monitor = new NullProgressMonitor(); } InputStream urlStream = null; try { URL url = getUrl(); URLConnection connection = url.openConnection(); connection.setConnectTimeout(TIMEOUT); connection.setReadTimeout(TIMEOUT); int length = connection.getContentLength(); monitor.beginTask( NLS.bind("Reading from {1}", getVersion(), getUrl().toString()), length >= 0 ? length : IProgressMonitor.UNKNOWN); urlStream = connection.getInputStream(); ZipInputStream zipStream = new ZipInputStream(urlStream); byte[] buffer = new byte[1024*8]; long start = System.currentTimeMillis(); int total = length; int totalRead = 0; ZipEntry entry; float kBps = -1; while((entry = zipStream.getNextEntry()) != null) { if (monitor.isCanceled()) break; String fullFilename = entry.getName(); IPath fullFilenamePath = new Path(fullFilename); int secsRemaining = (int) ((total-totalRead)/1024/kBps); String textRemaining = secsToText(secsRemaining); monitor.subTask(NLS.bind("{0} remaining. Reading {1}", textRemaining.length() > 0 ? textRemaining : "unknown time", StringUtils.abbreviateMiddle(fullFilenamePath.removeFirstSegments(1).toString(), "...", 45))); int entrySize = (int) entry.getCompressedSize(); OutputStream output = null; try { int len = 0; int read = 0; String action = null; if (jarFiles.contains(fullFilename)) { action = "Copying"; String filename = FilenameUtils.getName(fullFilename); output = new FileOutputStream(dirPath.append(filename).toOSString()); } else { action = "Skipping"; output = new NullOutputStream(); } int secs = (int) ((System.currentTimeMillis() - start) / 1000); kBps = (float) totalRead/1024/secs; while ((len = zipStream.read(buffer)) > 0) { if (monitor.isCanceled()) break; read += len; monitor.subTask(NLS.bind("{0} remaining. {1} {2} at {3}KB/s ({4}KB / {5}KB)", new Object[] { String.format("%s", textRemaining.length() > 0 ? textRemaining : "unknown time"), action, StringUtils.abbreviateMiddle(fullFilenamePath.removeFirstSegments(1).toString(), "...", 45), String.format("%,.1f", kBps), String.format("%,.1f", (float) read/1024), String.format("%,.1f", (float) entry.getSize()/1024) })); output.write(buffer, 0, len); } totalRead += entrySize; monitor.worked(entrySize); } finally { IOUtils.closeQuietly(output); } } } finally { IOUtils.closeQuietly(urlStream); monitor.done(); } } /** * @param secsRemaining * @return */ private String secsToText(int secsRemaining) { if (secsRemaining < 0) return ""; int mins = secsRemaining / 60; int secs = secsRemaining % 60; StringBuilder builder = new StringBuilder(); if (mins > 0) builder.append(NLS.bind("{0}min ", mins)); if (mins > 0 && secs > 0) builder.append("and "); if (secs > 0) builder.append(NLS.bind("{0}s", secs)); return builder.toString(); } }