1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.lfs.server.fs;
11
12 import java.io.IOException;
13 import java.nio.ByteBuffer;
14 import java.nio.channels.Channels;
15 import java.nio.channels.ReadableByteChannel;
16 import java.nio.channels.WritableByteChannel;
17 import java.util.logging.Level;
18 import java.util.logging.Logger;
19
20 import javax.servlet.AsyncContext;
21 import javax.servlet.ServletOutputStream;
22 import javax.servlet.WriteListener;
23 import javax.servlet.http.HttpServletResponse;
24
25 import org.apache.http.HttpStatus;
26 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
27 import org.eclipse.jgit.lfs.lib.Constants;
28 import org.eclipse.jgit.util.HttpSupport;
29
30
31
32
33
34
35 public class ObjectDownloadListener implements WriteListener {
36
37 private static final Logger LOG = Logger
38 .getLogger(ObjectDownloadListener.class.getName());
39
40 private final AsyncContext context;
41
42 private final HttpServletResponse response;
43
44 private final ServletOutputStream out;
45
46 private final ReadableByteChannel in;
47
48 private final WritableByteChannel outChannel;
49
50 private ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public ObjectDownloadListener(FileLfsRepository repository,
66 AsyncContext context, HttpServletResponse response,
67 AnyLongObjectId id) throws IOException {
68 this.context = context;
69 this.response = response;
70 this.in = repository.getReadChannel(id);
71 this.out = response.getOutputStream();
72 this.outChannel = Channels.newChannel(out);
73
74 response.addHeader(HttpSupport.HDR_CONTENT_LENGTH,
75 String.valueOf(repository.getSize(id)));
76 response.setContentType(Constants.HDR_APPLICATION_OCTET_STREAM);
77 }
78
79
80
81
82
83
84 @SuppressWarnings("Finally")
85 @Override
86 public void onWritePossible() throws IOException {
87 while (out.isReady()) {
88 try {
89 buffer.clear();
90 if (in.read(buffer) < 0) {
91 buffer = null;
92 } else {
93 buffer.flip();
94 }
95 } catch (Throwable t) {
96 LOG.log(Level.SEVERE, t.getMessage(), t);
97 buffer = null;
98 } finally {
99 if (buffer != null) {
100 outChannel.write(buffer);
101 } else {
102 try {
103 in.close();
104 } catch (IOException e) {
105 LOG.log(Level.SEVERE, e.getMessage(), e);
106 }
107 try {
108 out.close();
109 } finally {
110 context.complete();
111 }
112
113
114
115
116 return;
117 }
118 }
119 }
120 }
121
122
123
124
125
126
127 @Override
128 public void onError(Throwable e) {
129 try {
130 FileLfsServlet.sendError(response,
131 HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage());
132 context.complete();
133 in.close();
134 } catch (IOException ex) {
135 LOG.log(Level.SEVERE, ex.getMessage(), ex);
136 }
137 }
138 }