1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.index.reader;
20
21 import java.io.Closeable;
22 import java.io.DataOutput;
23 import java.io.DataOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.util.Date;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.zip.GZIPOutputStream;
30
31
32
33
34
35
36
37
38 public class ChunkWriter implements Closeable {
39 private static final int F_INDEXED = 1;
40
41 private static final int F_TOKENIZED = 2;
42
43 private static final int F_STORED = 4;
44
45 private final String chunkName;
46
47 private final DataOutputStream dataOutputStream;
48
49 private final int version;
50
51 private final Date timestamp;
52
53 public ChunkWriter(final String chunkName, final OutputStream outputStream, final int version, final Date timestamp)
54 throws IOException {
55 this.chunkName = chunkName.trim();
56 this.dataOutputStream = new DataOutputStream(new GZIPOutputStream(outputStream, 2 * 1024));
57 this.version = version;
58 this.timestamp = timestamp;
59
60 dataOutputStream.writeByte(version);
61 dataOutputStream.writeLong(timestamp == null ? -1 : timestamp.getTime());
62 }
63
64
65
66
67 public String getName() {
68 return chunkName;
69 }
70
71
72
73
74 public int getVersion() {
75 return version;
76 }
77
78
79
80
81 public Date getTimestamp() {
82 return timestamp;
83 }
84
85
86
87
88 public int writeChunk(final Iterator<Map<String, String>> iterator) throws IOException {
89 int written = 0;
90 while (iterator.hasNext()) {
91 writeRecord(iterator.next(), dataOutputStream);
92 written++;
93 }
94 return written;
95 }
96
97
98
99
100 @Override
101 public void close() throws IOException {
102 dataOutputStream.close();
103 }
104
105 private static void writeRecord(final Map<String, String> record, final DataOutput dataOutput) throws IOException {
106 dataOutput.writeInt(record.size());
107 for (Map.Entry<String, String> entry : record.entrySet()) {
108 writeField(entry.getKey(), entry.getValue(), dataOutput);
109 }
110 }
111
112 private static void writeField(final String fieldName, final String fieldValue, final DataOutput dataOutput)
113 throws IOException {
114 boolean isIndexed = !(fieldName.equals("i") || fieldName.equals("m"));
115 boolean isTokenized =
116 !(fieldName.equals("i") || fieldName.equals("m") || fieldName.equals("1") || fieldName.equals("px"));
117 int flags = (isIndexed ? F_INDEXED : 0) + (isTokenized ? F_TOKENIZED : 0) + F_STORED;
118 dataOutput.writeByte(flags);
119 dataOutput.writeUTF(fieldName);
120 writeUTF(fieldValue, dataOutput);
121 }
122
123 private static void writeUTF(final String str, final DataOutput dataOutput) throws IOException {
124 int strlen = str.length();
125 int utflen = 0;
126 int c;
127
128 for (int i = 0; i < strlen; i++) {
129 c = str.charAt(i);
130 if ((c >= 0x0001) && (c <= 0x007F)) {
131 utflen++;
132 } else if (c > 0x07FF) {
133 utflen += 3;
134 } else {
135 utflen += 2;
136 }
137 }
138 dataOutput.writeInt(utflen);
139 byte[] bytearr = new byte[utflen];
140 int count = 0;
141 int i = 0;
142 for (; i < strlen; i++) {
143 c = str.charAt(i);
144 if (!((c >= 0x0001) && (c <= 0x007F))) {
145 break;
146 }
147 bytearr[count++] = (byte) c;
148 }
149 for (; i < strlen; i++) {
150 c = str.charAt(i);
151 if ((c >= 0x0001) && (c <= 0x007F)) {
152 bytearr[count++] = (byte) c;
153
154 } else if (c > 0x07FF) {
155 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
156 bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
157 bytearr[count++] = (byte) (0x80 | ((c) & 0x3F));
158 } else {
159 bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
160 bytearr[count++] = (byte) (0x80 | ((c) & 0x3F));
161 }
162 }
163 dataOutput.write(bytearr, 0, utflen);
164 }
165 }