blob: e443a85ce3e75d1fca35ccfdb0e5e1e8c89267ae [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2009 IBM Corporation 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
*
* Contributors:
* IBM Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.wst.server.core.internal;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.internal.tar.TarEntry;
import org.eclipse.wst.server.core.internal.tar.TarInputStream;
/**
*
*/
public class InstallableRuntime2 implements IInstallableRuntime {
private IConfigurationElement element;
private byte[] BUFFER = null;
// Default sizes (infinite logarithmic progress will be used when default is employed)
private int DEFAULT_DOWNLOAD_SIZE = 10000000;
private int DEFAULT_FILE_COUNT = 1000;
public InstallableRuntime2(IConfigurationElement element) {
super();
this.element = element;
}
/**
*
* @return the id
*/
public String getId() {
try {
return element.getAttribute("id");
} catch (Exception e) {
return null;
}
}
public String getName() {
return getArchivePath();
}
public String getArchiveUrl() {
try {
return element.getAttribute("archiveUrl");
} catch (Exception e) {
// ignore
}
return null;
}
public String getArchivePath() {
try {
return element.getAttribute("archivePath");
} catch (Exception e) {
// ignore
}
return null;
}
public int getArchiveSize() {
try {
String size = element.getAttribute("archiveSize");
return Integer.parseInt(size);
} catch (Exception e) {
// ignore
}
return -1;
}
public int getFileCount() {
try {
String size = element.getAttribute("fileCount");
return Integer.parseInt(size);
} catch (Exception e) {
// ignore
}
return -1;
}
public String getLicenseURL() {
try {
return element.getAttribute("licenseUrl");
} catch (Exception e) {
// ignore
}
return null;
}
/*
* @see IInstallableRuntime#getLicense(IProgressMonitor)
*/
public String getLicense(IProgressMonitor monitor) throws CoreException {
URL url = null;
ByteArrayOutputStream out = null;
try {
String licenseURL = getLicenseURL();
if (licenseURL == null)
return null;
url = new URL(licenseURL);
InputStream in = url.openStream();
out = new ByteArrayOutputStream();
copyWithSize(in, out, null, 0);
return new String(out.toByteArray());
} catch (Exception e) {
if (Trace.WARNING) {
Trace.trace(Trace.STRING_WARNING, "Error loading license", e);
}
throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0,
NLS.bind(Messages.errorInstallingServer, e.getLocalizedMessage()), e));
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
// ignore
}
}
}
/*
* @see IInstallableRuntime#install(IPath)
*/
public void install(final IPath path) {
Job installRuntimeJob = new Job(Messages.jobInstallingRuntime) {
public boolean belongsTo(Object family) {
return ServerPlugin.PLUGIN_ID.equals(family);
}
protected IStatus run(IProgressMonitor monitor) {
try {
install(path, monitor);
} catch (CoreException ce) {
return ce.getStatus();
}
return Status.OK_STATUS;
}
};
installRuntimeJob.schedule();
}
private void copyWithSize(InputStream in, OutputStream out, IProgressMonitor monitor, int size) throws IOException {
if (BUFFER == null)
BUFFER = new byte[8192];
SubMonitor progress = SubMonitor.convert(monitor, size);
int r = in.read(BUFFER);
while (r >= 0) {
out.write(BUFFER, 0, r);
progress.worked(r);
r = in.read(BUFFER);
}
}
private void download(InputStream in, OutputStream out, IProgressMonitor monitor, String name, int size) throws IOException {
if (BUFFER == null)
BUFFER = new byte[8192];
String msg = NLS.bind((size > 0) ? Messages.taskDownloadSizeKnown : Messages.taskDownloadSizeUnknown,
new Object [] { name, "{0}", Integer.toString(size / 1024) });
SubMonitor progress = SubMonitor.convert(monitor, NLS.bind(msg, "0"), (size > 0) ? size : DEFAULT_DOWNLOAD_SIZE);
int r = in.read(BUFFER);
int total = 0;
int lastTotal = 0;
while (r >= 0) {
out.write(BUFFER, 0, r);
total += r;
if (total >= lastTotal + 8192) {
lastTotal = total;
progress.subTask(NLS.bind(msg, Integer.toString(lastTotal / 1024)));
}
progress.worked(r);
// if size is not known, use infinite logarithmic progress
if (size <= 0)
progress.setWorkRemaining(DEFAULT_DOWNLOAD_SIZE);
if (progress.isCanceled())
break;
r = in.read(BUFFER);
}
}
/*
* @see IInstallableRuntime#install(IPath, IProgressMonitor)
*/
public void install(IPath path, IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 1000);
URL url = null;
File temp = null;
try {
url = new URL(getArchiveUrl());
temp = File.createTempFile("runtime", "");
temp.deleteOnExit();
} catch (IOException e) {
if (monitor != null)
monitor.done();
if (Trace.WARNING) {
Trace.trace(Trace.STRING_WARNING,
"Error creating url and temp file", e);
}
throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0,
NLS.bind(Messages.errorInstallingServer, e.getLocalizedMessage()), e));
}
String name = url.getPath();
int slashIdx = name.lastIndexOf('/');
if (slashIdx >= 0)
name = name.substring(slashIdx + 1);
int archiveSize = getArchiveSize();
// download
FileOutputStream fout = null;
try {
InputStream in = url.openStream();
fout = new FileOutputStream(temp);
download(in, fout, progress.newChild(500), name, archiveSize);
progress.setWorkRemaining(500);
} catch (Exception e) {
if (monitor != null)
monitor.done();
if (Trace.WARNING) {
Trace.trace(Trace.STRING_WARNING, "Error downloading runtime",
e);
}
throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0,
NLS.bind(Messages.errorInstallingServer, e.getLocalizedMessage()), e));
} finally {
try {
if (fout != null)
fout.close();
} catch (IOException e) {
// ignore
}
}
if (progress.isCanceled())
throw new CoreException(Status.CANCEL_STATUS);
FileInputStream in = null;
try {
in = new FileInputStream(temp);
if (name.endsWith("zip"))
unzip(in, path, progress.newChild(500));
else if (name.endsWith("tar"))
untar(in, path, progress.newChild(500));
else if (name.endsWith("tar.gz")) {
File tarFile = File.createTempFile("runtime", ".tar");
tarFile.deleteOnExit();
String tarName = name;
if (slashIdx >= 0)
tarName = name.substring(0, name.length() - 3);
progress.subTask(NLS.bind(Messages.taskUncompressing, tarName));
int tempSize = Integer.MAX_VALUE;
if (temp.length() < Integer.MAX_VALUE)
tempSize = (int)temp.length();
ungzip(in, tarFile, progress.newChild(250), tempSize);
progress.setWorkRemaining(250);
if (!progress.isCanceled()) {
in = new FileInputStream(tarFile);
untar(in, path, progress.newChild(250));
}
}
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE, "Error uncompressing runtime",
e);
}
throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0,
NLS.bind(Messages.errorInstallingServer, e.getLocalizedMessage()), e));
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
// ignore
}
progress.done();
}
}
/**
* Unzip the input stream into the given path.
*
* @param in
* @param path
* @param monitor
* @throws IOException
*/
private void unzip(InputStream in, IPath path, IProgressMonitor monitor) throws IOException {
int fileCnt = getFileCount();
SubMonitor progress = SubMonitor.convert(monitor, (fileCnt > 0) ? fileCnt : DEFAULT_FILE_COUNT);
String archivePath = getArchivePath();
BufferedInputStream bin = new BufferedInputStream(in);
ZipInputStream zin = new ZipInputStream(bin);
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
progress.subTask(NLS.bind(Messages.taskUncompressing, name));
if (archivePath != null && name.startsWith(archivePath)) {
name = name.substring(archivePath.length());
if (name.length() > 1)
name = name.substring(1);
}
if (name != null && name.length() > 0) {
if (entry.isDirectory())
path.append(name).toFile().mkdirs();
else {
FileOutputStream fout = new FileOutputStream(path.append(name).toFile());
copyWithSize(zin, fout, progress.newChild(1), (int)entry.getSize());
fout.close();
// if count is not known, use infinite logarithmic progress
if (fileCnt <= 0)
progress.setWorkRemaining(DEFAULT_FILE_COUNT);
}
}
zin.closeEntry();
entry = zin.getNextEntry();
}
zin.close();
}
/**
* Untar the input stream into the given path.
*
* @param in
* @param path
* @param monitor
* @throws IOException
*/
protected void untar(InputStream in, IPath path, IProgressMonitor monitor) throws IOException {
int fileCnt = getFileCount();
SubMonitor progress = SubMonitor.convert(monitor, (fileCnt > 0) ? fileCnt : 500);
String archivePath = getArchivePath();
BufferedInputStream bin = new BufferedInputStream(in);
TarInputStream zin = new TarInputStream(bin);
TarEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
progress.subTask(NLS.bind(Messages.taskUncompressing, name));
if (archivePath != null && name.startsWith(archivePath)) {
name = name.substring(archivePath.length());
if (name.length() > 1)
name = name.substring(1);
}
if (name != null && name.length() > 0) {
if (entry.getFileType() == TarEntry.DIRECTORY)
path.append(name).toFile().mkdirs();
else {
File dir = path.append(name).removeLastSegments(1).toFile();
if (!dir.exists())
dir.mkdirs();
FileOutputStream fout = new FileOutputStream(path.append(name).toFile());
copyWithSize(zin, fout, progress.newChild(1), (int)entry.getSize());
fout.close();
if (fileCnt <= 0)
progress.setWorkRemaining(500);
}
}
entry = zin.getNextEntry();
}
zin.close();
}
protected void ungzip(InputStream in, File tarFile, IProgressMonitor monitor, int size) throws IOException {
GZIPInputStream gzin = null;
FileOutputStream fout = null;
try {
gzin = new GZIPInputStream(in);
fout = new FileOutputStream(tarFile);
copyWithSize(gzin, fout, monitor, size);
} finally {
if (gzin != null) {
try {
gzin.close();
} catch (IOException e) {
// ignore
}
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
// ignore
}
}
}
}
}
public String toString() {
return "InstallableRuntime2[" + getId() + "]";
}
}