Search in sources :

Example 21 with ZimbraQueryResults

use of com.zimbra.cs.index.ZimbraQueryResults in project zm-mailbox by Zimbra.

the class SearchConv method handle.

@Override
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);
    SearchConvRequest req = JaxbUtil.elementToJaxb(request);
    boolean nest = ZmBoolean.toBool(req.getNestMessages(), false);
    Account acct = getRequestedAccount(zsc);
    SearchParams params = SearchParams.parse(req, zsc, acct.getPrefMailInitialSearch());
    // append (conv:(convid)) onto the beginning of the queryStr
    ItemId cid = new ItemId(req.getConversationId(), zsc);
    params.setQueryString("conv:\"" + cid.toString(ifmt) + "\" (" + params.getQueryString() + ')');
    // force to group-by-message
    params.setTypes(EnumSet.of(MailItem.Type.MESSAGE));
    Element response = null;
    if (cid.belongsTo(mbox)) {
        // local
        ZimbraQueryResults results = mbox.index.search(zsc.getResponseProtocol(), octxt, params);
        try {
            response = zsc.createElement(MailConstants.SEARCH_CONV_RESPONSE);
            response.addAttribute(MailConstants.A_QUERY_OFFSET, Integer.toString(params.getOffset()));
            SortBy sort = results.getSortBy();
            response.addAttribute(MailConstants.A_SORTBY, sort.toString());
            List<Message> msgs = mbox.getMessagesByConversation(octxt, cid.getId(), sort, -1);
            if (msgs.isEmpty() && zsc.isDelegatedRequest()) {
                throw ServiceException.PERM_DENIED("you do not have sufficient permissions");
            }
            // filter out IMAP \Deleted messages from the message lists
            Conversation conv = mbox.getConversationById(octxt, cid.getId());
            if (conv.isTagged(Flag.FlagInfo.DELETED)) {
                List<Message> raw = msgs;
                msgs = new ArrayList<Message>();
                for (Message msg : raw) {
                    if (!msg.isTagged(Flag.FlagInfo.DELETED)) {
                        msgs.add(msg);
                    }
                }
            }
            Element container = nest ? ToXML.encodeConversationSummary(response, ifmt, octxt, conv, CONVERSATION_FIELD_MASK) : response;
            SearchResponse builder = new SearchResponse(zsc, octxt, container, params);
            builder.setAllRead(conv.getUnreadCount() == 0);
            boolean more = putHits(octxt, ifmt, builder, msgs, results, params, conv);
            response.addAttribute(MailConstants.A_QUERY_MORE, more);
            // call me AFTER putHits since some of the <info> is generated by the getting of the hits!
            builder.add(results.getResultInfo());
        } finally {
            Closeables.closeQuietly(results);
        }
        return response;
    } else {
        // remote
        try {
            Element proxyRequest = zsc.createElement(MailConstants.SEARCH_CONV_REQUEST);
            Account target = Provisioning.getInstance().get(AccountBy.id, cid.getAccountId(), zsc.getAuthToken());
            if (target != null) {
                params.setInlineRule(params.getInlineRule().toLegacyExpandResults(target.getServer()));
            }
            params.encodeParams(proxyRequest);
            proxyRequest.addAttribute(MailConstants.A_NEST_MESSAGES, nest);
            proxyRequest.addAttribute(MailConstants.A_CONV_ID, cid.toString());
            // okay, lets run the search through the query parser -- this has the side-effect of
            // re-writing the query in a format that is OK to proxy to the other server -- since the
            // query has an "AND conv:remote-conv-id" part, the query parser will figure out the right
            // format for us.  TODO somehow make this functionality a bit more exposed in the
            // ZimbraQuery APIs...
            String rewrittenQueryString = mbox.getRewrittenQueryString(octxt, params);
            proxyRequest.addAttribute(MailConstants.E_QUERY, rewrittenQueryString, Element.Disposition.CONTENT);
            // proxy to remote account
            response = proxyRequest(proxyRequest, context, target.getId());
            return response.detach();
        } catch (SoapFaultException e) {
            throw ServiceException.FAILURE("SoapFaultException: ", e);
        }
    }
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Account(com.zimbra.cs.account.Account) SearchParams(com.zimbra.cs.index.SearchParams) Message(com.zimbra.cs.mailbox.Message) ItemIdFormatter(com.zimbra.cs.service.util.ItemIdFormatter) SortBy(com.zimbra.cs.index.SortBy) Element(com.zimbra.common.soap.Element) Conversation(com.zimbra.cs.mailbox.Conversation) ItemId(com.zimbra.cs.service.util.ItemId) SoapFaultException(com.zimbra.common.soap.SoapFaultException) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ZimbraQueryResults(com.zimbra.cs.index.ZimbraQueryResults) SearchConvRequest(com.zimbra.soap.mail.message.SearchConvRequest)

Example 22 with ZimbraQueryResults

use of com.zimbra.cs.index.ZimbraQueryResults in project zm-mailbox by Zimbra.

the class ArchiveFormatter method formatCallback.

@Override
public void formatCallback(UserServletContext context) throws IOException, ServiceException, UserServletException {
    // Disable the jetty timeout
    disableJettyTimeout(context);
    HashMap<Integer, Integer> cnts = new HashMap<Integer, Integer>();
    int dot;
    HashMap<Integer, String> fldrs = new HashMap<Integer, String>();
    String emptyname = context.params.get("emptyname");
    String ext = "." + getType();
    String filename = context.params.get("filename");
    String lock = context.params.get("lock");
    String query = context.getQueryString();
    Set<String> names = new HashSet<String>(4096);
    Set<MailItem.Type> sysTypes = EnumSet.of(MailItem.Type.FOLDER, MailItem.Type.SEARCHFOLDER, MailItem.Type.TAG, MailItem.Type.FLAG, MailItem.Type.MOUNTPOINT);
    Set<MailItem.Type> searchTypes = EnumSet.of(MailItem.Type.MESSAGE, MailItem.Type.CONTACT, MailItem.Type.DOCUMENT, MailItem.Type.WIKI, MailItem.Type.APPOINTMENT, MailItem.Type.TASK, MailItem.Type.CHAT, MailItem.Type.NOTE);
    ArchiveOutputStream aos = null;
    String types = context.getTypesString();
    MailboxMaintenance maintenance = null;
    try {
        if (filename == null || filename.equals("")) {
            Date date = new Date();
            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
            SimpleDateFormat sdf = new SimpleDateFormat(".H-m-s");
            if (context.hasPart()) {
                filename = "attachments";
            } else {
                filename = context.targetMailbox.getAccountId() + '.' + df.format(date).replace('/', '-') + sdf.format(date);
            }
        } else if ((dot = filename.lastIndexOf('.')) != -1) {
            String userProvidedExtension = filename.substring(dot + 1);
            if (BLE.contains(userProvidedExtension.toUpperCase())) {
                filename = filename.substring(0, dot);
            }
        }
        if (!filename.endsWith(ext)) {
            filename += ext;
        }
        if (emptyname != null && !emptyname.equals("") && !emptyname.endsWith(ext)) {
            emptyname += ext;
        }
        context.resp.addHeader("Content-Disposition", HttpUtil.createContentDisposition(context.req, Part.ATTACHMENT, filename));
        if (ext.equals(".tar")) {
            context.resp.setContentType("application/x-tar");
        } else if (ext.equals(".tgz")) {
            context.resp.setContentType("application/x-compressed-tar");
        } else if (ext.equals(".zip")) {
            context.resp.setContentType("application/zip");
        }
        if (!Strings.isNullOrEmpty(types)) {
            try {
                searchTypes = MailItem.Type.setOf(types);
            } catch (IllegalArgumentException e) {
                throw MailServiceException.INVALID_TYPE(e.getMessage());
            }
            sysTypes.clear();
            // do not include conversations even when requested
            // (to be compatible with 7.1.4 and later. bug 67407)
            searchTypes.remove(MailItem.Type.CONVERSATION);
        }
        if (lock != null && (lock.equals("1") || lock.equals("t") || lock.equals("true"))) {
            maintenance = MailboxManager.getInstance().beginMaintenance(context.targetMailbox.getAccountId(), context.targetMailbox.getId());
        }
        Charset charset = context.getCharset();
        CharsetEncoder encoder = charset.newEncoder();
        if (context.requestedItems != null) {
            try {
                for (UserServletContext.Item item : context.requestedItems) aos = saveItem(context, item.mailItem, fldrs, cnts, item.versioned, aos, encoder, names);
            } catch (Exception e) {
                warn(e);
            }
        } else if (context.target != null && !(context.target instanceof Folder)) {
            try {
                aos = saveItem(context, context.target, fldrs, cnts, false, aos, encoder, names);
            } catch (Exception e) {
                warn(e);
            }
        } else {
            ZimbraQueryResults results = null;
            boolean saveTargetFolder = false;
            if (context.target instanceof Folder) {
                Folder f = (Folder) context.target;
                if (f.getId() != Mailbox.ID_FOLDER_USER_ROOT) {
                    saveTargetFolder = true;
                    query = "under:\"" + f.getPath() + "\"" + (query == null ? "" : " " + query);
                }
            }
            int maxDays = context.targetAccount.getIntAttr(Provisioning.A_zimbraExportMaxDays, 0);
            if (maxDays > 0) {
                if (context.getStartTime() == TIME_UNSPECIFIED || context.getEndTime() == TIME_UNSPECIFIED || context.getEndTime() == 0) {
                    ZimbraLog.misc.warn("Export rejected. start and end param must be set. end param must be non-zero");
                    throw new ExportPeriodNotSpecifiedException(maxDays);
                } else if (context.getEndTime() - context.getStartTime() > maxDays * Constants.MILLIS_PER_DAY) {
                    long requestDays = (long) Math.ceil((double) (context.getEndTime() - context.getStartTime()) / Constants.MILLIS_PER_DAY);
                    ZimbraLog.misc.warn("Export rejected. Specified period %d days is longer than zimbraExportMaxDays %d days.", requestDays, maxDays);
                    throw new ExportPeriodTooLongException(requestDays, maxDays);
                }
            }
            String taskQuery = query;
            if (query == null) {
                query = "";
            }
            String calendarQuery = query;
            if (context.getStartTime() != TIME_UNSPECIFIED) {
                query = query + " after:" + context.getStartTime();
                calendarQuery = calendarQuery + " appt-start:>=" + context.getStartTime();
            }
            if (context.getEndTime() != TIME_UNSPECIFIED) {
                query = query + " before:" + context.getEndTime();
                calendarQuery = calendarQuery + " appt-end:<" + context.getEndTime();
            }
            if (query == null || query.equals("")) {
                SortPath sp = new SortPath();
                for (MailItem.Type type : sysTypes) {
                    List<MailItem> items = context.targetMailbox.getItemList(context.opContext, type);
                    Collections.sort(items, sp);
                    for (MailItem item : items) {
                        aos = saveItem(context, item, fldrs, cnts, false, aos, encoder, names);
                    }
                }
                query = "is:local";
            }
            Map<Set<MailItem.Type>, String> typesMap = new HashMap<Set<MailItem.Type>, String>();
            typesMap.put(searchTypes, query);
            if (context.getStartTime() != TIME_UNSPECIFIED || context.getEndTime() != TIME_UNSPECIFIED) {
                if (searchTypes.contains(MailItem.Type.APPOINTMENT)) {
                    searchTypes.remove(MailItem.Type.APPOINTMENT);
                    Set<MailItem.Type> calendarTypes = new HashSet<MailItem.Type>();
                    calendarTypes.add(MailItem.Type.APPOINTMENT);
                    typesMap.put(calendarTypes, calendarQuery);
                }
                if (searchTypes.contains(MailItem.Type.TASK)) {
                    searchTypes.remove(MailItem.Type.TASK);
                    Set<MailItem.Type> taskTypes = new HashSet<MailItem.Type>();
                    taskTypes.add(MailItem.Type.TASK);
                    typesMap.put(taskTypes, (StringUtil.isNullOrEmpty(taskQuery)) ? "is:local" : taskQuery);
                }
            }
            for (Map.Entry<Set<MailItem.Type>, String> entry : typesMap.entrySet()) {
                results = context.targetMailbox.index.search(context.opContext, entry.getValue(), entry.getKey(), SortBy.NONE, LC.zimbra_archive_formatter_search_chunk_size.intValue());
                try {
                    while (results.hasNext()) {
                        if (saveTargetFolder) {
                            saveTargetFolder = false;
                            aos = saveItem(context, context.target, fldrs, cnts, false, aos, encoder, names);
                        }
                        aos = saveItem(context, results.getNext().getMailItem(), fldrs, cnts, false, aos, encoder, names);
                    }
                    Closeables.closeQuietly(results);
                    results = null;
                } catch (Exception e) {
                    warn(e);
                } finally {
                    Closeables.closeQuietly(results);
                }
            }
        }
        if (aos == null) {
            if (emptyname == null) {
                context.resp.setHeader("Content-Disposition", null);
                throw new UserServletException(HttpServletResponse.SC_NO_CONTENT, "No data found");
            }
            context.resp.setHeader("Content-Disposition", HttpUtil.createContentDisposition(context.req, Part.ATTACHMENT, emptyname));
            aos = getOutputStream(context, UTF8);
        }
    } finally {
        if (maintenance != null) {
            MailboxManager.getInstance().endMaintenance(maintenance, true, true);
        }
        if (aos != null) {
            try {
                aos.close();
            } catch (Exception e) {
            }
        }
    }
}
Also used : EnumSet(java.util.EnumSet) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) SearchFolder(com.zimbra.cs.mailbox.SearchFolder) Folder(com.zimbra.cs.mailbox.Folder) CharsetEncoder(java.nio.charset.CharsetEncoder) ExportPeriodNotSpecifiedException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodNotSpecifiedException) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) UserServletContext(com.zimbra.cs.service.UserServletContext) UserServletException(com.zimbra.cs.service.UserServletException) MailboxMaintenance(com.zimbra.cs.mailbox.MailboxMaintenance) Charset(java.nio.charset.Charset) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) Date(java.util.Date) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) ExportPeriodNotSpecifiedException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodNotSpecifiedException) ServiceException(com.zimbra.common.service.ServiceException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ExportPeriodTooLongException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodTooLongException) UserServletException(com.zimbra.cs.service.UserServletException) ExportPeriodTooLongException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodTooLongException) MailItem(com.zimbra.cs.mailbox.MailItem) SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) ZimbraQueryResults(com.zimbra.cs.index.ZimbraQueryResults) SimpleDateFormat(java.text.SimpleDateFormat) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

ZimbraQueryResults (com.zimbra.cs.index.ZimbraQueryResults)22 Mailbox (com.zimbra.cs.mailbox.Mailbox)13 ZimbraHit (com.zimbra.cs.index.ZimbraHit)11 OperationContext (com.zimbra.cs.mailbox.OperationContext)11 ServiceException (com.zimbra.common.service.ServiceException)9 ArrayList (java.util.ArrayList)9 SearchParams (com.zimbra.cs.index.SearchParams)8 Element (com.zimbra.common.soap.Element)6 Account (com.zimbra.cs.account.Account)5 IOException (java.io.IOException)5 Test (org.junit.Test)5 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)4 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)4 HashMap (java.util.HashMap)4 MessageHit (com.zimbra.cs.index.MessageHit)3 SortBy (com.zimbra.cs.index.SortBy)3 Contact (com.zimbra.cs.mailbox.Contact)3 Message (com.zimbra.cs.mailbox.Message)3 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)3 ZMailbox (com.zimbra.client.ZMailbox)2