mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged HEAD (5.2) to 5.2.N (5.2.1)
126412 jkaabimofrad: Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2) 121563 jkaabimofrad: RA-640: Fixed encoding issue when updating binary content, as well as, multipart uploading. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@126758 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -112,6 +112,8 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.Content;
|
||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
||||
import org.springframework.http.InvalidMediaTypeException;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Centralises access to file/folder/node services and maps between representations.
|
||||
@@ -719,7 +721,7 @@ public class NodesImpl implements Nodes
|
||||
|
||||
protected Set<QName> mapToNodeAspects(List<String> aspectNames)
|
||||
{
|
||||
Set<QName> nodeAspects = new HashSet<>(aspectNames.size());
|
||||
Set<QName> nodeAspects = new HashSet<>(aspectNames.size());
|
||||
|
||||
for (String aspectName : aspectNames)
|
||||
{
|
||||
@@ -732,7 +734,7 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Unknown aspect: "+aspectName);
|
||||
throw new InvalidArgumentException("Unknown aspect: " + aspectName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,7 +747,7 @@ public class NodesImpl implements Nodes
|
||||
|
||||
for (Entry<String, Object> entry : props.entrySet())
|
||||
{
|
||||
String propName = entry.getKey();
|
||||
String propName = entry.getKey();
|
||||
QName propQName = createQName(propName);
|
||||
|
||||
PropertyDefinition pd = dictionaryService.getProperty(propQName);
|
||||
@@ -772,7 +774,7 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Unknown property: "+propName);
|
||||
throw new InvalidArgumentException("Unknown property: " + propName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -993,7 +995,7 @@ public class NodesImpl implements Nodes
|
||||
if (aspectNames != null)
|
||||
{
|
||||
// node aspects - set any additional aspects
|
||||
Set<QName> aspectQNames = mapToNodeAspects(aspectNames);
|
||||
Set<QName> aspectQNames = mapToNodeAspects(aspectNames);
|
||||
for (QName aspectQName : aspectQNames)
|
||||
{
|
||||
if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE))
|
||||
@@ -1009,17 +1011,7 @@ public class NodesImpl implements Nodes
|
||||
{
|
||||
// add empty file
|
||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
String mimeType;
|
||||
ContentInfo contentInfo = nodeInfo.getContent();
|
||||
if (contentInfo != null && contentInfo.getMimeType() != null)
|
||||
{
|
||||
mimeType = contentInfo.getMimeType();
|
||||
}
|
||||
else
|
||||
{
|
||||
mimeType = mimetypeService.guessMimetype(nodeName);
|
||||
}
|
||||
writer.setMimetype(mimeType);
|
||||
setWriterContentType(writer, new ContentInfoWrapper(nodeInfo.getContent()), nodeRef, false);
|
||||
writer.putContent("");
|
||||
}
|
||||
|
||||
@@ -1302,18 +1294,7 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
|
||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
|
||||
String mimeType = contentInfo.getMimeType();
|
||||
if (mimeType == null)
|
||||
{
|
||||
String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||
writer.guessMimetype(fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.setMimetype(mimeType);
|
||||
}
|
||||
writer.guessEncoding();
|
||||
setWriterContentType(writer, new ContentInfoWrapper(contentInfo), nodeRef, true);
|
||||
writer.putContent(stream);
|
||||
|
||||
return getFolderOrDocumentFullInfo(nodeRef,
|
||||
@@ -1322,6 +1303,33 @@ public class NodesImpl implements Nodes
|
||||
parameters);
|
||||
}
|
||||
|
||||
private void setWriterContentType(ContentWriter writer, ContentInfoWrapper contentInfo, NodeRef nodeRef, boolean guessEncodingIfNull)
|
||||
{
|
||||
String mimeType = contentInfo.mimeType;
|
||||
// Manage MimeType
|
||||
if (mimeType == null)
|
||||
{
|
||||
// the mimeType was not provided via the contentInfo, so try to guess
|
||||
final String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
mimeType = mimetypeService.guessMimetype(fileName);
|
||||
}
|
||||
writer.setMimetype(mimeType);
|
||||
|
||||
// Manage Encoding
|
||||
if (contentInfo.encoding == null)
|
||||
{
|
||||
if (guessEncodingIfNull)
|
||||
{
|
||||
// the encoding was not provided, so try to guess
|
||||
writer.guessEncoding();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.setEncoding(contentInfo.encoding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node upload(String parentFolderNodeId, FormData formData, Parameters parameters)
|
||||
{
|
||||
@@ -1423,7 +1431,7 @@ public class NodesImpl implements Nodes
|
||||
// else if (overwrite && nodeService.hasAspect(existingFile, ContentModel.ASPECT_VERSIONABLE))
|
||||
// {
|
||||
// // Upload component was configured to overwrite files if name clashes
|
||||
// write(existingFile, content, fileName, false, true);
|
||||
// write(existingFile, content);
|
||||
//
|
||||
// // Extract the metadata (The overwrite policy controls
|
||||
// // which if any parts of the document's properties are updated from this)
|
||||
@@ -1487,7 +1495,7 @@ public class NodesImpl implements Nodes
|
||||
NodeRef newFile = createNodeImpl(parentNodeRef, fileName, nodeType, props);
|
||||
|
||||
// Write content
|
||||
write(newFile, content, fileName, true, true);
|
||||
write(newFile, content);
|
||||
|
||||
// Ensure the file is versionable (autoVersion = true, autoVersionProps = false)
|
||||
ensureVersioningEnabled(newFile, true, false);
|
||||
@@ -1513,40 +1521,13 @@ public class NodesImpl implements Nodes
|
||||
*
|
||||
* @param nodeRef the reference to the node having a content property
|
||||
* @param content the content
|
||||
* @param fileName the uploaded file name
|
||||
* @param applyMimeType If true, apply the mimeType from the Content object,
|
||||
* else leave the original mimeType (if the original type is null, then guess the mimeType)
|
||||
* @param guessEncoding If true, guess the encoding from the underlying
|
||||
* input stream, else use encoding set in the Content object as supplied
|
||||
*/
|
||||
protected void write(NodeRef nodeRef, Content content, String fileName, boolean applyMimeType, boolean guessEncoding)
|
||||
protected void write(NodeRef nodeRef, Content content)
|
||||
{
|
||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
String mimeType = content.getMimetype();
|
||||
// Per RA-637 requirement the mimeType provided by the client takes precedence, however,
|
||||
// if the mimeType is null, then it will be retrieved or guessed.
|
||||
if (mimeType == null || !applyMimeType)
|
||||
{
|
||||
ContentData existingContentData = (ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||
if (existingContentData != null)
|
||||
{
|
||||
mimeType = existingContentData.getMimetype();
|
||||
}
|
||||
else
|
||||
{
|
||||
mimeType = mimetypeService.guessMimetype(fileName);
|
||||
}
|
||||
}
|
||||
writer.setMimetype(mimeType);
|
||||
|
||||
if (guessEncoding)
|
||||
{
|
||||
writer.guessEncoding();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.setEncoding(content.getEncoding());
|
||||
}
|
||||
// if the mimeType is null, then it will be guessed.
|
||||
setWriterContentType(writer, new ContentInfoWrapper(content), nodeRef, true);
|
||||
writer.putContent(content.getInputStream());
|
||||
}
|
||||
|
||||
@@ -1682,4 +1663,52 @@ public class NodesImpl implements Nodes
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Jamal Kaabi-Mofrad
|
||||
*/
|
||||
private static class ContentInfoWrapper
|
||||
{
|
||||
private String mimeType;
|
||||
private String encoding;
|
||||
|
||||
ContentInfoWrapper(BasicContentInfo basicContentInfo)
|
||||
{
|
||||
if (basicContentInfo != null)
|
||||
{
|
||||
this.mimeType = basicContentInfo.getMimeType();
|
||||
this.encoding = basicContentInfo.getEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
ContentInfoWrapper(ContentInfo contentInfo)
|
||||
{
|
||||
if (contentInfo != null)
|
||||
{
|
||||
this.mimeType = contentInfo.getMimeType();
|
||||
this.encoding = contentInfo.getEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
ContentInfoWrapper(Content content)
|
||||
{
|
||||
if (content != null && StringUtils.isNotEmpty(content.getMimetype()))
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO I think it makes sense to push contentType parsing into org.springframework.extensions.webscripts.servlet.FormData
|
||||
MediaType media = MediaType.parseMediaType(content.getMimetype());
|
||||
this.mimeType = media.getType() + '/' + media.getSubtype();
|
||||
|
||||
if (media.getCharSet() != null)
|
||||
{
|
||||
this.encoding = media.getCharSet().name();
|
||||
}
|
||||
}
|
||||
catch (InvalidMediaTypeException ime)
|
||||
{
|
||||
throw new InvalidArgumentException(ime.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -788,6 +788,8 @@ public class NodeApiTest extends AbstractBaseApiTest
|
||||
ContentInfo contentInfo = document.getContent();
|
||||
assertNotNull(contentInfo);
|
||||
assertEquals(MimetypeMap.MIMETYPE_PDF, contentInfo.getMimeType());
|
||||
// Default encoding
|
||||
assertEquals("UTF-8", contentInfo.getEncoding());
|
||||
// Check there is no path info returned.
|
||||
// The path info should only be returned when it is requested via a select statement.
|
||||
assertNull(document.getPath());
|
||||
@@ -866,6 +868,26 @@ public class NodeApiTest extends AbstractBaseApiTest
|
||||
.build();
|
||||
post(getChildrenUrl(user1Home.getId()), user1, reqBody.getBody(), null, reqBody.getContentType(), 400);
|
||||
|
||||
// User1 uploads a new file
|
||||
reqBody = MultiPartBuilder.create()
|
||||
.setFileData(new FileData(fileName2, file2, MimetypeMap.MIMETYPE_TEXT_PLAIN, "windows-1252"))
|
||||
.build();
|
||||
response = post(getChildrenUrl(user1Home.getId()), user1, reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||
document = jacksonUtil.parseEntry(response.getJsonResponse(), Document.class);
|
||||
// Check the upload response
|
||||
assertEquals(fileName2, document.getName());
|
||||
contentInfo = document.getContent();
|
||||
assertNotNull(contentInfo);
|
||||
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, contentInfo.getMimeType());
|
||||
assertEquals("windows-1252", contentInfo.getEncoding());
|
||||
|
||||
// Test invalid mimeType
|
||||
reqBody = MultiPartBuilder.create()
|
||||
.setFileData(new FileData(fileName2, file2, "*/invalidSubType", "ISO-8859-1"))
|
||||
.setAutoRename(true)
|
||||
.build();
|
||||
post(getChildrenUrl(user1Home.getId()), user1, reqBody.getBody(), null, reqBody.getContentType(), 400);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1548,8 +1570,8 @@ public class NodeApiTest extends AbstractBaseApiTest
|
||||
// Update the empty node's content
|
||||
String content = "The quick brown fox jumps over the lazy dog.";
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes());
|
||||
File file = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt");
|
||||
BinaryPayload payload = new BinaryPayload(file, MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
File txtFile = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt");
|
||||
BinaryPayload payload = new BinaryPayload(txtFile, MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
|
||||
// Try to update a folder!
|
||||
putBinary(URL_NODES + f1_nodeId + "/content", user1, payload, null, null, 400);
|
||||
@@ -1576,6 +1598,8 @@ public class NodeApiTest extends AbstractBaseApiTest
|
||||
contentInfo = docResp.getContent();
|
||||
assertNotNull(contentInfo);
|
||||
assertNotNull(contentInfo.getEncoding());
|
||||
// Default encoding
|
||||
assertEquals("UTF-8", contentInfo.getEncoding());
|
||||
assertTrue(contentInfo.getSizeInBytes() > 0);
|
||||
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, contentInfo.getMimeType());
|
||||
assertNotNull(contentInfo.getMimeTypeName());
|
||||
@@ -1587,13 +1611,14 @@ public class NodeApiTest extends AbstractBaseApiTest
|
||||
assertEquals(content, response.getResponse());
|
||||
|
||||
// Update the node's content again. Also, change the mimeType and make the response to return path!
|
||||
file = getResourceFile("quick.pdf");
|
||||
payload = new BinaryPayload(file, MimetypeMap.MIMETYPE_PDF);
|
||||
File pdfFile = getResourceFile("quick.pdf");
|
||||
payload = new BinaryPayload(pdfFile, MimetypeMap.MIMETYPE_PDF, "ISO-8859-1");
|
||||
|
||||
response = putBinary(url + "?select=path", user1, payload, null, null, 200);
|
||||
docResp = jacksonUtil.parseEntry(response.getJsonResponse(), Document.class);
|
||||
assertEquals(docName, docResp.getName());
|
||||
assertNotNull(docResp.getContent());
|
||||
assertNotNull("ISO-8859-1", docResp.getContent());
|
||||
assertTrue(docResp.getContent().getSizeInBytes().intValue() > 0);
|
||||
assertEquals(MimetypeMap.MIMETYPE_PDF, docResp.getContent().getMimeType());
|
||||
PathInfo pathInfo = docResp.getPath();
|
||||
@@ -1605,6 +1630,16 @@ public class NodeApiTest extends AbstractBaseApiTest
|
||||
// check the last element is F1
|
||||
assertEquals(f1.getName(), pathElements.get(pathElements.size() - 1).getName());
|
||||
|
||||
// update the original content with different encoding
|
||||
payload = new BinaryPayload(txtFile, MimetypeMap.MIMETYPE_TEXT_PLAIN, "ISO-8859-15");
|
||||
response = putBinary(url, user1, payload, null, null, 200);
|
||||
docResp = jacksonUtil.parseEntry(response.getJsonResponse(), Document.class);
|
||||
assertEquals(docName, docResp.getName());
|
||||
assertNotNull(docResp.getContent());
|
||||
assertNotNull("ISO-8859-15", docResp.getContent());
|
||||
assertTrue(docResp.getContent().getSizeInBytes().intValue() > 0);
|
||||
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, docResp.getContent().getMimeType());
|
||||
|
||||
// Download the file
|
||||
response = getSingle(url, user1, null, 200);
|
||||
assertNotNull(content, response.getResponse());
|
||||
|
@@ -887,8 +887,8 @@ public class PublicApiHttpClient
|
||||
public BinaryRequestEntity(File file, String mimeType, String charset)
|
||||
{
|
||||
this.file = file;
|
||||
this.mimeType = (mimeType == null) ? "application/octet-stream" : mimeType;
|
||||
this.charset = (charset == null) ? "UTF-8" : charset;
|
||||
this.mimeType = mimeType;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -925,7 +925,15 @@ public class PublicApiHttpClient
|
||||
@Override
|
||||
public String getContentType()
|
||||
{
|
||||
return mimeType + "; " + charset;
|
||||
if (charset == null)
|
||||
{
|
||||
return mimeType;
|
||||
}
|
||||
if (mimeType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return mimeType + "; charset=" + charset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -204,12 +204,19 @@ public class MultiPartBuilder
|
||||
private final String fileName;
|
||||
private final File file;
|
||||
private final String mimetype;
|
||||
private final String encoding;
|
||||
|
||||
public FileData(String fileName, File file, String mimetype)
|
||||
{
|
||||
this(fileName, file, mimetype, null);
|
||||
}
|
||||
|
||||
public FileData(String fileName, File file, String mimetype, String encoding)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
this.file = file;
|
||||
this.mimetype = mimetype;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public String getFileName()
|
||||
@@ -226,6 +233,11 @@ public class MultiPartBuilder
|
||||
{
|
||||
return mimetype;
|
||||
}
|
||||
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MultiPartRequest
|
||||
@@ -265,7 +277,7 @@ public class MultiPartBuilder
|
||||
{
|
||||
FilePart fp = new FilePart("filedata", fileData.getFileName(), fileData.getFile(), fileData.getMimetype(), null);
|
||||
// Get rid of the default values added upon FilePart instantiation
|
||||
fp.setCharSet(null);
|
||||
fp.setCharSet(fileData.getEncoding());
|
||||
fp.setContentType(fileData.getMimetype());
|
||||
parts.add(fp);
|
||||
addPartIfNotNull(parts, "filename", fileData.getFileName());
|
||||
|
Reference in New Issue
Block a user