You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2010/02/16 19:12:42 UTC

svn commit: r910634 - in /cxf/trunk: rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/ rt/management-web/src/main/java/org/apache/cxf/management/web/loggin...

Author: sergeyb
Date: Tue Feb 16 18:12:37 2010
New Revision: 910634

URL: http://svn.apache.org/viewvc?rev=910634&view=rev
Log:
Providing an option to link log feeds with the services page

Modified:
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/StandardConverter.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPullSpringTest.java
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompull/WEB-INF/beans.xml

Modified: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java (original)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java Tue Feb 16 18:12:37 2010
@@ -22,9 +22,11 @@
 import java.io.StringWriter;
 import java.text.MessageFormat;
 import java.util.Date;
+import java.util.UUID;
 
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
 
 import org.apache.commons.lang.Validate;
 import org.apache.commons.lang.builder.EqualsBuilder;
@@ -42,6 +44,9 @@
 @XmlRootElement(namespace = "http://cxf.apache.org/log")
 public class LogRecord {
 
+    @XmlTransient
+    private String id = "uuid:" + UUID.randomUUID().toString();
+    
     private Date eventTimestamp = new Date();
     private LogLevel level = LogLevel.INFO;
     private String message = "";
@@ -53,6 +58,10 @@
         
     }
     
+    public LogRecord(String id) {
+        this.id = id;
+    }
+    
     public LogRecord(LogRecord copy) {
         this.eventTimestamp = copy.getEventTimestamp();
         this.level = copy.getLevel();
@@ -90,6 +99,10 @@
         return record;
     }
 
+    public String getId() {
+        return id;
+    }
+    
     @XmlElement(namespace = "http://cxf.apache.org/log")
     public Date getEventTimestamp() {
         return eventTimestamp;

Modified: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java (original)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java Tue Feb 16 18:12:37 2010
@@ -25,6 +25,7 @@
 import java.util.logging.Logger;
 
 import org.apache.commons.lang.Validate;
+import org.apache.cxf.Bus;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.management.web.logging.LogLevel;
 
@@ -33,7 +34,8 @@
 
     private List<LoggerLevel> loggers = new ArrayList<LoggerLevel>();
     private boolean initialized;
-
+    private Bus bus;
+    
     /**
      * Creates unconfigured and uninitialized bean. To configure setters must be used, then {@link #init()}
      * must be called.
@@ -47,6 +49,13 @@
         loggers.add(new LoggerLevel("", "INFO"));
     }
 
+    public void setBus(Bus bus) {
+        this.bus = bus;
+    }
+    
+    public Bus getBus() {
+        return bus;
+    }
 
     /**
      * Set one or more loggers and levels descriptor. <br>
@@ -115,7 +124,7 @@
             l.setLevel(LogLevel.toJUL(LogLevel.valueOf(loggers.get(i).getLevel())));
         }
     }
-
+    
     protected abstract Handler createHandler();
     
     protected void checkInit() {

Modified: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java (original)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java Tue Feb 16 18:12:37 2010
@@ -18,6 +18,8 @@
  */
 package org.apache.cxf.management.web.logging.atom;
 
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.WeakHashMap;
@@ -25,10 +27,15 @@
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriBuilder;
 
+import org.apache.abdera.model.Entry;
 import org.apache.abdera.model.Feed;
+import org.apache.cxf.Bus;
 import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.ext.search.ConditionType;
 import org.apache.cxf.jaxrs.ext.search.OrSearchCondition;
@@ -38,16 +45,11 @@
 import org.apache.cxf.management.web.logging.ReadWriteLogStorage;
 import org.apache.cxf.management.web.logging.ReadableLogStorage;
 import org.apache.cxf.management.web.logging.atom.converter.StandardConverter;
-import org.apache.cxf.management.web.logging.atom.converter.StandardConverter.Format;
-import org.apache.cxf.management.web.logging.atom.converter.StandardConverter.Multiplicity;
-import org.apache.cxf.management.web.logging.atom.converter.StandardConverter.Output;
 
 
-@Path("logs")
+@Path("/logs")
 public class AtomPullServer extends AbstractAtomBean {
 
-    private StandardConverter converter = 
-        new StandardConverter(Output.FEED, Multiplicity.MANY, Format.CONTENT);
     private List<LogRecord> records = new LinkedList<LogRecord>();
     private WeakHashMap<Integer, Feed> feeds = new WeakHashMap<Integer, Feed>();
     private ReadableLogStorage storage;
@@ -61,6 +63,17 @@
     @Context
     private MessageContext context;
     
+    private String endpointAddress;
+    private String serverAddress;
+    
+    public void setEndpointAddress(String address) {
+        this.endpointAddress = address;
+    }
+    
+    public void setServerAddress(String address) {
+        this.serverAddress = address;
+    }
+    
     @Override
     public void init() {
         // the storage might've been used to save previous records or it might
@@ -90,13 +103,34 @@
             }
             condition = new OrSearchCondition<LogRecord>(list);
         }
-        
+        initBusProperty();
+    }
+    
+    @Override
+    protected Handler createHandler() {
+        return new AtomPullHandler(this);
+    }
+    
+    protected void initBusProperty() {
+        if (endpointAddress != null && serverAddress != null && getBus() != null) {
+            Bus bus = getBus();
+            synchronized (bus) {
+                bus.setProperty("org.apache.cxf.extensions.logging.atom.pull",
+                    Collections.singletonMap(endpointAddress, serverAddress + "/logs"));
+            }
+        }
+    }
+    
+    @GET
+    @Produces("application/atom+xml")
+    public Feed getXmlFeed(@PathParam("id") int page) {
+        return getXmlFeedWithPage(1);
     }
     
     @GET
     @Produces("application/atom+xml")
-    public Feed getRecords() {
-        int page = getPageValue();
+    @Path("{id}")
+    public Feed getXmlFeedWithPage(@PathParam("id") int page) {
         
         // lets check if the Atom reader is asking for a set of records which has already been 
         // converted to Feed
@@ -111,7 +145,8 @@
         Feed feed = null;
         synchronized (records) {
             List<LogRecord> list = getSubList(page);
-            feed = (Feed)converter.convert(list).get(0);
+            Collections.sort(list, new LogRecordComparator());
+            feed = (Feed)new CustomFeedConverter(page).convert(list).get(0);
             setFeedPageProperties(feed, page);
         }
         // if at the moment we've converted n < pageSize number of records only and
@@ -124,14 +159,58 @@
         }
         return feed;
     }
+    
+    @GET
+    @Produces({"text/xml", "application/xhtml+xml" })
+    @Path("alternate/{id}")
+    public String getAlternateFeed(@PathParam("id") int page) {
+        List<LogRecord> list = getSubList(page);
+        Collections.sort(list, new LogRecordComparator());
+        return convertEntriesToHtml(list);
+        
+    }
 
     @GET
+    @Path("entry/{id}")
+    @Produces("application/atom+xml;type=entry")
+    public Entry getEntry(@PathParam("id") int index) {
+        List<LogRecord> list = getLogRecords(index);
+        return (Entry)new CustomEntryConverter(index).convert(list).get(0);
+    }
+    
+    @GET
+    @Path("entry/alternate/{id}")
+    @Produces({"text/xml", "application/xhtml+xml" })
+    public String getAlternateEntry(@PathParam("id") int index) {
+        List<LogRecord> logRecords = getLogRecords(index);
+        return convertEntryToHtml(logRecords.get(0));
+    }
+    
+    @GET
     @Path("records")
     @Produces("text/plain")
     public int getNumberOfAvaiableRecords() {
         return recordsSize;
     }
     
+    private List<LogRecord> getLogRecords(int index) {
+        List<LogRecord> list = new LinkedList<LogRecord>();
+        if (storage != null) {
+            int storageSize = storage.getSize();
+            if (recordsSize == -1 || index < storageSize) {
+                storage.load(list, condition, index, 1);
+            } else if (index < recordsSize) {
+                list.add(records.get(index - storageSize));   
+            }
+        } else {
+            list.add(records.get(index));
+        }
+        if (list.size() != 1) { 
+            throw new WebApplicationException(404);
+        }
+        return list;
+    }
+    
     
     protected List<LogRecord> getSubList(int page) {
         
@@ -194,11 +273,11 @@
     }
     
     protected void setFeedPageProperties(Feed feed, int page) {
-        String self = context.getUriInfo().getRequestUri().toString();
+        String self = context.getUriInfo().getAbsolutePath().toString();
         feed.addLink(self, "self");
         
-        String uri = context.getUriInfo().getAbsolutePath().toString();
-        
+        String uri = context.getUriInfo().getBaseUriBuilder().path("logs").build().toString();
+        feed.addLink(uri + "/alternate/" + page, "alternate");
         if (!useArchivedFeeds) {
             if (recordsSize != -1) {
                 if (page > 2) {
@@ -206,21 +285,21 @@
                 }
                 
                 if (page * pageSize < recordsSize) {
-                    feed.addLink(uri + "?page=" + (page + 1), "next");
+                    feed.addLink(uri + "/" + (page + 1), "next");
                 }
                 
                 if (page * (pageSize + 1) < recordsSize) {
-                    feed.addLink(uri + "?page=" + (recordsSize / pageSize + 1), "last");
+                    feed.addLink(uri + "/" + (recordsSize / pageSize + 1), "last");
                 }
             } else if (feed.getEntries().size() == pageSize) {
-                feed.addLink(uri + "?page=" + (page + 1), "next");
+                feed.addLink(uri + "/" + (page + 1), "next");
             }
             if (page > 1) {
-                uri = page > 2 ? uri + "?page=" + (page - 1) : uri;
+                uri = page > 2 ? uri + "/" + (page - 1) : uri;
                 feed.addLink(uri, "previous");
             }
         } else {
-            feed.addLink(uri, "current");
+            feed.addLink(self, "current");
             // TODO : add prev-archive and next-archive; next-archive should not be set if it will point to
             // current
             // and xmlns:fh="http://purl.org/syndication/history/1.0":archive extension but only if
@@ -229,24 +308,6 @@
         
     }
     
-        
-    protected int getPageValue() {
-        String pageValue = context.getUriInfo().getQueryParameters().getFirst("page");
-        int page = 1;
-        try {
-            if (pageValue != null) {
-                page = Integer.parseInt(pageValue);
-            } 
-        } catch (Exception ex) {
-            // default to 1
-        }
-        return page;
-    }
-    
-    @Override
-    protected Handler createHandler() {
-        return new AtomPullHandler(this);
-    }
     
     public void publish(LogRecord record) {
         if (alreadyClosed) {
@@ -291,6 +352,46 @@
         }
     }
     
+    // TODO : this all can be done later on in a simple xslt template
+    private String convertEntriesToHtml(List<LogRecord> rs) {
+        StringBuilder sb = new StringBuilder();
+        startHtmlHeadAndBody(sb, "CXF Service Log Entries");
+        addRecordToTable(sb, rs);
+        sb.append("</body></html>");
+        return sb.toString();
+    }
+    // TODO : this all can be done later on in a simple xslt template
+    private String convertEntryToHtml(LogRecord r) {
+        StringBuilder sb = new StringBuilder();
+        startHtmlHeadAndBody(sb, r.getLevel().toString());
+        addRecordToTable(sb, Collections.singletonList(r));
+        sb.append("</body></html>");
+        return sb.toString();
+    }
+    
+    private void addRecordToTable(StringBuilder sb, List<LogRecord> list) {
+        sb.append("<table border=\"1\">");
+        sb.append("<tr><th>Logger</th><th>Level</th><th>Message</th></tr>");
+        for (LogRecord lr : list) {
+            sb.append("<tr>");
+            sb.append("<td>" + lr.getLoggerName() + "</td>");
+            sb.append("<td>" + lr.getLevel().toString() + "</td>");
+            sb.append("<td>" + lr.getMessage() + "</td>");
+            sb.append("</tr>");
+        }
+        sb.append("</table><br/><br/>");
+    
+    }
+    
+    private void startHtmlHeadAndBody(StringBuilder sb, String title) {
+        sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
+        sb.append("<head>");
+        sb.append("<meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\"/>");
+        sb.append("<title>" + "Log record with level " + title + "</title>");
+        sb.append("</head>");
+        sb.append("<body>");
+    }
+    
     private static class SearchConditionImpl implements SearchCondition<LogRecord> {
         private LogRecord template;
         
@@ -318,11 +419,62 @@
         }
 
         public List<LogRecord> findAll(List<LogRecord> pojos) {
-            // TODO Auto-generated method stub
-            return null;
+            List<LogRecord> list = new LinkedList<LogRecord>();
+            for (LogRecord r : pojos) {
+                if (isMet(r)) {
+                    list.add(r);
+                }
+            }
+            return list;
+        }
+        
+        
+    }
+    
+    private static class LogRecordComparator implements Comparator<LogRecord> {
+
+        public int compare(LogRecord r1, LogRecord r2) {
+            return r1.getEventTimestamp().compareTo(r2.getEventTimestamp()) * -1;
+        }
+        
+    }
+    
+    private class CustomFeedConverter extends StandardConverter {
+        private int page;
+        public CustomFeedConverter(int page) {
+            super(Output.FEED, Multiplicity.MANY, Format.CONTENT);
+            this.page = page;
         }
         
+        @Override
+        protected void setDefaultEntryProperties(Entry entry, List<LogRecord> rs, int entryIndex) {
+            super.setDefaultEntryProperties(entry, rs, entryIndex);
+            UriBuilder builder = context.getUriInfo().getAbsolutePathBuilder().path("entry");
+            Integer realIndex = page == 1 ? entryIndex : page * pageSize + entryIndex;
+
+            entry.addLink(builder.clone().path(realIndex.toString()).build().toString(), "self");
+            entry.addLink(builder.path("alternate").path(realIndex.toString()).build().toString(), 
+                          "alternate");
+        }
         
     }
     
+    private class CustomEntryConverter extends StandardConverter {
+        private String selfFragment;
+        private String altFragment;
+        public CustomEntryConverter(int index) {
+            super(Output.ENTRY, Multiplicity.ONE, Format.CONTENT);
+            this.selfFragment = "logs/entry/" + index;
+            this.altFragment = "logs/alternate/entry/" + index;
+        }
+        
+        @Override
+        protected void setDefaultEntryProperties(Entry entry, List<LogRecord> rs, int entryIndex) {
+            super.setDefaultEntryProperties(entry, rs, entryIndex);
+            entry.addLink(context.getUriInfo().getBaseUriBuilder().path(selfFragment).build().toString(),
+                "self");
+            entry.addLink(context.getUriInfo().getBaseUriBuilder().path(altFragment).build().toString(),
+                "alternate");
+        }
+    }
 }

Modified: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/StandardConverter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/StandardConverter.java?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/StandardConverter.java (original)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/StandardConverter.java Tue Feb 16 18:12:37 2010
@@ -50,7 +50,7 @@
  * Converter producing ATOM Feeds on standalone Entries with LogRecords or LogRecordsLists embedded as content
  * or extension. For configuration details see constructor documentation.
  */
-public final class StandardConverter implements Converter {
+public class StandardConverter implements Converter {
 
     /** Conversion output */
     public enum Output {
@@ -111,7 +111,7 @@
         this.feedBuilder = feedBuilder;
         this.entryBuilder = entryBuilder;
         
-        configure(output, multiplicity, format);
+        configure(output, multiplicity, format); //NOPMD
         df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
         factory = Abdera.getNewFactory();
         try {
@@ -164,14 +164,14 @@
 
     private List<Entry> createEntries(Format format, List<LogRecord> records) {
         List<Entry> entries = new ArrayList<Entry>();
-        for (LogRecord record : records) {
-            entries.add(createEntryFromRecord(format, record));
+        for (int i = 0; i < records.size(); i++) {
+            entries.add(createEntryFromRecord(format, records.get(i), i));
         }
         return entries;
     }
     
     private Entry createEntryFromList(Format format, List<LogRecord> records) {
-        Entry e = createEntry(records);
+        Entry e = createEntry(records, 0);
         if (format == Format.CONTENT) {
             setEntryContent(e, createContent(records));
         } else {
@@ -180,8 +180,8 @@
         return e;
     }
     
-    private Entry createEntryFromRecord(Format format, LogRecord record) {
-        Entry e = createEntry(Collections.singletonList(record));
+    private Entry createEntryFromRecord(Format format, LogRecord record, int entryIndex) {
+        Entry e = createEntry(Collections.singletonList(record), entryIndex);
         if (format == Format.CONTENT) {
             setEntryContent(e, createContent(record));
         } else {
@@ -214,15 +214,11 @@
 
     private ExtensibleElement createExtension(LogRecord record) {
         ExtensibleElement erec = factory.newExtensionElement(qn("logRecord"));
-        String date = df.format(record.getEventTimestamp());
-        // timezone in date does not have semicolon as XML Date requires
-        // e.g we have "2009-11-23T22:03:53.996+0100"
-        // instead of "2009-11-23T22:03:53.996+01:00"
-        date = date.substring(0, date.length() - 2) + ":" + date.substring(date.length() - 2);
+        
         // forget about single line "addExtension().setText()" since
         // javac failure "org.apache.abdera.model.Element cannot be dereferenced"
         Element e = erec.addExtension(qn("eventTimestamp"));
-        e.setText(date);
+        e.setText(toAtomDateFormat(record.getEventTimestamp()));
         e = erec.addExtension(qn("level"));
         e.setText(record.getLevel().toString());
         e = erec.addExtension(qn("loggerName"));
@@ -236,6 +232,14 @@
         return erec;
     }
 
+    private String toAtomDateFormat(Date d) {
+        String date = df.format(d);
+        // timezone in date does not have semicolon as XML Date requires
+        // e.g we have "2009-11-23T22:03:53.996+0100"
+        // instead of "2009-11-23T22:03:53.996+01:00"
+        return date.substring(0, date.length() - 2) + ":" + date.substring(date.length() - 2);
+    }
+    
     private QName qn(String name) {
         return new QName("http://cxf.apache.org/log", name, "log");
     }
@@ -248,9 +252,9 @@
         return list;
     }
 
-    private Entry createEntry(List<LogRecord> records) {
+    private Entry createEntry(List<LogRecord> records, int entryIndex) {
         Entry entry = factory.newEntry();
-        setDefaultEntryProperties(entry, records);
+        setDefaultEntryProperties(entry, records, entryIndex);
         
         return entry;
     }
@@ -304,18 +308,20 @@
         } else {
             feed.setId("uuid:" + UUID.randomUUID().toString());
             feed.addAuthor("CXF");
-            feed.setTitle(String.format("Feed with %d entry(ies)", feed.getEntries().size()));
+            feed.setTitle("CXF Service Log Entries");
             feed.setUpdated(new Date());
         }
     }
     
-    protected void setDefaultEntryProperties(Entry entry, List<LogRecord> records) {
+    protected void setDefaultEntryProperties(Entry entry, List<LogRecord> records,
+                                             int entryIndex) {
         if (entryBuilder != null) {
             entry.setId(entryBuilder.getId(records));
             entry.addAuthor(entryBuilder.getAuthor(records));
             entry.setTitle(entryBuilder.getTitle(records));
             entry.setUpdated(entryBuilder.getUpdated(records));
             entry.setBaseUri(entryBuilder.getBaseUri(records));
+            entry.setSummary(entryBuilder.getSummary(records));
             List<String> categories = entryBuilder.getCategories(records);
             if (categories != null) {
                 for (String category : categories) {
@@ -331,11 +337,19 @@
             entry.setPublished(entryBuilder.getPublished(records));
             entry.setSummary(entryBuilder.getSummary(records));
         } else {    
-            entry.setId("uuid:" + UUID.randomUUID().toString());
             entry.addAuthor("CXF");
-            entry.setTitle(String.format("Entry with %d log record(s)", 
-                                         records.size()));
-            entry.setUpdated(new Date());
+            if (records.size() != 1) {
+                entry.setId("uuid:" + UUID.randomUUID().toString());
+                entry.setTitle(String.format("Entry with %d log record(s)", 
+                                             records.size()));
+            } else {
+                entry.setId(records.get(0).getId());
+                entry.setTitle("Log record with level " + records.get(0).getLevel().toString());
+                entry.setSummary(records.get(0).getLoggerName() + " : " + records.get(0).getMessage());
+            }
+            if (records.size() > 0) {
+                entry.setUpdated(toAtomDateFormat(records.get(0).getEventTimestamp()));
+            }
         }
     }
     

Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java Tue Feb 16 18:12:37 2010
@@ -20,12 +20,14 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -208,6 +210,7 @@
         return ret; 
     }
     
+    @SuppressWarnings("unchecked")
     protected void generateServiceList(HttpServletRequest request, HttpServletResponse response)
         throws IOException {        
         response.setContentType("text/html; charset=UTF-8");        
@@ -235,8 +238,11 @@
         List<ServletDestination> destinations = getServletDestinations();
             
         if (destinations.size() > 0) {
-            writeSOAPEndpoints(response, destinations);
-            writeRESTfulEndpoints(response, destinations);
+            //TODO : we may introduce a bus extension instead
+            Map<String, String> atomMap = 
+                (Map<String, String>)bus.getProperty("org.apache.cxf.extensions.logging.atom.pull");
+            writeSOAPEndpoints(response, destinations, atomMap);
+            writeRESTfulEndpoints(response, destinations, atomMap);
         } else {
             response.getWriter().write("<span class=\"heading\">No services have been found.</span>");
         }
@@ -244,7 +250,8 @@
         response.getWriter().write("</body></html>");
     }
 
-    private void writeSOAPEndpoints(HttpServletResponse response, List<ServletDestination> destinations)
+    private void writeSOAPEndpoints(HttpServletResponse response, List<ServletDestination> destinations,
+                                    Map<String, String> atomMap)
         throws IOException {
         response.getWriter().write("<span class=\"heading\">Available SOAP services:</span><br/>");
         response.getWriter().write("<table " + (serviceListStyleSheet == null
@@ -273,6 +280,7 @@
                 response.getWriter().write("<br/><span class=\"field\">Target namespace:</span> "
                         + "<span class=\"value\">" 
                         + sd.getEndpointInfo().getService().getTargetNamespace() + "</span>");
+                addAtomLinkIfNeeded(address, atomMap, response.getWriter());
                 response.getWriter().write("</td></tr>");
             }    
         }
@@ -280,7 +288,8 @@
     }
     
     
-    private void writeRESTfulEndpoints(HttpServletResponse response, List<ServletDestination> destinations)
+    private void writeRESTfulEndpoints(HttpServletResponse response, List<ServletDestination> destinations,
+                                       Map<String, String> atomMap)
         throws IOException {
         
         List<ServletDestination> restfulDests = new ArrayList<ServletDestination>();
@@ -306,12 +315,36 @@
                 response.getWriter().write("<br/><span class=\"field\">WADL :</span> "
                         + "<a href=\"" + address + "?_wadl&_type=xml\">"
                         + address + "?_wadl&type=xml" + "</a>");
+                addAtomLinkIfNeeded(address, atomMap, response.getWriter());
                 response.getWriter().write("</td></tr>");
             }    
         }
         response.getWriter().write("</table>");
     }
     
+    private static void addAtomLinkIfNeeded(String address, Map<String, String> extMap,
+                                            PrintWriter pw) {
+        String atomAddress = getExtensionEndpointAddress(address, extMap);
+        if (atomAddress != null) {
+            pw.write("<br/><span class=\"field\">Atom Log Feed :</span> "
+                + "<a href=\"" + atomAddress + "\">" + atomAddress + "</a>");
+        }
+    }
+    
+    private static String getExtensionEndpointAddress(String endpointAddress, Map<String, String> extMap) {
+        if (extMap != null) {
+            for (Map.Entry<String, String> entry : extMap.entrySet()) {
+                if (endpointAddress.endsWith(entry.getKey())) {    
+                    endpointAddress = 
+                        endpointAddress.substring(0, endpointAddress.length() - entry.getKey().length());
+                    endpointAddress += entry.getValue();
+                    return endpointAddress;
+                }
+            }
+        }
+        return null;
+    }
+    
     private void renderStyleSheet(HttpServletRequest request,
             HttpServletResponse response) throws IOException {
         response.setContentType("text/css; charset=UTF-8");

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPullSpringTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPullSpringTest.java?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPullSpringTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPullSpringTest.java Tue Feb 16 18:12:37 2010
@@ -37,6 +37,7 @@
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+import org.apache.cxf.jaxrs.provider.AtomEntryProvider;
 import org.apache.cxf.jaxrs.provider.AtomFeedProvider;
 import org.apache.cxf.management.web.logging.LogLevel;
 import org.apache.cxf.management.web.logging.ReadWriteLogStorage;
@@ -77,17 +78,39 @@
         Storage.clearRecords();
     }
 
+    
     @Test
     public void testFeed() throws Exception {
+        String listing = WebClient.create("http://localhost:9080/services").get(String.class);
+        assertTrue(listing.contains("http://localhost:9080/atom/logs"));
         WebClient wc = WebClient.create("http://localhost:9080/resource/root");
         wc.path("/log").get();
         Thread.sleep(3000);
         
-        Feed feed = getFeed("http://localhost:9080/atom/logs");
-        assertEquals(8, feed.getEntries().size());
+        checkSimpleFeed(getFeed("http://localhost:9080/atom/logs").getEntries());
+        checkSimpleFeed(getFeed("http://localhost:9080/atom/logs").getEntries());
+     
+        List<Entry> entries = new LinkedList<Entry>();
+        WebClient wcEntry = WebClient.create("http://localhost:9080/atom/logs",
+            Collections.singletonList(new AtomEntryProvider()))
+            .accept("application/atom+xml;type=entry");
+        HTTPConduit conduit = WebClient.getConfig(wcEntry).getHttpConduit();
+        conduit.getClient().setReceiveTimeout(1000000);
+        conduit.getClient().setConnectionTimeout(1000000);
+        for (int i = 0; i < 8; i++) {
+            Entry entry = wcEntry.path("entry/" + i).get(Entry.class);
+            entry.toString();
+            entries.add(entry);
+            wcEntry.back(true);
+        }
+        checkSimpleFeed(entries);
+    }
+    
+    private void checkSimpleFeed(List<Entry> entries) throws Exception {
+        assertEquals(8, entries.size());
         
         resetCounters();
-        for (Entry e : feed.getEntries()) {
+        for (Entry e : entries) {
             updateCounters(readLogRecord(e.getContent()), "Resource", "namedLogger");
         }
         
@@ -101,7 +124,7 @@
         Thread.sleep(3000);
         
         verifyPages("http://localhost:9080/atom2/logs", "next", 3, 2, "theNamedLogger");
-        verifyPages("http://localhost:9080/atom2/logs?page=3", "previous", 2, 3, "theNamedLogger");
+        verifyPages("http://localhost:9080/atom2/logs/3", "previous", 2, 3, "theNamedLogger");
     }
     
     @Test
@@ -117,14 +140,14 @@
         List<org.apache.cxf.management.web.logging.LogRecord> list = Storage.getRecords();
         assertEquals(4, list.size());
         verifyStoragePages("http://localhost:9080/atom3/logs", "next", "Resource3", "theStorageLogger");
-        verifyStoragePages("http://localhost:9080/atom3/logs?page=2", "previous", "Resource3", 
+        verifyStoragePages("http://localhost:9080/atom3/logs/2", "previous", "Resource3", 
                            "theStorageLogger");
     }
     
     @Test
     public void testPagedFeedWithReadOnlyStorage() throws Exception {
         verifyStoragePages("http://localhost:9080/atom4/logs", "next", "Resource4", "readOnlyStorageLogger");
-        verifyStoragePages("http://localhost:9080/atom4/logs?page=2", "previous", "Resource4", 
+        verifyStoragePages("http://localhost:9080/atom4/logs/2", "previous", "Resource4", 
                            "readOnlyStorageLogger");
     }
     
@@ -185,9 +208,6 @@
     private Feed getFeed(String address) {
         WebClient wc = WebClient.create(address,
                                          Collections.singletonList(new AtomFeedProvider()));
-        HTTPConduit conduit = WebClient.getConfig(wc).getHttpConduit();
-        conduit.getClient().setReceiveTimeout(1000000);
-        conduit.getClient().setConnectionTimeout(1000000);
         Feed feed = wc.accept("application/atom+xml").get(Feed.class);
         feed.toString();
         return feed;

Modified: cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompull/WEB-INF/beans.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompull/WEB-INF/beans.xml?rev=910634&r1=910633&r2=910634&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompull/WEB-INF/beans.xml (original)
+++ cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompull/WEB-INF/beans.xml Tue Feb 16 18:12:37 2010
@@ -44,6 +44,11 @@
 			value="
 			org.apache.cxf.systest.jaxrs.JAXRSLoggingAtomPullSpringTest$Resource:ALL,
 			namedLogger:WARN" />
+		  <property name="bus">
+			<ref bean="cxf" />	
+		  </property>	
+		  <property name="endpointAddress" value="/resource"/>
+		  <property name="serverAddress" value="/atom"/>
 	</bean>
 	
 	<bean id = "atomPullServer2" class="org.apache.cxf.management.web.logging.atom.AtomPullServer" 
@@ -87,6 +92,9 @@
 	<bean id="feed" class="org.apache.cxf.jaxrs.provider.AtomFeedProvider">
 	    <property name="formattedOutput" value="true"/>
 	</bean>
+	<bean id="entry" class="org.apache.cxf.jaxrs.provider.AtomEntryProvider">
+	    <property name="formattedOutput" value="true"/>
+	</bean>
 
 	<jaxrs:server id="resourceServer" address="/resource">
 		<jaxrs:serviceBeans>
@@ -121,6 +129,7 @@
 		</jaxrs:serviceBeans>
 		<jaxrs:providers>
 			<ref bean="feed" />
+			<ref bean="entry" />
 		</jaxrs:providers>
 	</jaxrs:server>