* stable-4.9: Fix ObjectUploadListener#close Fix error handling in FileLfsServlet ObjectDownloadListener#onWritePossible: Make code spec compatible ObjectDownloadListener: Return from onWritePossible when data is written Fix IOException when LockToken#close fails Change-Id: Ib7d01cb0ece8b259156855045a53b8baf3fa2968 Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>tags/v4.11.3.201809181037-r
*/ | */ | ||||
protected static void sendError(HttpServletResponse rsp, int status, String message) | protected static void sendError(HttpServletResponse rsp, int status, String message) | ||||
throws IOException { | throws IOException { | ||||
if (rsp.isCommitted()) { | |||||
rsp.getOutputStream().close(); | |||||
return; | |||||
} | |||||
rsp.reset(); | |||||
rsp.setStatus(status); | rsp.setStatus(status); | ||||
PrintWriter writer = rsp.getWriter(); | PrintWriter writer = rsp.getWriter(); | ||||
LfsGson.toJson(message, writer); | LfsGson.toJson(message, writer); |
private final WritableByteChannel outChannel; | private final WritableByteChannel outChannel; | ||||
private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192); | |||||
private ByteBuffer buffer = ByteBuffer.allocateDirect(8192); | |||||
/** | /** | ||||
* <p>Constructor for ObjectDownloadListener.</p> | * <p>Constructor for ObjectDownloadListener.</p> | ||||
@Override | @Override | ||||
public void onWritePossible() throws IOException { | public void onWritePossible() throws IOException { | ||||
while (out.isReady()) { | while (out.isReady()) { | ||||
if (in.read(buffer) != -1) { | |||||
buffer.flip(); | |||||
outChannel.write(buffer); | |||||
buffer.compact(); | |||||
} else { | |||||
in.close(); | |||||
buffer.flip(); | |||||
while (out.isReady()) { | |||||
if (buffer.hasRemaining()) { | |||||
outChannel.write(buffer); | |||||
} else { | |||||
try { | |||||
buffer.clear(); | |||||
if (in.read(buffer) < 0) { | |||||
buffer = null; | |||||
} else { | |||||
buffer.flip(); | |||||
} | |||||
} catch(Throwable t) { | |||||
LOG.log(Level.SEVERE, t.getMessage(), t); | |||||
buffer = null; | |||||
} finally { | |||||
if (buffer != null) { | |||||
outChannel.write(buffer); | |||||
} else { | |||||
try { | |||||
out.close(); | |||||
} finally { | |||||
context.complete(); | context.complete(); | ||||
} | } | ||||
return; | |||||
} | } | ||||
} | } | ||||
} | } |
channel.close(); | channel.close(); | ||||
// TODO check if status 200 is ok for PUT request, HTTP foresees 204 | // TODO check if status 200 is ok for PUT request, HTTP foresees 204 | ||||
// for successful PUT without response body | // for successful PUT without response body | ||||
response.setStatus(HttpServletResponse.SC_OK); | |||||
if (!response.isCommitted()) { | |||||
response.setStatus(HttpServletResponse.SC_OK); | |||||
} | |||||
} finally { | } finally { | ||||
context.complete(); | context.complete(); | ||||
} | } |
@Override | @Override | ||||
public void close() { | public void close() { | ||||
if (link.isPresent()) { | |||||
try { | |||||
Files.delete(link.get()); | |||||
} catch (IOException e) { | |||||
LOG.error(MessageFormat.format(JGitText.get().closeLockTokenFailed, | |||||
this), e); | |||||
} | |||||
if (!link.isPresent()) { | |||||
return; | |||||
} | |||||
Path p = link.get(); | |||||
if (!Files.exists(p)) { | |||||
return; | |||||
} | |||||
try { | |||||
Files.delete(p); | |||||
} catch (IOException e) { | |||||
LOG.error(MessageFormat | |||||
.format(JGitText.get().closeLockTokenFailed, this), e); | |||||
} | } | ||||
} | } | ||||