use of com.zimbra.cs.service.util.ItemIdFormatter in project zm-mailbox by Zimbra.
the class SendMsg method handle.
public Element handle(Element request, Map<String, Object> context, QName respQname) throws ServiceException {
try {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Mailbox mbox = getRequestedMailbox(zsc);
AccountUtil.checkQuotaWhenSendMail(mbox);
OperationContext octxt = getOperationContext(zsc, context);
ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
// <m>
Element msgElem = request.getElement(MailConstants.E_MSG);
// check to see whether the entire message has been uploaded under separate cover
String attachId = msgElem.getAttribute(MailConstants.A_ATTACHMENT_ID, null);
boolean needCalendarSentByFixup = request.getAttributeBool(MailConstants.A_NEED_CALENDAR_SENTBY_FIXUP, false);
boolean isCalendarForward = request.getAttributeBool(MailConstants.A_IS_CALENDAR_FORWARD, false);
boolean noSaveToSent = request.getAttributeBool(MailConstants.A_NO_SAVE_TO_SENT, false);
boolean fetchSavedMsg = request.getAttributeBool(MailConstants.A_FETCH_SAVED_MSG, false);
String origId = msgElem.getAttribute(MailConstants.A_ORIG_ID, null);
ItemId iidOrigId = origId == null ? null : new ItemId(origId, zsc);
String replyType = msgElem.getAttribute(MailConstants.A_REPLY_TYPE, MailSender.MSGTYPE_REPLY);
String identityId = msgElem.getAttribute(MailConstants.A_IDENTITY_ID, null);
String dataSourceId = msgElem.getAttribute(MailConstants.A_DATASOURCE_ID, null);
String draftId = msgElem.getAttribute(MailConstants.A_DRAFT_ID, null);
ItemId iidDraft = draftId == null ? null : new ItemId(draftId, zsc);
boolean sendFromDraft = msgElem.getAttributeBool(MailConstants.A_SEND_FROM_DRAFT, false);
SendState state = SendState.NEW;
ItemId savedMsgId = null;
Pair<String, ItemId> sendRecord = null;
// get the "send uid" and check that this isn't a retry of a pending send
String sendUid = request.getAttribute(MailConstants.A_SEND_UID, null);
if (sendUid != null) {
long delay = MAX_IN_FLIGHT_DELAY_MSECS;
do {
if (state == SendState.PENDING) {
try {
delay -= RETRY_CHECK_PERIOD_MSECS;
Thread.sleep(RETRY_CHECK_PERIOD_MSECS);
} catch (InterruptedException ie) {
}
}
Pair<SendState, Pair<String, ItemId>> result = findPendingSend(mbox.getId(), sendUid);
state = result.getFirst();
sendRecord = result.getSecond();
} while (state == SendState.PENDING && delay >= 0);
}
if (state == SendState.SENT) {
// message successfully sent by another thread
savedMsgId = sendRecord.getSecond();
} else if (state == SendState.PENDING) {
// tired of waiting for another thread to complete the send
throw MailServiceException.TRY_AGAIN("message send already in progress: " + sendUid);
} else if (state == SendState.NEW) {
MimeMessageData mimeData = new MimeMessageData();
try {
// holds return data about the MimeMessage
MimeMessage mm;
if (attachId != null) {
mm = parseUploadedMessage(zsc, attachId, mimeData, needCalendarSentByFixup);
} else if (iidDraft != null && sendFromDraft) {
Message msg = mbox.getMessageById(octxt, iidDraft.getId());
mm = msg.getMimeMessage(false);
} else {
mm = ParseMimeMessage.parseMimeMsgSoap(zsc, octxt, mbox, msgElem, null, mimeData);
}
savedMsgId = doSendMessage(octxt, mbox, mm, mimeData.uploads, iidOrigId, replyType, identityId, dataSourceId, noSaveToSent, needCalendarSentByFixup, isCalendarForward);
// a null ItemId makes the send appear to still be PENDING)
if (savedMsgId == null) {
savedMsgId = NO_MESSAGE_SAVED_TO_SENT;
}
// and record it in the table in case the client retries the send
if (sendRecord != null) {
sendRecord.setSecond(savedMsgId);
}
} catch (ServiceException e) {
clearPendingSend(mbox.getId(), sendRecord);
throw e;
} catch (RuntimeException re) {
clearPendingSend(mbox.getId(), sendRecord);
throw re;
} finally {
// purge the messages fetched from other servers.
if (mimeData.fetches != null) {
FileUploadServlet.deleteUploads(mimeData.fetches);
}
}
}
if (iidDraft != null) {
deleteDraft(iidDraft, octxt, mbox, zsc);
}
Element response = zsc.createElement(respQname);
if (savedMsgId != null && savedMsgId != NO_MESSAGE_SAVED_TO_SENT && savedMsgId.getId() > 0) {
if (fetchSavedMsg) {
Message msg = GetMsg.getMsg(octxt, mbox, savedMsgId, false);
ToXML.encodeMessageAsMP(response, ifmt, octxt, msg, null, 0, true, true, null, false, false, LC.mime_encode_missing_blob.booleanValue(), MsgContent.both);
} else {
Element respElement = response.addElement(MailConstants.E_MSG);
respElement.addAttribute(MailConstants.A_ID, ifmt.formatItemId(savedMsgId));
}
} else {
response.addElement(MailConstants.E_MSG);
}
return response;
} finally {
processor = null;
}
}
use of com.zimbra.cs.service.util.ItemIdFormatter in project zm-mailbox by Zimbra.
the class ModifyCalendarItem method modifyCalendarItem.
private Element modifyCalendarItem(ZimbraSoapContext zsc, OperationContext octxt, Element request, Account acct, Mailbox mbox, int folderId, CalendarItem calItem, Invite inv, Invite seriesInv, Element response, boolean isInterMboxMove, MailSendQueue sendQueue) throws ServiceException {
// <M>
Element msgElem = request.getElement(MailConstants.E_MSG);
ModifyCalendarItemParser parser = new ModifyCalendarItemParser(inv, seriesInv);
CalSendData dat = handleMsgElement(zsc, octxt, msgElem, acct, mbox, parser);
dat.mDontNotifyAttendees = isInterMboxMove;
if (!dat.mInvite.hasRecurId())
ZimbraLog.calendar.info("<ModifyCalendarItem> id=%d, folderId=%d, subject=\"%s\", UID=%s", calItem.getId(), folderId, dat.mInvite.isPublic() ? dat.mInvite.getName() : "(private)", dat.mInvite.getUid());
else
ZimbraLog.calendar.info("<ModifyCalendarItem> id=%d, folderId=%d, subject=\"%s\", UID=%s, recurId=%s", calItem.getId(), folderId, dat.mInvite.isPublic() ? dat.mInvite.getName() : "(private)", dat.mInvite.getUid(), dat.mInvite.getRecurId().getDtZ());
boolean hasRecipients;
try {
Address[] rcpts = dat.mMm.getAllRecipients();
hasRecipients = rcpts != null && rcpts.length > 0;
} catch (MessagingException e) {
throw ServiceException.FAILURE("Checking recipients of outgoing msg ", e);
}
// If we are sending this to other people, then we MUST be the organizer!
if (!dat.mInvite.isOrganizer() && hasRecipients)
throw MailServiceException.MUST_BE_ORGANIZER("ModifyCalendarItem");
if (!dat.mInvite.isOrganizer()) {
// neverSent is always false for attendee users.
dat.mInvite.setNeverSent(false);
} else if (!dat.mInvite.hasOtherAttendees()) {
// neverSent is always false for appointments without attendees.
dat.mInvite.setNeverSent(false);
} else if (hasRecipients) {
// neverSent is set to false when attendees are notified.
dat.mInvite.setNeverSent(false);
} else {
// This is the case of organizer saving an invite with attendees, but without sending the notification.
assert (dat.mInvite.hasOtherAttendees() && !hasRecipients);
if (!inv.hasOtherAttendees()) {
// Special case of going from a personal appointment (no attendees) to a draft appointment with
// attendees. neverSent was false for being a personal appointment, so we need to explicitly set it to true.
// This case is essentially identical to creating a new appointment with attendees without notification.
dat.mInvite.setNeverSent(true);
} else {
// Set neverSent to false, but only if it wasn't already set to true before.
// !inv.isNeverSent() ? false : true ==> inv.isNeverSent()
dat.mInvite.setNeverSent(inv.isNeverSent());
}
}
boolean echo = request.getAttributeBool(MailConstants.A_CAL_ECHO, false);
ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
int maxSize = (int) request.getAttributeLong(MailConstants.A_MAX_INLINED_LENGTH, 0);
boolean wantHTML = request.getAttributeBool(MailConstants.A_WANT_HTML, false);
boolean neuter = request.getAttributeBool(MailConstants.A_NEUTER, true);
boolean forceSend = request.getAttributeBool(MailConstants.A_CAL_FORCESEND, true);
if (inv.isOrganizer()) {
// Notify removed attendees before making any changes to the appointment.
List<ZAttendee> atsCanceled = parser.getAttendeesCanceled();
if (!inv.isNeverSent()) {
// No need to notify for a draft appointment.
if (!atsCanceled.isEmpty()) {
notifyRemovedAttendees(zsc, octxt, acct, mbox, inv.getCalendarItem(), inv, atsCanceled, sendQueue);
}
}
List<ZAttendee> atsAdded = parser.getAttendeesAdded();
// Figure out if we're notifying all attendees. Must do this before clearing recipients from dat.mMm.
boolean notifyAllAttendees = isNotifyingAll(dat.mMm, atsAdded);
// If notifying all the attendees update the last sequence number otherwise retain the existing value.
if (notifyAllAttendees) {
dat.mInvite.setLastFullSeqNo(dat.mInvite.getSeqNo());
} else {
dat.mInvite.setLastFullSeqNo(inv.getLastFullSeqNo());
}
if (inv.isRecurrence()) {
// Clear to/cc/bcc from the MimeMessage, so that the sendCalendarMessage call only updates the organizer's
// own appointment without notifying any attendees. Notifications will be sent later,
removeAllRecipients(dat.mMm);
// (unless they are added as new series attendees)
if (!acct.isCalendarKeepExceptionsOnSeriesTimeChange()) {
InviteChanges ic = new InviteChanges(seriesInv, dat.mInvite);
if (ic.isExceptionRemovingChange()) {
long now = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
Invite[] invites = calItem.getInvites();
for (Invite except : invites) {
if (!except.isNeverSent() && except.hasRecurId() && !except.isCancel() && inviteIsAfterTime(except, now)) {
List<ZAttendee> toNotify = CalendarUtils.getRemovedAttendees(except.getAttendees(), seriesInv.getAttendees(), false, acct);
if (!toNotify.isEmpty()) {
notifyRemovedAttendees(zsc, octxt, acct, mbox, calItem, except, toNotify, sendQueue);
}
}
}
}
}
// Save the change to the series as specified by the client.
sendCalendarMessage(zsc, octxt, folderId, acct, mbox, dat, response, true, forceSend, sendQueue);
// Echo the updated inv in the response.
if (echo && dat.mAddInvData != null) {
echoAddedInvite(response, ifmt, octxt, mbox, dat.mAddInvData, maxSize, wantHTML, neuter);
}
boolean ignorePastExceptions = true;
// Reflect added/removed attendees in the exception instances.
if (!atsAdded.isEmpty() || !atsCanceled.isEmpty()) {
addRemoveAttendeesInExceptions(octxt, mbox, inv.getCalendarItem(), atsAdded, atsCanceled, ignorePastExceptions);
}
// Send notifications.
if (hasRecipients) {
notifyCalendarItem(zsc, octxt, acct, mbox, inv.getCalendarItem(), notifyAllAttendees, atsAdded, ignorePastExceptions, sendQueue);
}
} else {
// Modifying a one-off appointment or an exception instance. There are no
// complications like in the series update case. Just update the invite with the
// data supplied by the client, and let the built-in notification take place.
sendCalendarMessage(zsc, octxt, folderId, acct, mbox, dat, response, true, forceSend, sendQueue);
// Echo the updated inv in the response.
if (echo && dat.mAddInvData != null) {
echoAddedInvite(response, ifmt, octxt, mbox, dat.mAddInvData, maxSize, wantHTML, neuter);
}
}
} else {
// not organizer
// Apply the change.
sendCalendarMessage(zsc, octxt, folderId, acct, mbox, dat, response, true, forceSend, sendQueue);
// Echo the updated inv in the response.
if (echo && dat.mAddInvData != null) {
echoAddedInvite(response, ifmt, octxt, mbox, dat.mAddInvData, maxSize, wantHTML, neuter);
}
}
return response;
}
use of com.zimbra.cs.service.util.ItemIdFormatter in project zm-mailbox by Zimbra.
the class ModifySearchFolder method handle.
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Mailbox mbox = getRequestedMailbox(zsc);
OperationContext octxt = getOperationContext(zsc, context);
ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
Element t = request.getElement(MailConstants.E_SEARCH);
ItemId iid = new ItemId(t.getAttribute(MailConstants.A_ID), zsc);
String query = t.getAttribute(MailConstants.A_QUERY);
String types = t.getAttribute(MailConstants.A_SEARCH_TYPES, null);
String sort = t.getAttribute(MailConstants.A_SORTBY, null);
mbox.modifySearchFolder(octxt, iid.getId(), query, types, sort);
SearchFolder search = mbox.getSearchFolderById(octxt, iid.getId());
Element response = zsc.createElement(MailConstants.MODIFY_SEARCH_FOLDER_RESPONSE);
ToXML.encodeSearchFolder(response, ifmt, search);
return response;
}
use of com.zimbra.cs.service.util.ItemIdFormatter in project zm-mailbox by Zimbra.
the class MailDocumentHandler method insertMountpointReferences.
private void insertMountpointReferences(Element response, String[] xpath, ItemId iidMountpoint, ItemId iidLocal, ZimbraSoapContext lc) {
int depth = 0;
while (depth < xpath.length && response != null) {
response = response.getOptionalElement(xpath[depth++]);
}
if (response == null) {
return;
}
ItemIdFormatter ifmt = new ItemIdFormatter(lc);
String local = iidLocal.toString(ifmt);
for (Element elt : response.listElements()) {
String folder = elt.getAttribute(MailConstants.A_FOLDER, null);
if (local.equalsIgnoreCase(folder)) {
elt.addAttribute(MailConstants.A_FOLDER, iidMountpoint.toString(ifmt));
}
}
}
use of com.zimbra.cs.service.util.ItemIdFormatter in project zm-mailbox by Zimbra.
the class SaveDocument method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
OperationContext octxt = getOperationContext(zsc, context);
Element docElem = request.getElement(MailConstants.E_DOC);
Doc doc = null;
Element response = null;
boolean success = false;
Mailbox mbox = null;
int folderId = 0;
try {
String explicitName = docElem.getAttribute(MailConstants.A_NAME, null);
String explicitCtype = docElem.getAttribute(MailConstants.A_CONTENT_TYPE, null);
//bug 37180, extract the filename from the path (for IE). IE sends the full path.
if (explicitName != null) {
try {
explicitName = explicitName.replaceAll("\\\\", "/");
explicitName = explicitName.substring(explicitName.lastIndexOf("/") + 1);
} catch (Exception e) {
//Do nothing
}
}
String description = docElem.getAttribute(MailConstants.A_DESC, null);
ItemId fid = new ItemId(docElem.getAttribute(MailConstants.A_FOLDER, DEFAULT_DOCUMENT_FOLDER), zsc);
folderId = fid.getId();
String id = docElem.getAttribute(MailConstants.A_ID, null);
int itemId = id == null ? 0 : new ItemId(id, zsc).getId();
int ver = (int) docElem.getAttributeLong(MailConstants.A_VERSION, 0);
mbox = getRequestedMailbox(zsc);
Element attElem = docElem.getOptionalElement(MailConstants.E_UPLOAD);
Element msgElem = docElem.getOptionalElement(MailConstants.E_MSG);
Element docRevElem = docElem.getOptionalElement(MailConstants.E_DOC);
if (attElem != null) {
String aid = attElem.getAttribute(MailConstants.A_ID, null);
doc = getUploadedDoc(aid, zsc, explicitName, explicitCtype, description);
} else if (msgElem != null) {
String part = msgElem.getAttribute(MailConstants.A_PART);
ItemId iid = new ItemId(msgElem.getAttribute(MailConstants.A_ID), zsc);
doc = fetchMimePart(octxt, zsc.getAuthToken(), iid, part, explicitName, explicitCtype, description);
} else if (docRevElem != null) {
ItemId iid = new ItemId(docRevElem.getAttribute(MailConstants.A_ID), zsc);
int revSource = (int) docRevElem.getAttributeLong(MailConstants.A_VERSION, 0);
Account sourceAccount = Provisioning.getInstance().getAccountById(iid.getAccountId());
if (sourceAccount.getId().equals(zsc.getRequestedAccountId())) {
Document docRev;
if (revSource == 0) {
docRev = mbox.getDocumentById(octxt, iid.getId());
} else {
docRev = (Document) mbox.getItemRevision(octxt, iid.getId(), MailItem.Type.DOCUMENT, revSource);
}
doc = new Doc(docRev);
} else {
doc = new Doc(zsc.getAuthToken(), sourceAccount, iid.getId(), revSource);
}
// the content from another document
if (ver != 0) {
doc.name = null;
}
} else {
String inlineContent = docElem.getAttribute(MailConstants.E_CONTENT);
doc = new Doc(inlineContent, explicitName, explicitCtype, description);
}
// set content-type based on file extension.
setDocContentType(doc);
Document docItem = null;
InputStream is = null;
try {
is = doc.getInputStream();
} catch (IOException e) {
throw ServiceException.FAILURE("can't save document", e);
}
if (itemId == 0) {
// create a new page
docItem = createDocument(doc, zsc, octxt, mbox, docElem, is, folderId, MailItem.Type.DOCUMENT);
} else {
// add a new revision
docItem = mbox.getDocumentById(octxt, itemId);
if (docItem.getVersion() != ver) {
throw MailServiceException.MODIFY_CONFLICT(new Argument(MailConstants.A_NAME, doc.name, Argument.Type.STR), new Argument(MailConstants.A_ID, itemId, Argument.Type.IID), new Argument(MailConstants.A_VERSION, docItem.getVersion(), Argument.Type.NUM));
}
String name = docItem.getName();
if (doc.name != null) {
name = doc.name;
}
boolean descEnabled = docElem.getAttributeBool(MailConstants.A_DESC_ENABLED, docItem.isDescriptionEnabled());
docItem = mbox.addDocumentRevision(octxt, itemId, getAuthor(zsc), name, doc.description, descEnabled, is);
}
response = zsc.createElement(MailConstants.SAVE_DOCUMENT_RESPONSE);
Element m = response.addElement(MailConstants.E_DOC);
m.addAttribute(MailConstants.A_ID, new ItemIdFormatter(zsc).formatItemId(docItem));
m.addAttribute(MailConstants.A_VERSION, docItem.getVersion());
m.addAttribute(MailConstants.A_NAME, docItem.getName());
success = true;
} catch (ServiceException e) {
if (e.getCode().equals(MailServiceException.ALREADY_EXISTS)) {
MailItem item = null;
if (mbox != null && folderId != 0) {
item = mbox.getItemByPath(octxt, doc.name, folderId);
}
if (item != null && item instanceof Document) {
// name clash with another Document
throw MailServiceException.ALREADY_EXISTS("name " + doc.name + " in folder " + folderId, doc.name, item.getId(), ((Document) item).getVersion());
} else if (item != null) {
// name clash with a folder
throw MailServiceException.ALREADY_EXISTS("name " + doc.name + " in folder " + folderId, doc.name, item.getId());
}
}
throw e;
} finally {
if (success && doc != null) {
doc.cleanup();
}
}
return response;
}
Aggregations