@SuppressWarnings("unchecked") private O createArchiveOutputStream(boolean overwrite) throws IOException { O archiveOut; FileOutputStream out; if (!file.exists() || file.length() == 0 || overwrite) { out = new FileOutputStream(file); } else { throw new FileNotFoundException( "can't open for output, check existence or access rights: " + file.getAbsolutePath()); } String pathStr = path.toString(); Set<String> streamCodecs = CompressCodecService.getCodecs(); for (String codec : streamCodecs) { if (pathStr.endsWith("." + codec)) { archiveOut = (O) archiveService .getCodec(getName()) .createArchiveOutputStream(codecService.getCodec(codec).encode(out)); archiveOut.setWatcher(watcher); return archiveOut; } } archiveOut = (O) archiveService.getCodec(getName()).createArchiveOutputStream(out); archiveOut.setWatcher(watcher); return archiveOut; }
@SuppressWarnings("unchecked") private I createArchiveInputStream() throws IOException { I archiveIn; FileInputStream in; if (file.isFile() && file.canRead()) { in = new FileInputStream(file); } else { throw new FileNotFoundException( "can't open for input, check existence or access rights: " + path); } String pathStr = path.toString(); Set<String> streamCodecs = CompressCodecService.getCodecs(); for (String codec : streamCodecs) { if (pathStr.endsWith("." + codec)) { archiveIn = (I) archiveService .getCodec(getName()) .createArchiveInputStream(codecService.getCodec(codec).decode(in)); archiveIn.setWatcher(watcher); return archiveIn; } } archiveIn = (I) archiveService.getCodec(getName()).createArchiveInputStream(in); archiveIn.setWatcher(watcher); return archiveIn; }
/** A basic archive session */ public abstract class ArchiveSession<I extends ArchiveInputStream, O extends ArchiveOutputStream> implements Session<ArchivePacket> { private static final ESLogger logger = ESLoggerFactory.getLogger(ArchiveSession.class.getSimpleName()); private static final CompressCodecService codecService = CompressCodecService.getInstance(); private static final ArchiveService archiveService = ArchiveService.getInstance(); private boolean isOpen; private EnumSet<Mode> mode; private File file; private Path path; private I in; private O out; private BytesProgressWatcher watcher; private long packetCounter; private AtomicLong archiveCounter = new AtomicLong(); protected ArchiveSession(BytesProgressWatcher watcher) { this.watcher = watcher; this.packetCounter = 0L; } public BytesProgressWatcher getWatcher() { if (watcher == null) { watcher = new BytesProgressWatcher(0L); } return watcher; } public abstract String getName(); @Override public synchronized void open(EnumSet<Mode> mode, Path path, File file) throws IOException { if (isOpen) { return; } this.mode = mode; this.file = file; this.path = path; if (mode.contains(Mode.READ)) { this.in = createArchiveInputStream(); this.isOpen = this.in != null; if (!isOpen) { throw new FileNotFoundException( "can't open for input, check existence or access rights: " + file.getAbsolutePath()); } } else if (mode.contains(Mode.WRITE)) { this.out = createArchiveOutputStream(false); this.isOpen = this.out != null; if (!isOpen) { throw new FileNotFoundException( "can't open for output, check existence or access rights: " + file.getAbsolutePath()); } } else if (mode.contains(Mode.OVERWRITE)) { this.out = createArchiveOutputStream(true); this.isOpen = this.out != null; if (!isOpen) { throw new FileNotFoundException( "can't open for output, check existence or access rights: " + file.getAbsolutePath()); } } } @SuppressWarnings("unchecked") private I createArchiveInputStream() throws IOException { I archiveIn; FileInputStream in; if (file.isFile() && file.canRead()) { in = new FileInputStream(file); } else { throw new FileNotFoundException( "can't open for input, check existence or access rights: " + path); } String pathStr = path.toString(); Set<String> streamCodecs = CompressCodecService.getCodecs(); for (String codec : streamCodecs) { if (pathStr.endsWith("." + codec)) { archiveIn = (I) archiveService .getCodec(getName()) .createArchiveInputStream(codecService.getCodec(codec).decode(in)); archiveIn.setWatcher(watcher); return archiveIn; } } archiveIn = (I) archiveService.getCodec(getName()).createArchiveInputStream(in); archiveIn.setWatcher(watcher); return archiveIn; } @SuppressWarnings("unchecked") private O createArchiveOutputStream(boolean overwrite) throws IOException { O archiveOut; FileOutputStream out; if (!file.exists() || file.length() == 0 || overwrite) { out = new FileOutputStream(file); } else { throw new FileNotFoundException( "can't open for output, check existence or access rights: " + file.getAbsolutePath()); } String pathStr = path.toString(); Set<String> streamCodecs = CompressCodecService.getCodecs(); for (String codec : streamCodecs) { if (pathStr.endsWith("." + codec)) { archiveOut = (O) archiveService .getCodec(getName()) .createArchiveOutputStream(codecService.getCodec(codec).encode(out)); archiveOut.setWatcher(watcher); return archiveOut; } } archiveOut = (O) archiveService.getCodec(getName()).createArchiveOutputStream(out); archiveOut.setWatcher(watcher); return archiveOut; } @Override public ArchivePacket newPacket() { return new ArchivePacket(); } @Override public synchronized ArchivePacket read() throws IOException { if (!isOpen()) { throw new IOException("not open"); } if (in == null) { throw new IOException("no input stream found"); } ArchiveEntry entry = in.getNextEntry(); if (entry == null) { return null; } ArchivePacket packet = newPacket(); String name = entry.getName(); packet.meta("name", name); ArchiveUtils.decodeArchiveEntryName(packet, name); int size = (int) entry.getEntrySize(); if (size >= 0) { byte[] b = new byte[size]; // naive but fast, heap may explode int num = in.read(b, 0, size); // fill byte array from stream packet.payload(new String(b)); } else { // slow copy, unknown size (zip deflate method) ByteArrayOutputStream b = new ByteArrayOutputStream(); Streams.copy(in, b); packet.payload(new String(b.toByteArray())); } packetCounter++; return packet; } @Override @SuppressWarnings("unchecked") public synchronized void write(ArchivePacket packet) throws IOException { if (!isOpen()) { throw new IOException("not open"); } if (out == null) { throw new IOException("no output stream found"); } if (packet == null || packet.payload() == null) { throw new IOException("no payload to write for entry"); } byte[] buf = packet.payload().toString().getBytes(); String name = ArchiveUtils.encodeArchiveEntryName(packet); ArchiveEntry entry = out.newArchiveEntry(); entry.setName(name); entry.setLastModified(new Date()); entry.setEntrySize(buf.length); out.putArchiveEntry(entry); out.write(buf); out.closeArchiveEntry(); packetCounter++; if (watcher.getBytesToTransfer() != 0 && watcher.getBytesTransferred() > watcher.getBytesToTransfer()) { logger.debug( "bytes watcher: transferred = {}, rate {}", watcher.getBytesTransferred(), watcher.getRecentByteRatePerSecond()); switchToNextArchive(); watcher.resetWatcher(); } } @Override public synchronized void close() throws IOException { if (!isOpen) { return; } if (out != null) { out.close(); } if (in != null) { in.close(); } this.isOpen = false; } @Override public long getPacketCounter() { return packetCounter; } @Override public boolean isOpen() { return isOpen; } /** * Switches to next archive stream if a certain byte limit was set * * @throws IOException */ private void switchToNextArchive() throws IOException { close(); String filename = file.getName(); String prefix = Long.toString(archiveCounter.get()) + "."; if (filename.startsWith(prefix)) { filename = filename.substring(prefix.length()); } filename = archiveCounter.incrementAndGet() + "." + filename; this.file = new File(file.getParent() + File.separator + filename); this.path = file.toPath(); open(mode, path, file); } }