1
2
3
4
5 package net.java.truevfs.driver.tar.gzip;
6
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStream;
10 import java.util.zip.Deflater;
11 import java.util.zip.GZIPInputStream;
12 import javax.annotation.concurrent.Immutable;
13 import net.java.truecommons.io.AbstractSink;
14 import net.java.truecommons.io.AbstractSource;
15 import net.java.truecommons.io.Streams;
16 import net.java.truecommons.shed.BitField;
17 import net.java.truevfs.comp.tardriver.TarDriver;
18 import net.java.truevfs.comp.tardriver.TarDriverEntry;
19 import net.java.truevfs.comp.tardriver.TarInputService;
20 import net.java.truevfs.comp.tardriver.TarOutputService;
21 import net.java.truevfs.kernel.spec.FsAccessOption;
22 import static net.java.truevfs.kernel.spec.FsAccessOption.STORE;
23 import net.java.truevfs.kernel.spec.FsController;
24 import net.java.truevfs.kernel.spec.FsInputSocketSource;
25 import net.java.truevfs.kernel.spec.FsModel;
26 import net.java.truevfs.kernel.spec.FsNodeName;
27 import net.java.truevfs.kernel.spec.FsOutputSocketSink;
28 import net.java.truecommons.cio.InputService;
29 import net.java.truevfs.kernel.spec.cio.MultiplexingOutputService;
30 import net.java.truecommons.cio.OutputService;
31
32
33
34
35
36
37
38
39 @Immutable
40 public class TarGZipDriver extends TarDriver {
41
42
43
44
45
46
47
48
49
50 public int getBufferSize() {
51 return Streams.BUFFER_SIZE;
52 }
53
54
55
56
57
58
59
60
61
62 public int getLevel() {
63 return Deflater.BEST_COMPRESSION;
64 }
65
66 @Override
67 protected InputService<TarDriverEntry> newInput(
68 final FsModel model,
69 final FsInputSocketSource source)
70 throws IOException {
71 final class Source extends AbstractSource {
72 @Override
73 public InputStream stream() throws IOException {
74 final InputStream in = source.stream();
75 try {
76 return new GZIPInputStream(in, getBufferSize());
77 } catch(final Throwable ex) {
78 try {
79 in.close();
80 } catch (final Throwable ex2) {
81 ex.addSuppressed(ex2);
82 }
83 throw ex;
84 }
85 }
86 }
87
88 return new TarInputService(model, new Source(), this);
89 }
90
91 @Override
92 protected OutputService<TarDriverEntry> newOutput(
93 final FsModel model,
94 final FsOutputSocketSink sink,
95 final InputService<TarDriverEntry> input)
96 throws IOException {
97 final class Sink extends AbstractSink {
98 @Override
99 public OutputStream stream() throws IOException {
100 final OutputStream out = sink.stream();
101 try {
102 return new GZIPOutputStream(out, getBufferSize(), getLevel());
103 } catch(final Throwable ex) {
104 try {
105 out.close();
106 } catch (final Throwable ex2) {
107 ex.addSuppressed(ex2);
108 }
109 throw ex;
110 }
111 }
112 }
113
114 return new MultiplexingOutputService<>(getPool(),
115 new TarOutputService(model, new Sink(), this));
116 }
117
118
119
120
121
122 @Override
123 protected FsOutputSocketSink sink(
124 BitField<FsAccessOption> options,
125 final FsController controller,
126 final FsNodeName name) {
127
128
129 options = options.set(STORE);
130 return new FsOutputSocketSink(options,
131 controller.output(options, name, null));
132 }
133
134
135 private static final class GZIPOutputStream
136 extends java.util.zip.GZIPOutputStream {
137 GZIPOutputStream(OutputStream out, int size, int level)
138 throws IOException {
139 super(out, size);
140 def.setLevel(level);
141 }
142 }
143 }