final XmldbURI pathUri = XmldbURI.create(request.getPath());
String contentType = request.getHeader("Content-Type");
String charset = getContext().getDefaultCharset();
MimeType mime = MimeType.BINARY_TYPE;
if (contentType != null) {
final int semicolon = contentType.indexOf(';');
if (semicolon > 0) {
contentType = contentType.substring(0, semicolon).trim();
}
mime = MimeTable.getInstance().getContentType(contentType);
if (mime == null) {
mime = MimeType.BINARY_TYPE;
}
final int equals = contentType.indexOf('=', semicolon);
if (equals > 0) {
final String param = contentType.substring(semicolon + 1, equals)
.trim();
if (param.compareToIgnoreCase("charset=") == 0) {
charset = param.substring(equals + 1).trim();
}
}
}
final String currentDateTime = DateFormatter.toXSDDateTime(new Date());
Collection collection = broker.getCollection(pathUri);
if (mime.getName().equals(Atom.MIME_TYPE)) {
final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
docFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = null;
Document doc = null;
try {
final InputSource src = new InputSource(
new InputStreamReader(request.getInputStream(), charset)
);
docBuilder = docFactory.newDocumentBuilder();
doc = docBuilder.parse(src);
} catch (final IOException e) {
LOG.warn(e);
throw new BadRequestException(e.getMessage());
} catch (final SAXException e) {
LOG.warn(e);
throw new BadRequestException(e.getMessage());
} catch (final ParserConfigurationException e) {
LOG.warn(e);
throw new BadRequestException(e.getMessage());
}
final Element root = doc.getDocumentElement();
final String ns = root.getNamespaceURI();
if (ns == null || !ns.equals(Atom.NAMESPACE_STRING)) {
throw new BadRequestException(
"Any content posted with the Atom mime type must be in the Atom namespace.");
}
if ("feed".equals(root.getLocalName())) {
DocumentImpl feedDoc = null;
final TransactionManager transact = broker.getBrokerPool().getTransactionManager();
final Txn transaction = transact.beginTransaction();
try {
if (collection != null) {
feedDoc = collection.getDocument(broker, FEED_DOCUMENT_URI);
if (feedDoc != null) {
throw new PermissionDeniedException(
"Collection at " + request.getPath()
+ " already exists.");
}
} else {
collection = broker.getOrCreateCollection(transaction, pathUri);
setPermissions(broker, root, collection);
broker.saveCollection(transaction, collection);
}
final String id = UUIDGenerator.getUUID();
DOM.replaceTextElement(root,
Atom.NAMESPACE_STRING,
"updated", currentDateTime, true);
DOM.replaceTextElement(root,
Atom.NAMESPACE_STRING,
"id", "urn:uuid:" + id, true);
Element editLink = findLink(root, "edit");
if (editLink != null) {
throw new BadRequestException(
"An edit link relation cannot be specified in the feed.");
}
editLink = doc.createElementNS(Atom.NAMESPACE_STRING, "link");
editLink.setAttribute("rel", "edit");
editLink.setAttribute("type", Atom.MIME_TYPE);
editLink.setAttribute("href", "#");
root.appendChild(editLink);
Element selfLink = findLink(root, "self");
if (selfLink != null) {
throw new BadRequestException(
"A self link relation cannot be specified in the feed.");
}
selfLink = doc.createElementNS(Atom.NAMESPACE_STRING, "link");
selfLink.setAttribute("rel", "self");
selfLink.setAttribute("type", Atom.MIME_TYPE);
selfLink.setAttribute("href", "#");
root.appendChild(selfLink);
final IndexInfo info = collection.validateXMLResource(transaction, broker, FEED_DOCUMENT_URI, doc);
setPermissions(broker, root, info.getDocument());
// TODO : We should probably unlock the collection here
collection.store(transaction, broker, info, doc, false);
transact.commit(transaction);
response.setStatusCode(204);
response.setHeader("Location", request.getModuleBase() + request.getPath());
} catch (final IOException ex) {
transact.abort(transaction);
throw new EXistException("IO error: " + ex.getMessage(), ex);
} catch (final TriggerException ex) {
transact.abort(transaction);
throw new EXistException("Trigger failed: " + ex.getMessage(), ex);
} catch (final SAXException ex) {
transact.abort(transaction);
throw new EXistException("SAX error: " + ex.getMessage(), ex);
} catch (final LockException ex) {
transact.abort(transaction);
throw new EXistException("Cannot acquire write lock.", ex);
} finally {
transact.close(transaction);
}
} else if ("entry".equals(root.getLocalName())) {
if (collection == null) {
throw new BadRequestException("Collection "
+ request.getPath() + " does not exist.");
}
LOG.debug("Adding entry to " + request.getPath());
DocumentImpl feedDoc = null;
feedDoc = collection.getDocument(broker, FEED_DOCUMENT_URI);
if (!feedDoc.getPermissions().validate(broker.getSubject(), Permission.WRITE))
{throw new PermissionDeniedException(
"Permission denied to update feed " + collection.getURI());}
final TransactionManager transact = broker.getBrokerPool().getTransactionManager();
final Txn transaction = transact.beginTransaction();
final String uuid = UUIDGenerator.getUUID();
final String id = "urn:uuid:" + uuid;
final Element publishedE = DOM.replaceTextElement(root,
Atom.NAMESPACE_STRING, "published", currentDateTime, true, true);
DOM.replaceTextElement(root, Atom.NAMESPACE_STRING, "updated", currentDateTime, true, true);
DOM.replaceTextElement(root, Atom.NAMESPACE_STRING, "id", id, true, true);
Element editLink = findLink(root, "edit");
final Element editLinkSrc = findLink(root, "edit-media");
if (editLink != null || editLinkSrc != null) {
throw new BadRequestException(
"An edit link relation cannot be specified in the entry.");
}
editLink = doc.createElementNS(Atom.NAMESPACE_STRING, "link");
editLink.setAttribute("rel", "edit");
editLink.setAttribute("type", Atom.MIME_TYPE);
editLink.setAttribute("href", "?id=" + id);
final Node next = publishedE.getNextSibling();
if (next == null) {
root.appendChild(editLink);
} else {
root.insertBefore(editLink, next);
}
try {
// get the feed
LOG.debug("Acquiring lock on feed document...");
final ElementImpl feedRoot = (ElementImpl) feedDoc.getDocumentElement();
// Lock the feed
feedDoc.getUpdateLock().acquire(Lock.WRITE_LOCK);
// Append the entry
collection = broker.getOrCreateCollection(transaction, pathUri.append(ENTRY_COLLECTION_URI));
setPermissions(broker, root, collection);
broker.saveCollection(transaction, collection);
final XmldbURI entryURI = entryURI(uuid);
final DocumentImpl entryDoc = collection.getDocument(broker, entryURI);
if (entryDoc != null) {
throw new PermissionDeniedException("Entry with " + id
+ " already exists.");
}
final IndexInfo info = collection.validateXMLResource(transaction, broker, entryURI, doc);
setPermissions(broker, root, info.getDocument());
// TODO : We should probably unlock the collection here
collection.store(transaction, broker, info, doc, false);
// Update the updated element
DOMDB.replaceTextElement(transaction, feedRoot,
Atom.NAMESPACE_STRING, "updated", currentDateTime,
true);
// Store the changes
LOG.debug("Storing change...");
broker.storeXMLResource(transaction, feedDoc);
transact.commit(transaction);
LOG.debug("Done!");
//XXX: response outside of try-block
response.setStatusCode(201);
response.setHeader("Location", request.getModuleBase()
+ request.getPath() + "?id=" + id);
getEntryById(broker, request.getPath(), id, response);
/*
* response.setContentType(Atom.MIME_TYPE+"; charset="+charset
* ); OutputStreamWriter w = new
* OutputStreamWriter(response.getOutputStream(),charset);
* Transformer identity =
* TransformerFactory.newInstance().newTransformer();
* identity.transform(new DOMSource(doc),new
* StreamResult(w)); w.flush(); w.close();
*/
} catch (final IOException ex) {
transact.abort(transaction);
throw new EXistException("IO error: " + ex.getMessage(), ex);
} catch (final TriggerException ex) {
transact.abort(transaction);
throw new EXistException("Trigger failed: "
+ ex.getMessage(), ex);
} catch (final SAXException ex) {
transact.abort(transaction);
throw new EXistException("SAX error: " + ex.getMessage(),
ex);
} catch (final LockException ex) {
transact.abort(transaction);
throw new EXistException("Cannot acquire write lock.", ex);
/*
* } catch (IOException ex) { throw new
* EXistException("Internal error while serializing result."
* ,ex); } catch (TransformerException ex) { throw new
* EXistException("Serialization error.",ex);
*/
} finally {
transact.close(transaction);
if (feedDoc != null)
{feedDoc.getUpdateLock().release(Lock.WRITE_LOCK);}
}
} else {
throw new BadRequestException(
"Unexpected element: {http://www.w3.org/2005/Atom}" + root.getLocalName());
}
} else {
if (collection == null)
{throw new BadRequestException("Collection " + request.getPath() + " does not exist.");}
final DocumentImpl feedDoc = collection.getDocument(broker, FEED_DOCUMENT_URI);
if (feedDoc == null)
{throw new BadRequestException("Feed at " + request.getPath() + " does not exist.");}
if (!feedDoc.getPermissions().validate(broker.getSubject(), Permission.WRITE))
{throw new PermissionDeniedException(
"Permission denied to update feed " + collection.getURI());}
String filename = request.getHeader("Slug");
if (filename == null) {
final String ext = MimeTable.getInstance().getPreferredExtension(mime);
int count = 1;
while (filename == null) {
filename = "resource" + count + ext;
if (collection.getDocument(broker, XmldbURI.create(filename)) != null)
{filename = null;}
count++;
}
}
final TransactionManager transact = broker.getBrokerPool().getTransactionManager();
final Txn transaction = transact.beginTransaction();
try {
final XmldbURI docUri = XmldbURI.create(filename);
if (collection.getDocument(broker, docUri) != null) {
transact.abort(transaction);
throw new BadRequestException("Resource " + docUri + " already exists in collection " + pathUri);
}
final File tempFile = storeInTemporaryFile(request.getInputStream(), request.getContentLength());
if (mime.isXMLType()) {
InputStream is = new FileInputStream(tempFile);
final IndexInfo info = collection.validateXMLResource(
transaction, broker, docUri,
new InputSource(new InputStreamReader(is, charset)));
is.close();
info.getDocument().getMetadata().setMimeType(contentType);
is = new FileInputStream(tempFile);
collection.store(transaction, broker, info,
new InputSource(new InputStreamReader(is, charset)), false);
is.close();
} else {
final FileInputStream is = new FileInputStream(tempFile);
collection.addBinaryResource(transaction, broker, docUri, is, contentType, tempFile.length());
is.close();
}
try {
LOG.debug("Acquiring lock on feed document...");
feedDoc.getUpdateLock().acquire(Lock.WRITE_LOCK);
String title = request.getHeader("Title");
if (title == null)
{title = filename;}
final String created = DateFormatter.toXSDDateTime(new Date());
final ElementImpl feedRoot = (ElementImpl) feedDoc.getDocumentElement();
DOMDB.replaceTextElement(transaction, feedRoot, Atom.NAMESPACE_STRING, "updated", created, true);
final String uuid = UUIDGenerator.getUUID();
final String id = "urn:uuid:" + uuid;
final Element mediaEntry = generateMediaEntry(id, created, title, filename, mime.getName());
collection = broker.getOrCreateCollection(transaction, pathUri.append(ENTRY_COLLECTION_URI));
broker.saveCollection(transaction, collection);
final XmldbURI entryURI = entryURI(uuid);