Search in sources :

Example 1 with AdditionalEventInfo

use of org.apache.jackrabbit.spi.commons.AdditionalEventInfo in project jackrabbit by apache.

the class EventJournalResourceImpl method spool.

@Override
public void spool(OutputContext outputContext) throws IOException {
    Calendar cal = Calendar.getInstance(Locale.ENGLISH);
    try {
        outputContext.setContentType("application/atom+xml; charset=UTF-8");
        outputContext.setProperty("Vary", "If-None-Match");
        // TODO: Content-Encoding: gzip
        // find out where to start
        long prevts = -1;
        String inm = request.getHeader("If-None-Match");
        if (inm != null) {
            // TODO: proper parsing when comma-delimited
            inm = inm.trim();
            if (inm.startsWith("\"") && inm.endsWith("\"")) {
                String tmp = inm.substring(1, inm.length() - 1);
                try {
                    prevts = Long.parseLong(tmp, 16);
                    journal.skipTo(prevts);
                } catch (NumberFormatException ex) {
                // broken etag
                }
            }
        }
        boolean hasPersistEvents = false;
        if (outputContext.hasStream()) {
            long lastts = -1;
            long now = System.currentTimeMillis();
            boolean done = false;
            // collect events
            List<Event> events = new ArrayList<Event>(MAXEV);
            while (!done && journal.hasNext()) {
                Event e = journal.nextEvent();
                hasPersistEvents |= e.getType() == Event.PERSIST;
                if (e.getDate() != lastts) {
                    // consider stopping
                    if (events.size() > MAXEV) {
                        done = true;
                    }
                    if (e.getDate() > now + MAXWAIT) {
                        done = true;
                    }
                }
                if (!done && (prevts == -1 || e.getDate() >= prevts)) {
                    events.add(e);
                }
                lastts = e.getDate();
            }
            if (lastts >= 0) {
                // construct ETag from newest event
                outputContext.setETag("\"" + Long.toHexString(lastts) + "\"");
            }
            OutputStream os = outputContext.getOutputStream();
            StreamResult streamResult = new StreamResult(os);
            SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance();
            TransformerHandler th = tf.newTransformerHandler();
            Transformer s = th.getTransformer();
            s.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            s.setOutputProperty(OutputKeys.INDENT, "yes");
            s.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            th.setResult(streamResult);
            th.startDocument();
            th.startElement(ATOMNS, FEED, FEED, NOATTRS);
            writeAtomElement(th, TITLE, "EventJournal for " + getLocator().getWorkspaceName());
            th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS);
            writeAtomElement(th, NAME, "Jackrabbit Event Journal Feed Generator");
            th.endElement(ATOMNS, AUTHOR, AUTHOR);
            String id = getFullUri(request);
            writeAtomElement(th, ID, id);
            AttributesImpl linkattrs = new AttributesImpl();
            linkattrs.addAttribute(null, "self", "self", "CDATA", id);
            writeAtomElement(th, LINK, linkattrs, null);
            cal.setTimeInMillis(lastts >= 0 ? lastts : now);
            String upd = ISO8601.format(cal);
            writeAtomElement(th, UPDATED, upd);
            String lastDateString = "";
            long lastTimeStamp = 0;
            long index = 0;
            AttributesImpl contentatt = new AttributesImpl();
            contentatt.addAttribute(null, "type", "type", "CDATA", EVENTMEDIATYPE);
            while (!events.isEmpty()) {
                List<Event> bundle = null;
                String path = null;
                String op;
                if (hasPersistEvents) {
                    bundle = new ArrayList<Event>();
                    Event e = null;
                    op = "operations";
                    do {
                        e = events.remove(0);
                        bundle.add(e);
                        // compute common path
                        if (path == null) {
                            path = e.getPath();
                        } else {
                            if (e.getPath() != null && e.getPath().length() < path.length()) {
                                path = e.getPath();
                            }
                        }
                    } while (e.getType() != Event.PERSIST && !events.isEmpty());
                } else {
                    // no persist events
                    Event e = events.remove(0);
                    bundle = Collections.singletonList(e);
                    path = e.getPath();
                    op = EventUtil.getEventName(e.getType());
                }
                Event firstEvent = bundle.get(0);
                String entryupd = lastDateString;
                if (lastTimeStamp != firstEvent.getDate()) {
                    cal.setTimeInMillis(firstEvent.getDate());
                    entryupd = ISO8601.format(cal);
                    index = 0;
                } else {
                    index += 1;
                }
                th.startElement(ATOMNS, ENTRY, ENTRY, NOATTRS);
                String entrytitle = op + (path != null ? (": " + path) : "");
                writeAtomElement(th, TITLE, entrytitle);
                String entryid = id + "?type=journal&ts=" + Long.toHexString(firstEvent.getDate()) + "-" + index;
                writeAtomElement(th, ID, entryid);
                String author = firstEvent.getUserID() == null || firstEvent.getUserID().length() == 0 ? null : firstEvent.getUserID();
                if (author != null) {
                    th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS);
                    writeAtomElement(th, NAME, author);
                    th.endElement(ATOMNS, AUTHOR, AUTHOR);
                }
                writeAtomElement(th, UPDATED, entryupd);
                th.startElement(ATOMNS, CONTENT, CONTENT, contentatt);
                for (Event e : bundle) {
                    // serialize the event
                    th.startElement(EVNS, E_EVENT, E_EVENT, NOATTRS);
                    // DAV:href
                    if (e.getPath() != null) {
                        boolean isCollection = (e.getType() == Event.NODE_ADDED || e.getType() == Event.NODE_REMOVED);
                        String href = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), e.getPath(), false).getHref(isCollection);
                        th.startElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, DavConstants.XML_HREF, NOATTRS);
                        th.characters(href.toCharArray(), 0, href.length());
                        th.endElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, DavConstants.XML_HREF);
                    }
                    // event type
                    String evname = EventUtil.getEventName(e.getType());
                    th.startElement(EVNS, E_EVENTTYPE, E_EVENTTYPE, NOATTRS);
                    th.startElement(EVNS, evname, evname, NOATTRS);
                    th.endElement(EVNS, evname, evname);
                    th.endElement(EVNS, E_EVENTTYPE, E_EVENTTYPE);
                    // date
                    writeObsElement(th, E_EVENTDATE, Long.toString(e.getDate()));
                    // user data
                    if (e.getUserData() != null && e.getUserData().length() > 0) {
                        writeObsElement(th, E_EVENTUSERDATA, firstEvent.getUserData());
                    }
                    // try to compute nodetype information
                    if (e instanceof AdditionalEventInfo) {
                        try {
                            Name pnt = ((AdditionalEventInfo) e).getPrimaryNodeTypeName();
                            if (pnt != null) {
                                writeObsElement(th, E_EVENTPRIMARNODETYPE, pnt.toString());
                            }
                            Set<Name> mixins = ((AdditionalEventInfo) e).getMixinTypeNames();
                            if (mixins != null) {
                                for (Name mixin : mixins) {
                                    writeObsElement(th, E_EVENTMIXINNODETYPE, mixin.toString());
                                }
                            }
                        } catch (UnsupportedRepositoryOperationException ex) {
                        // optional
                        }
                    }
                    // identifier
                    if (e.getIdentifier() != null) {
                        writeObsElement(th, E_EVENTIDENTIFIER, e.getIdentifier());
                    }
                    // info
                    if (!e.getInfo().isEmpty()) {
                        th.startElement(EVNS, E_EVENTINFO, E_EVENTINFO, NOATTRS);
                        Map<?, ?> m = e.getInfo();
                        for (Map.Entry<?, ?> entry : m.entrySet()) {
                            String key = entry.getKey().toString();
                            Object value = entry.getValue();
                            String t = value != null ? value.toString() : null;
                            writeElement(th, null, key, NOATTRS, t);
                        }
                        th.endElement(EVNS, E_EVENTINFO, E_EVENTINFO);
                    }
                    th.endElement(EVNS, E_EVENT, E_EVENT);
                    lastTimeStamp = e.getDate();
                    lastDateString = entryupd;
                }
                th.endElement(ATOMNS, CONTENT, CONTENT);
                th.endElement(ATOMNS, ENTRY, ENTRY);
            }
            th.endElement(ATOMNS, FEED, FEED);
            th.endDocument();
            os.flush();
        }
    } catch (Exception ex) {
        throw new IOException("error generating feed: " + ex.getMessage());
    }
}
Also used : UnsupportedRepositoryOperationException(javax.jcr.UnsupportedRepositoryOperationException) TransformerHandler(javax.xml.transform.sax.TransformerHandler) Transformer(javax.xml.transform.Transformer) OutputStream(java.io.OutputStream) AdditionalEventInfo(org.apache.jackrabbit.spi.commons.AdditionalEventInfo) ArrayList(java.util.ArrayList) Name(org.apache.jackrabbit.spi.Name) AttributesImpl(org.xml.sax.helpers.AttributesImpl) StreamResult(javax.xml.transform.stream.StreamResult) Calendar(java.util.Calendar) SAXTransformerFactory(javax.xml.transform.sax.SAXTransformerFactory) IOException(java.io.IOException) RepositoryException(javax.jcr.RepositoryException) IOException(java.io.IOException) UnsupportedRepositoryOperationException(javax.jcr.UnsupportedRepositoryOperationException) DavException(org.apache.jackrabbit.webdav.DavException) SAXException(org.xml.sax.SAXException) Event(javax.jcr.observation.Event) Map(java.util.Map)

Aggregations

IOException (java.io.IOException)1 OutputStream (java.io.OutputStream)1 ArrayList (java.util.ArrayList)1 Calendar (java.util.Calendar)1 Map (java.util.Map)1 RepositoryException (javax.jcr.RepositoryException)1 UnsupportedRepositoryOperationException (javax.jcr.UnsupportedRepositoryOperationException)1 Event (javax.jcr.observation.Event)1 Transformer (javax.xml.transform.Transformer)1 SAXTransformerFactory (javax.xml.transform.sax.SAXTransformerFactory)1 TransformerHandler (javax.xml.transform.sax.TransformerHandler)1 StreamResult (javax.xml.transform.stream.StreamResult)1 Name (org.apache.jackrabbit.spi.Name)1 AdditionalEventInfo (org.apache.jackrabbit.spi.commons.AdditionalEventInfo)1 DavException (org.apache.jackrabbit.webdav.DavException)1 SAXException (org.xml.sax.SAXException)1 AttributesImpl (org.xml.sax.helpers.AttributesImpl)1