/******************************************************************************* * Copyright (c) 2007, 2011 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.pdtextensions.server.internal.lhttpd; 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.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.equinox.internal.p2.core.helpers.TarEntry; import org.eclipse.equinox.internal.p2.core.helpers.TarException; import org.eclipse.equinox.internal.p2.core.helpers.TarInputStream; import org.eclipse.osgi.util.NLS; import org.pdtextensions.server.IPEXInstallableRuntime; import org.pdtextensions.server.PEXServerPlugin; /** * mostly taken from wst * */ @SuppressWarnings("restriction") public abstract class InstallableRuntime2 implements IPEXInstallableRuntime { 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 abstract String getArchiveUrl(); public abstract String getArchivePath(); public int getArchiveSize() { return -1; } public int getFileCount() { return -1; } public abstract String getLicenseURL(); /* * @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, PEXServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.InstallableRuntime2_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(NLS.bind(Messages.InstallableRuntime2_TaskInstallRuntime, this.getName())) { public boolean belongsTo(Object family) { return PEXServerPlugin.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.InstallableRuntime2_DownloadKnownSize : Messages.InstallableRuntime2_DownloadUnknownSize, new Object [] { name, "{0}", Integer.toString(size / 1024) }); //$NON-NLS-1$ SubMonitor progress = SubMonitor.convert(monitor, NLS.bind(msg, "0"), (size > 0) ? size : DEFAULT_DOWNLOAD_SIZE); //$NON-NLS-1$ 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", ""); //$NON-NLS-1$ //$NON-NLS-2$ 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, PEXServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.InstallableRuntime2_ErrorInstallingServer, e.getLocalizedMessage()), e)); } String name = url.getQuery(); // 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, PEXServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.InstallableRuntime2_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")) //$NON-NLS-1$ unzip(in, path, progress.newChild(500)); else if (name.endsWith("tar")) //$NON-NLS-1$ untar(in, path, progress.newChild(500)); else if (name.endsWith("tar.gz")) { //$NON-NLS-1$ File tarFile = File.createTempFile("runtime", ".tar"); //$NON-NLS-1$ //$NON-NLS-2$ tarFile.deleteOnExit(); String tarName = name; progress.subTask(NLS.bind(Messages.InstallableRuntime2_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, PEXServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.InstallableRuntime2_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.InstallableRuntime2_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); try { TarInputStream zin = new TarInputStream(bin); TarEntry entry = zin.getNextEntry(); while (entry != null) { String name = entry.getName(); progress.subTask(NLS.bind(Messages.InstallableRuntime2_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(); } catch (TarException ex) { throw new IOException(ex); } } 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() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } }