1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.lfs.server.fs;
44
45 import java.io.FileNotFoundException;
46 import java.io.IOException;
47 import java.nio.ByteBuffer;
48 import java.nio.channels.Channels;
49 import java.nio.channels.ReadableByteChannel;
50 import java.nio.channels.WritableByteChannel;
51 import java.util.logging.Level;
52 import java.util.logging.Logger;
53
54 import javax.servlet.AsyncContext;
55 import javax.servlet.ReadListener;
56 import javax.servlet.ServletInputStream;
57 import javax.servlet.http.HttpServletRequest;
58 import javax.servlet.http.HttpServletResponse;
59
60 import org.apache.http.HttpStatus;
61 import org.eclipse.jgit.lfs.errors.CorruptLongObjectException;
62 import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream;
63 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
64 import org.eclipse.jgit.lfs.lib.Constants;
65
66
67
68
69
70
71 public class ObjectUploadListener implements ReadListener {
72
73 private static Logger LOG = Logger
74 .getLogger(ObjectUploadListener.class.getName());
75
76 private final AsyncContext context;
77
78 private final HttpServletResponse response;
79
80 private final ServletInputStream in;
81
82 private final ReadableByteChannel inChannel;
83
84 private final AtomicObjectOutputStream out;
85
86 private WritableByteChannel channel;
87
88 private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
89
90
91
92
93
94
95
96
97
98
99
100 public ObjectUploadListener(FileLfsRepository repository,
101 AsyncContext context, HttpServletRequest request,
102 HttpServletResponse response, AnyLongObjectId id)
103 throws FileNotFoundException, IOException {
104 this.context = context;
105 this.response = response;
106 this.in = request.getInputStream();
107 this.inChannel = Channels.newChannel(in);
108 this.out = repository.getOutputStream(id);
109 this.channel = Channels.newChannel(out);
110 response.setContentType(Constants.CONTENT_TYPE_GIT_LFS_JSON);
111 }
112
113
114
115
116
117
118 @Override
119 public void onDataAvailable() throws IOException {
120 while (in.isReady()) {
121 if (inChannel.read(buffer) > 0) {
122 buffer.flip();
123 channel.write(buffer);
124 buffer.compact();
125 } else {
126 buffer.flip();
127 while (buffer.hasRemaining()) {
128 channel.write(buffer);
129 }
130 close();
131 return;
132 }
133 }
134 }
135
136
137
138
139 @Override
140 public void onAllDataRead() throws IOException {
141 close();
142 }
143
144
145
146
147 protected void close() throws IOException {
148 try {
149 inChannel.close();
150 channel.close();
151
152
153 response.setStatus(HttpServletResponse.SC_OK);
154 } finally {
155 context.complete();
156 }
157 }
158
159
160
161
162
163 @Override
164 public void onError(Throwable e) {
165 try {
166 out.abort();
167 inChannel.close();
168 channel.close();
169 int status;
170 if (e instanceof CorruptLongObjectException) {
171 status = HttpStatus.SC_BAD_REQUEST;
172 LOG.log(Level.WARNING, e.getMessage(), e);
173 } else {
174 status = HttpStatus.SC_INTERNAL_SERVER_ERROR;
175 LOG.log(Level.SEVERE, e.getMessage(), e);
176 }
177 FileLfsServlet.sendError(response, status, e.getMessage());
178 } catch (IOException ex) {
179 LOG.log(Level.SEVERE, ex.getMessage(), ex);
180 }
181 }
182 }