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