use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.
the class CalDavDataImport method importData.
@Override
public void importData(List<Integer> folderIds, boolean fullSync) throws ServiceException {
ArrayList<CalendarFolder> folders = new ArrayList<CalendarFolder>();
try {
mbox.beginTrackingSync();
if (folderIds != null)
for (int fid : folderIds) folders.add(new CalendarFolder(fid));
else
folders = syncFolders();
OperationContext octxt = new OperationContext(mbox);
for (CalendarFolder f : folders) {
f.folder = mbox.getFolderById(octxt, f.id);
if (f.folder.getDefaultView() == MailItem.Type.APPOINTMENT) {
sync(octxt, f);
}
}
} catch (DavException e) {
throw ServiceException.FAILURE("error importing CalDAV data", e);
} catch (IOException e) {
throw ServiceException.FAILURE("error importing CalDAV data", e);
} catch (HttpException e) {
throw ServiceException.FAILURE("error importing CalDAV data", e);
}
}
use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.
the class CalDavDataImport method sync.
private void sync(OperationContext octxt, CalendarFolder cf) throws ServiceException, IOException, DavException, HttpException {
Folder syncFolder = cf.folder;
// hack alert: caldav import uses sync date field to store sync token
int lastSync = (int) syncFolder.getLastSyncDate();
int currentSync = lastSync;
boolean allDone = false;
HashMap<Integer, Integer> modifiedFromRemote = new HashMap<Integer, Integer>();
ArrayList<Integer> deletedFromRemote = new ArrayList<Integer>();
// loop through as long as there are un'synced local changes
while (!allDone) {
allDone = true;
if (lastSync > 0) {
// Don't push local changes during initial sync.
// push local deletion
List<Integer> deleted = new ArrayList<Integer>();
for (int itemId : mbox.getTombstones(lastSync).getAllIds()) {
if (deletedFromRemote.contains(itemId)) {
// was just deleted from sync
continue;
}
deleted.add(itemId);
}
// move to trash is equivalent to delete
HashSet<Integer> fid = new HashSet<Integer>();
fid.add(Mailbox.ID_FOLDER_TRASH);
List<Integer> trashed = mbox.getModifiedItems(octxt, lastSync, MailItem.Type.UNKNOWN, fid).getFirst();
deleted.addAll(trashed);
if (!deleted.isEmpty()) {
// pushDelete returns true if one or more items were deleted
allDone &= !pushDelete(deleted);
}
// push local modification
fid.clear();
fid.add(syncFolder.getId());
List<Integer> modified = mbox.getModifiedItems(octxt, lastSync, MailItem.Type.UNKNOWN, fid).getFirst();
for (int itemId : modified) {
MailItem item = mbox.getItemById(octxt, itemId, MailItem.Type.UNKNOWN);
if (modifiedFromRemote.containsKey(itemId) && modifiedFromRemote.get(itemId).equals(item.getModifiedSequence()))
// was just downloaded from remote
continue;
try {
pushModify(item);
} catch (Exception e) {
ZimbraLog.datasource.info("Failed to push item " + item.getId(), e);
}
allDone = false;
}
}
if (cf.ctagMatched) {
currentSync = mbox.getLastChangeID();
break;
}
// pull in the changes from the remote server
List<RemoteItem> remoteItems = getRemoteItems(syncFolder);
for (RemoteItem item : remoteItems) {
MailItem localItem = applyRemoteItem(item, syncFolder);
if (localItem != null) {
if (item.status == Status.deleted)
deletedFromRemote.add(localItem.getId());
else
modifiedFromRemote.put(localItem.getId(), localItem.getModifiedSequence());
}
}
currentSync = mbox.getLastChangeID();
lastSync = currentSync;
}
mbox.setSyncDate(octxt, syncFolder.getId(), currentSync);
}
use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.
the class MailItemResource method patchProperties.
/* Modifies the set of dead properties saved for this resource.
* Properties in the parameter 'set' are added to the existing properties.
* Properties in 'remove' are removed.
*/
@Override
public void patchProperties(DavContext ctxt, java.util.Collection<Element> set, java.util.Collection<QName> remove) throws DavException, IOException {
List<QName> reqProps = new ArrayList<QName>();
for (QName n : remove) {
mDeadProps.remove(n);
reqProps.add(n);
}
for (Element e : set) {
QName name = e.getQName();
if (name.equals(DavElements.E_DISPLAYNAME) && (type == MailItem.Type.FOLDER || type == MailItem.Type.MOUNTPOINT)) {
// rename folder
try {
String val = e.getText();
String uri = getUri();
Mailbox mbox = getMailbox(ctxt);
mbox.rename(ctxt.getOperationContext(), mId, type, val, mFolderId);
setProperty(DavElements.P_DISPLAYNAME, val);
UrlNamespace.addToRenamedResource(getOwner(), uri, this);
UrlNamespace.addToRenamedResource(getOwner(), uri.substring(0, uri.length() - 1), this);
} catch (ServiceException se) {
ctxt.getResponseProp().addPropError(DavElements.E_DISPLAYNAME, new DavException(se.getMessage(), DavProtocol.STATUS_FAILED_DEPENDENCY));
}
mDeadProps.remove(name);
continue;
} else if (name.equals(DavElements.E_CALENDAR_COLOR) && (type == MailItem.Type.FOLDER || type == MailItem.Type.MOUNTPOINT)) {
// change color
String colorStr = e.getText();
Color color = new Color(colorStr.substring(0, 7));
byte col = (byte) COLOR_LIST.indexOf(colorStr);
if (col >= 0)
color.setColor(col);
try {
Mailbox mbox = getMailbox(ctxt);
mbox.setColor(ctxt.getOperationContext(), new int[] { mId }, type, color);
} catch (ServiceException se) {
ctxt.getResponseProp().addPropError(DavElements.E_CALENDAR_COLOR, new DavException(se.getMessage(), DavProtocol.STATUS_FAILED_DEPENDENCY));
}
mDeadProps.remove(name);
continue;
} else if (name.equals(DavElements.E_SUPPORTED_CALENDAR_COMPONENT_SET)) {
// change default view
@SuppressWarnings("unchecked") List<Element> elements = e.elements(DavElements.E_COMP);
boolean isTodo = false;
boolean isEvent = false;
for (Element element : elements) {
Attribute attr = element.attribute(DavElements.P_NAME);
if (attr != null && CalComponent.VTODO.name().equals(attr.getValue())) {
isTodo = true;
} else if (attr != null && CalComponent.VEVENT.name().equals(attr.getValue())) {
isEvent = true;
}
}
if (isEvent ^ isTodo) {
// we support a calendar collection of type event or todo, not both or none.
Type type = (isEvent) ? Type.APPOINTMENT : Type.TASK;
try {
Mailbox mbox = getMailbox(ctxt);
mbox.setFolderDefaultView(ctxt.getOperationContext(), mId, type);
// See UrlNamespace.addToRenamedResource()
if (this instanceof Collection) {
((Collection) this).view = type;
}
} catch (ServiceException se) {
ctxt.getResponseProp().addPropError(name, new DavException(se.getMessage(), DavProtocol.STATUS_FAILED_DEPENDENCY));
}
} else {
ctxt.getResponseProp().addPropError(name, new DavException.CannotModifyProtectedProperty(name));
}
continue;
}
mDeadProps.put(name, e);
reqProps.add(name);
}
String configVal = "";
if (mDeadProps.size() > 0) {
org.dom4j.Document doc = org.dom4j.DocumentHelper.createDocument();
Element top = doc.addElement(CONFIG_KEY);
for (Map.Entry<QName, Element> entry : mDeadProps.entrySet()) top.add(entry.getValue().detach());
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputFormat format = OutputFormat.createCompactFormat();
XMLWriter writer = new XMLWriter(out, format);
writer.write(doc);
configVal = new String(out.toByteArray(), "UTF-8");
if (configVal.length() > PROP_LENGTH_LIMIT)
for (Map.Entry<QName, Element> entry : mDeadProps.entrySet()) ctxt.getResponseProp().addPropError(entry.getKey(), new DavException("prop length exceeded", DavProtocol.STATUS_INSUFFICIENT_STORAGE));
}
Mailbox mbox = null;
try {
mbox = getMailbox(ctxt);
mbox.lock.lock();
Metadata data = mbox.getConfig(ctxt.getOperationContext(), CONFIG_KEY);
if (data == null) {
data = new Metadata();
}
data.put(Integer.toString(mId), configVal);
mbox.setConfig(ctxt.getOperationContext(), CONFIG_KEY, data);
} catch (ServiceException se) {
for (QName qname : reqProps) ctxt.getResponseProp().addPropError(qname, new DavException(se.getMessage(), HttpServletResponse.SC_FORBIDDEN));
} finally {
if (mbox != null)
mbox.lock.release();
}
}
use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.
the class MailItemResource method moveORcopyWithOverwrite.
public void moveORcopyWithOverwrite(DavContext ctxt, Collection dest, String newName, boolean deleteOriginal) throws DavException {
try {
if (deleteOriginal)
move(ctxt, dest, newName);
else
copy(ctxt, dest, newName);
} catch (DavException e) {
if (e.getStatus() == HttpServletResponse.SC_PRECONDITION_FAILED) {
// in case of name conflict, delete the existing mail item and
// attempt the move operation again.
// return if the error is not ALREADY_EXISTS
ServiceException se = (ServiceException) e.getCause();
int id = 0;
try {
if (se.getCode().equals(MailServiceException.ALREADY_EXISTS) == false)
throw e;
else {
// get the conflicting item-id
if (se instanceof SoapFaultException) {
// destination belongs other mailbox.
String itemIdStr = ((SoapFaultException) se).getArgumentValue("id");
ItemId itemId = new ItemId(itemIdStr, dest.getItemId().getAccountId());
id = itemId.getId();
} else {
// destination belongs to same mailbox.
String name = null;
for (Argument arg : se.getArgs()) {
if (arg.name != null && arg.value != null && arg.value.length() > 0) {
if (arg.name.equals("name"))
name = arg.value;
/* commented out since the exception is giving wrong itemId for copy.
If the the item is conflicting with an existing item we want the
id of the existing item. But, the exception has the proposed id of
the new item which does not exist yet.
else if (arg.mName.equals("itemId"))
id = Integer.parseInt(arg.mValue);
*/
}
}
if (id <= 0) {
if (name == null && !deleteOriginal) {
// in case of copy get the id from source name since we don't support copy with rename.
name = ctxt.getItem();
}
if (name != null) {
Mailbox mbox = getMailbox(ctxt);
MailItem item = mbox.getItemByPath(ctxt.getOperationContext(), name, dest.getId());
id = item.getId();
} else
throw e;
}
}
}
deleteDestinationItem(ctxt, dest, id);
} catch (ServiceException se1) {
throw new DavException("cannot move/copy item", HttpServletResponse.SC_FORBIDDEN, se1);
}
if (deleteOriginal)
move(ctxt, dest, newName);
else
copy(ctxt, dest, newName);
} else {
throw e;
}
}
}
use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.
the class ScheduleOutbox method handleFreebusyRequest.
private void handleFreebusyRequest(DavContext ctxt, ZComponent vfreebusy, String originator, String rcpt, Element resp) throws DavException, ServiceException {
ZProperty dtstartProp = vfreebusy.getProperty(ICalTok.DTSTART);
ZProperty dtendProp = vfreebusy.getProperty(ICalTok.DTEND);
ZProperty durationProp = vfreebusy.getProperty(ICalTok.DURATION);
if (dtstartProp == null || dtendProp == null && durationProp == null)
throw new DavException("missing dtstart or dtend/duration in the schedule request", HttpServletResponse.SC_BAD_REQUEST, null);
long start, end;
try {
ParsedDateTime startTime = ParsedDateTime.parseUtcOnly(dtstartProp.getValue());
start = startTime.getUtcTime();
if (dtendProp != null) {
end = ParsedDateTime.parseUtcOnly(dtendProp.getValue()).getUtcTime();
} else {
ParsedDuration dur = ParsedDuration.parse(durationProp.getValue());
ParsedDateTime endTime = startTime.add(dur);
end = endTime.getUtcTime();
}
} catch (ParseException pe) {
throw new DavException("can't parse date", HttpServletResponse.SC_BAD_REQUEST, pe);
}
ZimbraLog.dav.debug("rcpt: " + rcpt + ", start: " + new Date(start) + ", end: " + new Date(end));
FreeBusy fb = null;
if (ctxt.isFreebusyEnabled()) {
FreeBusyQuery fbQuery = new FreeBusyQuery(ctxt.getRequest(), ctxt.getAuthAccount(), start, end, null);
fbQuery.addEmailAddress(getAddressFromPrincipalURL(rcpt), FreeBusyQuery.CALENDAR_FOLDER_ALL);
java.util.Collection<FreeBusy> fbResult = fbQuery.getResults();
if (fbResult.size() > 0)
fb = fbResult.iterator().next();
}
if (fb != null) {
String fbMsg = fb.toVCalendar(FreeBusy.Method.REPLY, originator, rcpt, null);
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("2.0;Success");
resp.addElement(DavElements.E_CALENDAR_DATA).setText(fbMsg);
} else {
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("5.3;No f/b for the user");
}
}
Aggregations