Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4d3ad0a

Browse filesBrowse files
committed
Add a caching output stream
1 parent b4b1fb6 commit 4d3ad0a
Copy full SHA for 4d3ad0a

File tree

Expand file treeCollapse file tree

2 files changed

+152
-1
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+152
-1
lines changed
+151Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package org.sonatype.plexus.build.incremental;
2+
3+
/*
4+
* Copyright The Codehaus Foundation.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import java.io.File;
20+
import java.io.IOException;
21+
import java.io.OutputStream;
22+
import java.nio.Buffer;
23+
import java.nio.ByteBuffer;
24+
import java.nio.channels.FileChannel;
25+
import java.nio.file.Path;
26+
import java.nio.file.StandardOpenOption;
27+
28+
/**
29+
* Caching OutputStream to avoid overwriting a file with
30+
* the same content.
31+
*/
32+
class CachingOutputStream extends OutputStream {
33+
private final Path path;
34+
private FileChannel channel;
35+
private ByteBuffer readBuffer;
36+
private ByteBuffer writeBuffer;
37+
private boolean modified;
38+
39+
public CachingOutputStream(File path) throws IOException {
40+
this(requireNonNull(path).toPath());
41+
}
42+
43+
public CachingOutputStream(Path path) throws IOException {
44+
this(path, 32 * 1024);
45+
}
46+
47+
public CachingOutputStream(Path path, int bufferSize) throws IOException {
48+
this.path = requireNonNull(path);
49+
this.channel =
50+
FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
51+
this.readBuffer = ByteBuffer.allocate(bufferSize);
52+
this.writeBuffer = ByteBuffer.allocate(bufferSize);
53+
}
54+
55+
@Override
56+
public void write(int b) throws IOException {
57+
if (writeBuffer.remaining() < 1) {
58+
((Buffer) writeBuffer).flip();
59+
flushBuffer(writeBuffer);
60+
((Buffer) writeBuffer).clear();
61+
}
62+
writeBuffer.put((byte) b);
63+
}
64+
65+
@Override
66+
public void write(byte[] b) throws IOException {
67+
write(b, 0, b.length);
68+
}
69+
70+
@Override
71+
public void write(byte[] b, int off, int len) throws IOException {
72+
if (writeBuffer.remaining() < len) {
73+
((Buffer) writeBuffer).flip();
74+
flushBuffer(writeBuffer);
75+
((Buffer) writeBuffer).clear();
76+
}
77+
int capacity = writeBuffer.capacity();
78+
while (len >= capacity) {
79+
flushBuffer(ByteBuffer.wrap(b, off, capacity));
80+
off += capacity;
81+
len -= capacity;
82+
}
83+
if (len > 0) {
84+
writeBuffer.put(b, off, len);
85+
}
86+
}
87+
88+
@Override
89+
public void flush() throws IOException {
90+
((Buffer) writeBuffer).flip();
91+
flushBuffer(writeBuffer);
92+
((Buffer) writeBuffer).clear();
93+
super.flush();
94+
}
95+
96+
private void flushBuffer(ByteBuffer writeBuffer) throws IOException {
97+
if (modified) {
98+
channel.write(writeBuffer);
99+
} else {
100+
int len = writeBuffer.remaining();
101+
ByteBuffer readBuffer;
102+
if (this.readBuffer.capacity() >= len) {
103+
readBuffer = this.readBuffer;
104+
((Buffer) readBuffer).clear();
105+
readBuffer.limit(len);
106+
} else {
107+
readBuffer = ByteBuffer.allocate(len);
108+
}
109+
while (len > 0) {
110+
int read = channel.read(readBuffer);
111+
if (read <= 0) {
112+
modified = true;
113+
channel.position(channel.position() - readBuffer.position());
114+
channel.write(writeBuffer);
115+
return;
116+
}
117+
len -= read;
118+
}
119+
((Buffer) readBuffer).flip();
120+
if (readBuffer.compareTo(writeBuffer) != 0) {
121+
modified = true;
122+
channel.position(channel.position() - readBuffer.remaining());
123+
channel.write(writeBuffer);
124+
}
125+
}
126+
}
127+
128+
@Override
129+
public void close() throws IOException {
130+
if (channel.isOpen()) {
131+
flush();
132+
long position = channel.position();
133+
if (position != channel.size()) {
134+
modified = true;
135+
channel.truncate(position);
136+
}
137+
channel.close();
138+
}
139+
}
140+
141+
public boolean isModified() {
142+
return modified;
143+
}
144+
145+
private static <T> T requireNonNull(T t) {
146+
if (t == null) {
147+
throw new NullPointerException();
148+
}
149+
return t;
150+
}
151+
}

‎src/main/java/org/sonatype/plexus/build/incremental/DefaultBuildContext.java

Copy file name to clipboardExpand all lines: src/main/java/org/sonatype/plexus/build/incremental/DefaultBuildContext.java
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public boolean hasDelta(List relpaths) {
5151
}
5252

5353
public OutputStream newFileOutputStream(File file) throws IOException {
54-
return new FileOutputStream(file);
54+
return new CachingOutputStream(file);
5555
}
5656

5757
public Scanner newScanner(File basedir) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.