Search in sources :

Example 1 with DavException

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);
    }
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) DavException(com.zimbra.cs.dav.DavException) ArrayList(java.util.ArrayList) HttpException(org.apache.http.HttpException) IOException(java.io.IOException)

Example 2 with DavException

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);
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Folder(com.zimbra.cs.mailbox.Folder) ServiceException(com.zimbra.common.service.ServiceException) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) IOException(java.io.IOException) HttpException(org.apache.http.HttpException) DavException(com.zimbra.cs.dav.DavException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) MailItem(com.zimbra.cs.mailbox.MailItem) HashSet(java.util.HashSet)

Example 3 with DavException

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();
    }
}
Also used : Attribute(org.dom4j.Attribute) Element(org.dom4j.Element) ArrayList(java.util.ArrayList) Metadata(com.zimbra.cs.mailbox.Metadata) XMLWriter(org.dom4j.io.XMLWriter) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) DavException(com.zimbra.cs.dav.DavException) QName(org.dom4j.QName) Color(com.zimbra.common.mailbox.Color) OutputFormat(org.dom4j.io.OutputFormat) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Type(com.zimbra.cs.mailbox.MailItem.Type) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Map(java.util.Map) HashMap(java.util.HashMap)

Example 4 with DavException

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;
        }
    }
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Argument(com.zimbra.common.service.ServiceException.Argument) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) DavException(com.zimbra.cs.dav.DavException) ItemId(com.zimbra.cs.service.util.ItemId) SoapFaultException(com.zimbra.common.soap.SoapFaultException)

Example 5 with DavException

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");
    }
}
Also used : FreeBusy(com.zimbra.cs.fb.FreeBusy) DavException(com.zimbra.cs.dav.DavException) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) FreeBusyQuery(com.zimbra.cs.fb.FreeBusyQuery) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException) Date(java.util.Date)

Aggregations

DavException (com.zimbra.cs.dav.DavException)67 ServiceException (com.zimbra.common.service.ServiceException)27 Element (org.dom4j.Element)25 Account (com.zimbra.cs.account.Account)18 Mailbox (com.zimbra.cs.mailbox.Mailbox)18 DavResource (com.zimbra.cs.dav.resource.DavResource)15 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)15 ArrayList (java.util.ArrayList)14 Provisioning (com.zimbra.cs.account.Provisioning)11 Document (org.dom4j.Document)9 DavResponse (com.zimbra.cs.dav.service.DavResponse)8 MailItem (com.zimbra.cs.mailbox.MailItem)8 Invite (com.zimbra.cs.mailbox.calendar.Invite)7 ZMailbox (com.zimbra.client.ZMailbox)6 RequestProp (com.zimbra.cs.dav.DavContext.RequestProp)6 IOException (java.io.IOException)6 Collection (com.zimbra.cs.dav.resource.Collection)5 Folder (com.zimbra.cs.mailbox.Folder)5 CalendarCollection (com.zimbra.cs.dav.resource.CalendarCollection)4 HttpException (org.apache.http.HttpException)4