[153800] Installable runtime tar support
diff --git a/plugins/org.eclipse.wst.server.core/schema/installableRuntimes.exsd b/plugins/org.eclipse.wst.server.core/schema/installableRuntimes.exsd
index faa16ea..8be2925 100644
--- a/plugins/org.eclipse.wst.server.core/schema/installableRuntimes.exsd
+++ b/plugins/org.eclipse.wst.server.core/schema/installableRuntimes.exsd
@@ -13,7 +13,8 @@
<element name="extension">
<complexType>
<sequence>
- <element ref="installableRuntime" minOccurs="1" maxOccurs="unbounded"/>
+ <element ref="installableRuntime" minOccurs="0" maxOccurs="unbounded"/>
+ <element ref="runtime" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
@@ -42,7 +43,7 @@
<element name="installableRuntime">
<annotation>
<appInfo>
- <meta.element labelAttribute="name"/>
+ <meta.element labelAttribute="name" deprecated="true"/>
</appInfo>
</annotation>
<complexType>
@@ -79,6 +80,9 @@
<documentation>
the id of the bundle in which the runtime zip is in
</documentation>
+ <appInfo>
+ <meta.attribute deprecated="true"/>
+ </appInfo>
</annotation>
</attribute>
<attribute name="bundleVersion" type="string">
@@ -86,13 +90,57 @@
<documentation>
the optional version of the bundle in which the runtime zip is in
</documentation>
+ <appInfo>
+ <meta.attribute deprecated="true"/>
+ </appInfo>
</annotation>
</attribute>
- <attribute name="path" type="string" use="required">
+ <attribute name="path" type="string">
<annotation>
<documentation>
if bundleId is specified then represents the relative path of the runtime zip inside the bundle, otherwise it assumes a relative path of the runtime archive inside the feature directory
</documentation>
+ <appInfo>
+ <meta.attribute deprecated="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="runtime">
+ <annotation>
+ <appInfo>
+ <meta.element labelAttribute="id"/>
+ </appInfo>
+ </annotation>
+ <complexType>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ specifies a unique identifier for this extension point
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="url" type="string" use="required">
+ <annotation>
+ <documentation>
+ a URL to the runtime download
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="licenseUrl" type="string">
+ <annotation>
+ <documentation>
+ a URL to the runtime license
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="platform" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
</annotation>
</attribute>
</complexType>
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/InstallableRuntime2.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/InstallableRuntime2.java
new file mode 100644
index 0000000..0843fff
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/InstallableRuntime2.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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.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;
+
+ 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 getURL() {
+ try {
+ return element.getAttribute("url");
+ } catch (Exception e) {
+ // ignore
+ }
+ return null;
+ }
+
+ 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;
+ try {
+ url = new URL(getLicenseURL());
+ InputStream in = url.openStream();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buf = new byte[8192];
+ copy(buf, in, out);
+ return new String(out.toByteArray());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ /*
+ * @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 copy(byte[] buf, InputStream in, OutputStream out) throws IOException {
+ int r = in.read(buf);
+ while (r >= 0) {
+ out.write(buf, 0, r);
+ r = in.read(buf);
+ }
+ }
+
+ /*
+ * @see IInstallableRuntime#install(IPath, IProgressMonitor)
+ */
+ public void install(IPath path, IProgressMonitor monitor) throws CoreException {
+ URL url = null;
+ File temp = null;
+ try {
+ url = new URL(getURL());
+ temp = File.createTempFile("runtime", "");
+ temp.deleteOnExit();
+ } catch (IOException e) {
+ throw new CoreException(null);
+ }
+ String name = url.getPath();
+
+ // download
+ try {
+ InputStream in = url.openStream();
+ FileOutputStream fout = new FileOutputStream(temp);
+ byte[] buf = new byte[8192];
+ copy(buf, in, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try {
+ FileInputStream in = new FileInputStream(temp);
+ if (name.endsWith("zip"))
+ unzip(in, path, monitor);
+ else if (name.endsWith("tar"))
+ untar(in, path, monitor);
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error uncompressing runtime", e);
+ throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0,
+ NLS.bind(Messages.errorInstallingServer, e.getLocalizedMessage()), e));
+ }
+ }
+
+ private void unzip(InputStream in, IPath path, IProgressMonitor monitor) throws IOException {
+ // unzip from bundle into path
+ BufferedInputStream bin = new BufferedInputStream(in);
+ ZipInputStream zin = new ZipInputStream(bin);
+ ZipEntry entry = zin.getNextEntry();
+ byte[] buf = new byte[8192];
+ while (entry != null) {
+ String name = entry.getName();
+ monitor.setTaskName("Unzipping: " + name);
+
+ if (entry.isDirectory())
+ path.append(name).toFile().mkdirs();
+ else {
+ FileOutputStream fout = new FileOutputStream(path.append(name).toFile());
+ copy(buf, zin, fout);
+ }
+ zin.closeEntry();
+ entry = zin.getNextEntry();
+ }
+ zin.close();
+ }
+
+ protected void untar(InputStream in, IPath path, IProgressMonitor monitor) throws IOException {
+ // untar from bundle into path
+ BufferedInputStream bin = new BufferedInputStream(in);
+ TarInputStream zin = new TarInputStream(bin);
+ TarEntry entry = zin.getNextEntry();
+ byte[] buf = new byte[8192];
+ while (entry != null) {
+ String name = entry.getName();
+ monitor.setTaskName("Untarring: " + name);
+
+ if (entry.getFileType() == TarEntry.DIRECTORY)
+ path.append(name).toFile().mkdirs();
+ else {
+ FileOutputStream fout = new FileOutputStream(path.append(name).toFile());
+ copy(buf, zin, fout);
+ }
+ zin.close();
+ entry = zin.getNextEntry();
+ }
+ zin.close();
+ }
+
+ public String toString() {
+ return "InstallableRuntime2[" + getId() + "]";
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
index c3494ac..9e60286 100644
--- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
@@ -1060,7 +1060,12 @@
List<IInstallableRuntime> list = new ArrayList<IInstallableRuntime>(size);
for (int i = 0; i < size; i++) {
try {
- list.add(new InstallableRuntime(cf[i]));
+ if ("runtime".equals(cf[i].getName())) {
+ String platform = cf[i].getAttribute("platform");
+ //if (platform == null || Swt.g) TODO
+ list.add(new InstallableRuntime2(cf[i]));
+ } else
+ list.add(new InstallableRuntime(cf[i]));
Trace.trace(Trace.EXTENSION_POINT, " Loaded installableRuntime: " + cf[i].getAttribute("id"));
} catch (Throwable t) {
Trace.trace(Trace.SEVERE, " Could not load installableRuntime: " + cf[i].getAttribute("id"), t);
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarEntry.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarEntry.java
similarity index 93%
rename from plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarEntry.java
rename to plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarEntry.java
index f71ade8..4d97196 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarEntry.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarEntry.java
@@ -8,15 +8,14 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.wst.server.ui.internal.downloadableRuntime;
-
+package org.eclipse.wst.server.core.internal.tar;
/**
* Representation of a file in a tar archive.
- *
- * @since 3.1
+ * <p>
+ * Copied from org.eclipse.ui.internal.wizards.datatransfer.
+ * </p>
*/
-public class TarEntry implements Cloneable
-{
+public class TarEntry implements Cloneable {
private String name;
private long mode, time, size;
private int type;
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarException.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarException.java
similarity index 70%
rename from plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarException.java
rename to plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarException.java
index 7e82894..1a3b1fd 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarException.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 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
@@ -8,12 +8,16 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.wst.server.ui.internal.downloadableRuntime;
+package org.eclipse.wst.server.core.internal.tar;
+import java.io.IOException;
/**
* Exception generated upon encountering corrupted tar files.
+ * <p>
+ * Copied from org.eclipse.ui.internal.wizards.datatransfer.
+ * </p>
*/
-public class TarException extends Exception {
+public class TarException extends IOException {
/**
* Generated serial version UID for this class.
*/
@@ -34,14 +38,4 @@
public TarException(String s) {
super(s);
}
-
- /**
- * Constructs a TarException with the specified detail string.
- *
- * @param s the detail string
- * @param cause the cause
- */
- public TarException(String s, Throwable cause) {
- super(s, cause);
- }
-}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarFile.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarFile.java
similarity index 96%
rename from plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarFile.java
rename to plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarFile.java
index e2f30c2..0d97478 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarFile.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarFile.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.wst.server.ui.internal.downloadableRuntime;
+package org.eclipse.wst.server.core.internal.tar;
import java.io.File;
import java.io.FileInputStream;
@@ -20,8 +20,9 @@
* Reads a .tar or .tar.gz archive file, providing an index enumeration
* and allows for accessing an InputStream for arbitrary files in the
* archive.
- *
- * @since 3.1
+ * <p>
+ * Copied from org.eclipse.ui.internal.wizards.datatransfer.
+ * </p>
*/
public class TarFile {
private File file;
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarInputStream.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarInputStream.java
similarity index 95%
rename from plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarInputStream.java
rename to plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarInputStream.java
index 7df6b1c..1eb16f3 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarInputStream.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/tar/TarInputStream.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 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
@@ -8,21 +8,20 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.wst.server.ui.internal.downloadableRuntime;
+package org.eclipse.wst.server.core.internal.tar;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-
/**
* Input stream for reading files in ustar format (tar) compatible
* with the specification in IEEE Std 1003.1-2001. Also supports
* long filenames encoded using the GNU @LongLink extension.
- *
- * @since 3.1
+ * <p>
+ * Copied from org.eclipse.ui.internal.wizards.datatransfer.
+ * </p>
*/
-public class TarInputStream extends FilterInputStream
-{
+public class TarInputStream extends FilterInputStream {
private int nextEntry = 0;
private int nextEOF = 0;
private int filepos = 0;
@@ -243,7 +242,7 @@
long fileMode = Long.decode(mode.toString()).longValue();
entry.setMode(fileMode);
} catch(NumberFormatException nfe) { // TODO
- throw new TarException("TarImport_invalid_tar_format", nfe);
+ throw new TarException("TarImport_invalid_tar_format" + nfe);
}
pos = 100 + 24;
@@ -264,7 +263,7 @@
try {
fileSize = Integer.decode(size.toString()).intValue();
} catch(NumberFormatException nfe) { // TODO
- throw new TarException("DataTransferMessages.TarImport_invalid_tar_format", nfe);
+ throw new TarException("DataTransferMessages.TarImport_invalid_tar_format" + nfe);
}
entry.setSize(fileSize);
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/HttpResponse.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/HttpResponse.java
deleted file mode 100644
index fbcf38a..0000000
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/HttpResponse.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.ui.internal.downloadableRuntime;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLConnection;
-
-import org.eclipse.wst.server.ui.internal.Trace;
-
-public class HttpResponse {
- protected URLConnection connection;
-
- protected URL url;
-
- protected InputStream in;
-
- protected long lastModified;
-
- protected long offset;
-
- protected HttpResponse(URL url) {
- this.url = url;
- }
-
- protected URLConnection getConnection() throws IOException {
- if (connection == null)
- connection = url.openConnection();
- //if (offset > 0)
- // connection.setRequestProperty("Range", "bytes=" + offset + "-");
- return connection;
- }
-
- public InputStream getInputStream() throws IOException {
- if (in == null && url != null) {
- if (connection == null || offset > 0)
- connection = getConnection();
- if (offset > 0)
- connection.setRequestProperty("Range", "bytes=" + offset + "-");
- try {
- in = connection.getInputStream();
- } catch (IOException ioe) {
- connection = null;
- throw ioe;
- }
- //checkOffset();
- }
- return in;
- }
-
- public void close() {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- // ignore
- }
- in = null;
- }
- if (connection != null) {
- ((HttpURLConnection) connection).disconnect();
- connection = null;
- }
- }
-
- public long getContentLength() {
- if (connection != null)
- return connection.getContentLength();
- return 0;
- }
-
- public int getStatusCode() {
- try {
- getConnection();
- return ((HttpURLConnection) connection).getResponseCode();
- } catch (IOException e) {
- Trace.trace(Trace.SEVERE, "Error getting status code", e);
- }
-
- return HttpURLConnection.HTTP_BAD_REQUEST;
- }
-
- public String getStatusMessage() {
- try {
- if (connection != null)
- return ((HttpURLConnection) connection).getResponseMessage();
- } catch (IOException e) {
- Trace.trace(Trace.SEVERE, "Error getting status message", e);
- }
-
- return "";
- }
-
- public long getLastModified() {
- if (lastModified == 0) {
- try {
- if (connection == null)
- connection = getConnection();
-
- lastModified = connection.getLastModified();
- } catch (IOException e) {
- Trace.trace(Trace.SEVERE, "Error opening connection", e);
- }
- }
- return lastModified;
- }
-
- public void setOffset(long offset) {
- this.offset = offset;
- }
-
-/* private void checkOffset() throws IOException {
- if (offset == 0)
- return;
- String range = connection.getHeaderField("Content-Range");
- //System.out.println("Content-Range=" + range);
- if (range == null) {
- //System.err.println("Server does not support ranges");
- throw new IOException(Messages.HttpResponse_rangeExpected);
- } else if (!range.startsWith("bytes " + offset + "-")) {
- //System.err.println("Server returned wrong range");
- throw new IOException(Messages.HttpResponse_wrongRange);
- }
- }*/
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarOutputStream.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarOutputStream.java
deleted file mode 100644
index 6d51507..0000000
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/downloadableRuntime/TarOutputStream.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2006 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.ui.internal.downloadableRuntime;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Output stream for writing ustar archive files (tar) compatible
- * with the specification in IEEE Std 1003.1-2001.
- *
- * @since 3.1
- */
-public class TarOutputStream extends FilterOutputStream {
- private int byteswritten = 0;
- private int datapos = 0;
- private long cursize = 0;
-
- /**
- * Creates a new tar output stream.
- *
- * @param out the stream to write to
- */
- public TarOutputStream(OutputStream out) {
- super(out);
- }
-
- /*
- * Close the output stream and write any necessary padding.
- */
- public void close() throws IOException {
- // Spec says to write 1024 bytes of zeros at the end.
- byte[] zeros = new byte[1024];
- cursize = 1024;
- write(zeros, 0, 1024);
-
- // Default block size for tar files is 10240, so we have to
- // pad the end of the file to be a multiple of this size.
- if((byteswritten % 10240) != 0) {
- int length = 10240 - (byteswritten % 10240);
- cursize = length;
- zeros = new byte[length];
- write(zeros, 0, length);
- }
- super.close();
- }
-
- /**
- * Close the current entry in the tar file. Must be called
- * after each entry is completed.
- *
- * @throws IOException
- */
- public void closeEntry() throws IOException {
- byte[] data = new byte[512];
- int len = 512 - datapos;
- if(len > 0 && datapos > 0) {
- cursize = len;
- write(data, 0, len);
- }
- }
-
- /**
- * The checksum of a tar file header is simply the sum of the bytes in
- * the header.
- *
- * @param header
- * @return checksum
- */
- private long headerChecksum(byte[] header) {
- long sum = 0;
- for(int i = 0; i < 512; i++) {
- sum += header[i] & 0xff;
- }
- return sum;
- }
-
- /**
- * Adds an entry for a new file in the tar archive.
- *
- * @param e TarEntry describing the file
- * @throws IOException
- */
- public void putNextEntry(TarEntry e) throws IOException {
- byte[] header = new byte[512];
- String filename = e.getName();
- String prefix = null;
- int pos, i;
-
- /* Split filename into name and prefix if necessary. */
- byte[] filenameBytes = filename.getBytes("UTF8"); //$NON-NLS-1$
- if (filenameBytes.length > 99) {
- int seppos = filename.lastIndexOf('/');
- if(seppos == -1) {
- throw new IOException("filename too long"); //$NON-NLS-1$
- }
- prefix = filename.substring(0, seppos);
- filename = filename.substring(seppos + 1);
- filenameBytes = filename.getBytes("UTF8"); //$NON-NLS-1$
- if (filenameBytes.length > 99) {
- throw new IOException("filename too long"); //$NON-NLS-1$
- }
- }
-
- /* Filename. */
- pos = 0;
- System.arraycopy(filenameBytes, 0, header, 0, filenameBytes.length);
- pos += 100;
-
- /* File mode. */
- StringBuffer mode = new StringBuffer(Long.toOctalString(e.getMode()));
- while(mode.length() < 7) {
- mode.insert(0,'0');
- }
- for(i = 0; i < 7; i++) {
- header[pos + i] = (byte) mode.charAt(i);
- }
- pos += 8;
-
- /* UID. */
- header[pos] = '0';
- pos += 8;
-
- /* GID. */
- header[pos] = '0';
- pos += 8;
-
- /* Length of the file. */
- String length = Long.toOctalString(e.getSize());
- for(i = 0; i < length.length(); i++) {
- header[pos + i] = (byte) length.charAt(i);
- }
- pos += 12;
-
- /* mtime */
- String mtime = Long.toOctalString(e.getTime());
- for(i = 0; i < mtime.length(); i++) {
- header[pos + i] = (byte) mtime.charAt(i);
- }
- pos += 12;
-
- /* "Blank" out the checksum. */
- for(i = 0; i < 8; i++) {
- header[pos + i] = ' ';
- }
- pos += 8;
-
- /* Link flag. */
- header[pos] = (byte) e.getFileType();
- pos += 1;
-
- /* Link destination. */
- pos += 100;
-
- /* Add ustar header. */
- String ustar = "ustar 00"; //$NON-NLS-1$
- for(i = 0; i < ustar.length(); i++) {
- header[pos + i] = (byte) ustar.charAt(i);
- }
- header[pos + 5] = 0;
- pos += 8;
-
- /* Username. */
- String uname = "nobody"; //$NON-NLS-1$
- for(i = 0; i < uname.length(); i++) {
- header[pos + i] = (byte) uname.charAt(i);
- }
- pos += 32;
-
-
- /* Group name. */
- String gname = "nobody"; //$NON-NLS-1$
- for(i = 0; i < gname.length(); i++) {
- header[pos + i] = (byte) gname.charAt(i);
- }
- pos += 32;
-
- /* Device major. */
- pos += 8;
-
- /* Device minor. */
- pos += 8;
-
- /* File prefix. */
- if(prefix != null) {
- byte[] prefixBytes = prefix.getBytes("UTF8"); //$NON-NLS-1$
- if (prefixBytes.length > 155) {
- throw new IOException("prefix too large"); //$NON-NLS-1$
- }
- System.arraycopy(prefixBytes, 0, header, pos, prefixBytes.length);
- }
-
- long sum = headerChecksum(header);
- pos = 100 + 8 + 8 + 8 + 12 + 12;
- String sumval = Long.toOctalString(sum);
- for(i = 0; i < sumval.length(); i++) {
- header[pos + i] = (byte) sumval.charAt(i);
- }
-
- cursize = 512;
- write(header, 0, 512);
-
- cursize = e.getSize();
- }
-
- /*
- * Writes data for the current file into the archive.
- */
- public void write(byte[] b, int off, int len) throws IOException {
- super.write(b, off, len);
- datapos = (datapos + len) % 512;
- byteswritten += len;
- cursize -= len;
- if(cursize < 0) {
- throw new IOException("too much data written for current file"); //$NON-NLS-1$
- }
- }
-}