comparison src/org/tmatesoft/hg/internal/FileContentSupplier.java @ 618:7c0d2ce340b8

Refactor approach how content finds it way down to a commit revision
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 16 May 2013 19:46:13 +0200
parents e447384f3771
children 12a4f60ea972
comparison
equal deleted inserted replaced
617:65c01508f002 618:7c0d2ce340b8
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import java.io.File; 19 import java.io.File;
20 import java.io.FileInputStream; 20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.IOException; 21 import java.io.IOException;
23 import java.nio.ByteBuffer; 22 import java.nio.ByteBuffer;
24 import java.nio.channels.FileChannel; 23 import java.nio.channels.FileChannel;
25 24
26 import org.tmatesoft.hg.core.HgIOException; 25 import org.tmatesoft.hg.core.HgIOException;
26 import org.tmatesoft.hg.core.SessionContext;
27 import org.tmatesoft.hg.internal.DataSerializer.DataSource;
27 import org.tmatesoft.hg.repo.HgRepository; 28 import org.tmatesoft.hg.repo.HgRepository;
28 import org.tmatesoft.hg.util.Path; 29 import org.tmatesoft.hg.util.Path;
29 30
30 /** 31 /**
31 * FIXME files are opened at the moment of instantiation, though the moment the data is requested might be distant 32 * {@link DataSource} that reads from regular files
32 * 33 *
33 * @author Artem Tikhomirov 34 * @author Artem Tikhomirov
34 * @author TMate Software Ltd. 35 * @author TMate Software Ltd.
35 */ 36 */
36 public class FileContentSupplier implements CommitFacility.ByteDataSupplier { 37 public class FileContentSupplier implements DataSource {
37 private final FileChannel channel; 38 private final File file;
38 private IOException error; 39 private final SessionContext ctx;
39 40
40 public FileContentSupplier(HgRepository repo, Path file) throws HgIOException { 41 public FileContentSupplier(HgRepository repo, Path file) {
41 this(new File(repo.getWorkingDir(), file.toString())); 42 this(repo, new File(repo.getWorkingDir(), file.toString()));
42 } 43 }
43 44
44 public FileContentSupplier(File f) throws HgIOException { 45 public FileContentSupplier(SessionContext.Source ctxSource, File f) {
45 if (!f.canRead()) { 46 ctx = ctxSource.getSessionContext();
46 throw new HgIOException(String.format("Can't read file %s", f), f); 47 file = f;
47 } 48 }
49
50 public void serialize(DataSerializer out) throws HgIOException {
51 FileInputStream fis = null;
48 try { 52 try {
49 channel = new FileInputStream(f).getChannel(); 53 fis = new FileInputStream(file);
50 } catch (FileNotFoundException ex) { 54 FileChannel fc = fis.getChannel();
51 throw new HgIOException("Can't open file", ex, f); 55 ByteBuffer buffer = ByteBuffer.allocate((int) Math.min(100*1024, fc.size()));
56 while (fc.read(buffer) != -1) {
57 buffer.flip();
58 // #allocate() above ensures backing array
59 out.write(buffer.array(), 0, buffer.limit());
60 buffer.clear();
61 }
62 } catch (IOException ex) {
63 throw new HgIOException("Failed to get content of the file", ex, file);
64 } finally {
65 new FileUtils(ctx.getLog()).closeQuietly(fis);
52 } 66 }
53 } 67 }
54
55 public int read(ByteBuffer buf) {
56 if (error != null) {
57 return -1;
58 }
59 try {
60 return channel.read(buf);
61 } catch (IOException ex) {
62 error = ex;
63 }
64 return -1;
65 }
66 68
67 public void done() throws IOException { 69 public int serializeLength() {
68 channel.close(); 70 return Internals.ltoi(file.length());
69 if (error != null) {
70 throw error;
71 }
72 } 71 }
73 } 72 }