Mercurial > jhg
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 } |