Bug 530263 - ContainerCopyFromPage doesn't list all existing files

- fix DockerConnection.readContainerDirectory() method to handle
  the case whereby data is so big it is broken up over multiple
  read calls and not specifically on a line boundary
- add a kludge that retries the call for the path if we get a
  connection is reset by peer error

Change-Id: Id64f77e46fe983cdae8ffb6c7f7d3c3075f16368
Reviewed-on: https://git.eclipse.org/r/156124
Tested-by: Linux Tools Bot <linuxtools-bot@eclipse.org>
Reviewed-by: Jeff Johnston <jjohnstn@redhat.com>
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
index e0e99bc..773a152 100644
--- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
@@ -2267,44 +2267,26 @@
 					ExecCreateParam.attachStderr());
 			final String execId = execCreation.id();
 			final LogStream pty_stream = copyClient.execStart(execId);
+			String lastLine = ""; //$NON-NLS-1$
 			try {
 				while (pty_stream.hasNext()) {
 					ByteBuffer b = pty_stream.next().content();
 					byte[] buffer = new byte[b.remaining()];
 					b.get(buffer);
-					String s = new String(buffer);
+					String s = lastLine + new String(buffer);
 					String[] lines = s.split("\\r?\\n"); //$NON-NLS-1$
-					for (String line : lines) {
-						if (line.trim().startsWith("total")) //$NON-NLS-1$
-							continue; // ignore the total line
-						String[] token = line.split("\\s+"); //$NON-NLS-1$
-						boolean isDirectory = token[0].startsWith("d"); //$NON-NLS-1$
-						boolean isLink = token[0].startsWith("l"); //$NON-NLS-1$
-						if (token.length > 8) {
-							// last token depends on whether we have a link or not
-							String link = null;
-							if (isLink) {
-								String linkname = token[token.length - 1];
-								if (linkname.endsWith("/")) { //$NON-NLS-1$
-									linkname = linkname.substring(0, linkname.length() - 1);
-									isDirectory = true;
-								}
-								IPath linkPath = new Path(path);
-								linkPath = linkPath.append(linkname);
-								link = linkPath.toString();
-								String name = token[token.length - 3];
-								childList.add(new ContainerFileProxy(path, name,
-										isDirectory, isLink, link));
-							} else {
-								String name = token[token.length - 1];
-								// remove quotes and any indicator char
-								name = name.substring(1, name.length()
-										- (name.endsWith("\"") ? 1 : 2));
-								childList.add(new ContainerFileProxy(path, name,
-										isDirectory));
-							}
-						}
+					if (lines.length > 0) {
+						lastLine = lines[lines.length - 1];
+					} else {
+						lastLine = ""; //$NON-NLS-1$
 					}
+					for (int i = 0; i < lines.length - 1; ++i) {
+						String line = lines[i];
+						processDirectoryLine(line, path, childList);
+					}
+				}
+				if (!lastLine.isEmpty()) {
+					processDirectoryLine(lastLine, path, childList);
 				}
 			} finally {
 				if (pty_stream != null)
@@ -2313,11 +2295,48 @@
 					copyClient.close();
 			}
 		} catch (Exception e) {
+			if (e.getCause() instanceof IOException) {
+				// ugly hack as we often get Connection reset by peer exceptions
+				// so retry
+				return readContainerDirectory(id, path);
+			}
 			// e.printStackTrace();
 		}
 		return childList;
 	}
 
+	private void processDirectoryLine(String line, String path,
+			List<ContainerFileProxy> childList) {
+		if (line.trim().startsWith("total")) //$NON-NLS-1$
+			return; // ignore the total line
+		String[] token = line.split("\\s+"); //$NON-NLS-1$
+		boolean isDirectory = token[0].startsWith("d"); //$NON-NLS-1$
+		boolean isLink = token[0].startsWith("l"); //$NON-NLS-1$
+		if (token.length > 8) {
+			// last token depends on whether we have a link or not
+			String link = null;
+			if (isLink) {
+				String linkname = token[token.length - 1];
+				if (linkname.endsWith("/")) { //$NON-NLS-1$
+					linkname = linkname.substring(0, linkname.length() - 1);
+					isDirectory = true;
+				}
+				IPath linkPath = new Path(path);
+				linkPath = linkPath.append(linkname);
+				link = linkPath.toString();
+				String name = token[token.length - 3];
+				childList.add(new ContainerFileProxy(path, name, isDirectory,
+						isLink, link));
+			} else {
+				String name = token[token.length - 1];
+				// remove quotes and any indicator char
+				name = name.substring(1,
+						name.length() - (name.endsWith("\"") ? 1 : 2));
+				childList.add(new ContainerFileProxy(path, name, isDirectory));
+			}
+		}
+	}
+
 	public void execShell(final String id) throws DockerException {
 		try {
 			final ExecCreation execCreation = client.execCreate(id,