in src/main/java/org/apache/sling/servlets/post/impl/helper/SlingFileUploadHandler.java [196:304]
private void processChunk(
final Resource resParent,
final Resource res,
final RequestProperty prop,
final RequestParameter value,
final List<Modification> changes)
throws PersistenceException {
try {
final ModifiableValueMap mvm = res.adaptTo(ModifiableValueMap.class);
long chunkOffset = prop.getChunk().getOffset();
if (chunkOffset == 0) {
// first chunk
// check if another chunk upload is already in progress. throw
// exception
final Iterator<Resource> itr =
new FilteringResourceIterator(res.listChildren(), SlingPostConstants.CHUNK_NODE_NAME);
if (itr.hasNext()) {
throw new PersistenceException("Chunk upload already in progress at {" + res.getPath() + "}");
}
addChunkMixin(mvm);
mvm.put(SlingPostConstants.NT_SLING_CHUNKS_LENGTH, 0);
changes.add(Modification.onModified(res.getPath() + "/" + SlingPostConstants.NT_SLING_CHUNKS_LENGTH));
if (mvm.get(JcrConstants.JCR_DATA) == null) {
// create a empty jcr:data property
mvm.put(JcrConstants.JCR_DATA, new ByteArrayInputStream("".getBytes()));
}
}
if (mvm.get(SlingPostConstants.NT_SLING_CHUNKS_LENGTH) == null) {
throw new PersistenceException("no chunk upload found at {" + res.getPath() + "}");
}
long currentLength = mvm.get(SlingPostConstants.NT_SLING_CHUNKS_LENGTH, Long.class);
long totalLength = prop.getChunk().getLength();
if (chunkOffset != currentLength) {
throw new PersistenceException(
"Chunk's offset {" + chunkOffset + "} doesn't match expected offset {" + currentLength + "}");
}
if (totalLength != 0) {
if (mvm.get(SlingPostConstants.NT_SLING_FILE_LENGTH) != null) {
long expectedLength = mvm.get(SlingPostConstants.NT_SLING_FILE_LENGTH, Long.class);
if (totalLength != expectedLength) {
throw new PersistenceException("File length {"
+ totalLength + "} doesn't match expected length {"
+ expectedLength + "}");
}
} else {
mvm.put(SlingPostConstants.NT_SLING_FILE_LENGTH, totalLength);
}
}
final Iterator<Resource> itr = new FilteringResourceIterator(
res.listChildren(), SlingPostConstants.CHUNK_NODE_NAME + "_" + String.valueOf(chunkOffset));
if (itr.hasNext()) {
throw new PersistenceException(
"Chunk already present at {" + itr.next().getPath() + "}");
}
String nodeName = SlingPostConstants.CHUNK_NODE_NAME + "_"
+ String.valueOf(chunkOffset) + "_"
+ String.valueOf(chunkOffset + value.getSize() - 1);
if (totalLength == (currentLength + value.getSize())
|| prop.getChunk().isCompleted()) {
File file = null;
InputStream fileIns = null;
try {
file = mergeChunks(res, value.getInputStream());
fileIns = new FileInputStream(file);
mvm.put(JcrConstants.JCR_DATA, fileIns);
changes.add(Modification.onModified(res.getPath() + "/" + JcrConstants.JCR_DATA));
final Iterator<Resource> rsrcItr =
new FilteringResourceIterator(res.listChildren(), SlingPostConstants.CHUNK_NODE_NAME);
while (rsrcItr.hasNext()) {
Resource rsrcRange = rsrcItr.next();
changes.add(Modification.onDeleted(rsrcRange.getPath()));
rsrcRange.getResourceResolver().delete(rsrcRange);
}
if (mvm.get(SlingPostConstants.NT_SLING_FILE_LENGTH) != null) {
changes.add(
Modification.onDeleted(res.getPath() + "/" + SlingPostConstants.NT_SLING_FILE_LENGTH));
mvm.remove(SlingPostConstants.NT_SLING_FILE_LENGTH);
}
if (mvm.get(SlingPostConstants.NT_SLING_CHUNKS_LENGTH) != null) {
changes.add(Modification.onDeleted(
res.getPath() + "/" + SlingPostConstants.NT_SLING_CHUNKS_LENGTH));
mvm.remove(SlingPostConstants.NT_SLING_CHUNKS_LENGTH);
}
removeChunkMixin(mvm);
} finally {
try {
fileIns.close();
file.delete();
} catch (IOException ign) {
}
}
} else {
final Map<String, Object> props = new HashMap<>();
props.put(JcrConstants.JCR_DATA, value.getInputStream());
props.put(SlingPostConstants.NT_SLING_CHUNK_OFFSET, chunkOffset);
props.put(SlingPostConstants.NT_SLING_CHUNKS_LENGTH, currentLength + value.getSize());
for (final String key : props.keySet()) {
changes.add(Modification.onModified(res.getPath() + "/" + nodeName + "/" + key));
}
props.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, SlingPostConstants.NT_SLING_CHUNK_NODETYPE);
final Resource rangeRsrc = res.getResourceResolver().create(res, nodeName, props);
changes.add(Modification.onCreated(rangeRsrc.getPath()));
}
} catch (IOException e) {
throw new PersistenceException("Error while retrieving inputstream from parameter value.", e);
}
}