cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r902834 [1/2] - in /cxf/trunk: rt/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/ rt/management-web/ rt/management-web/src/ rt/management-web/src/main/ rt/management-web/src/main/java/ rt/management-web/src/main/java/org/...
Date Mon, 25 Jan 2010 14:51:52 GMT
Author: sergeyb
Date: Mon Jan 25 14:51:51 2010
New Revision: 902834

URL: http://svn.apache.org/viewvc?rev=902834&view=rev
Log:
Creating rt/management-web module and moving JAXRS atom logging code into it

Added:
    cxf/trunk/rt/management-web/
    cxf/trunk/rt/management-web/pom.xml   (with props)
    cxf/trunk/rt/management-web/src/
    cxf/trunk/rt/management-web/src/main/
    cxf/trunk/rt/management-web/src/main/java/
    cxf/trunk/rt/management-web/src/main/java/org/
    cxf/trunk/rt/management-web/src/main/java/org/apache/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/LoggingThread.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/Converter.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/converter/StandardConverter.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/deliverer/
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/deliverer/Deliverer.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/deliverer/RetryingDeliverer.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/deliverer/WebClientDeliverer.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/package-info.java   (with props)
    cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/package-info.java   (with props)
    cxf/trunk/rt/management-web/src/test/
    cxf/trunk/rt/management-web/src/test/java/
    cxf/trunk/rt/management-web/src/test/java/apache/
    cxf/trunk/rt/management-web/src/test/java/apache/cxf/
    cxf/trunk/rt/management-web/src/test/java/apache/cxf/management/
    cxf/trunk/rt/management-web/src/test/java/apache/cxf/management/web/
Removed:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/
Modified:
    cxf/trunk/rt/pom.xml
    cxf/trunk/systests/jaxrs/pom.xml
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPullSpringTest.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushSpringTest.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushTest.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/logging_atompush.properties
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/logging_atompush_atompub.properties
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/logging_atompush_batch.properties
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompull/WEB-INF/beans.xml
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/beans.xml

Added: cxf/trunk/rt/management-web/pom.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/pom.xml?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/pom.xml (added)
+++ cxf/trunk/rt/management-web/pom.xml Mon Jan 25 14:51:51 2010
@@ -0,0 +1,85 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+ 
+  http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.cxf</groupId>
+    <artifactId>cxf-rt-management-web</artifactId>
+    <packaging>jar</packaging>
+    <version>2.3.0-SNAPSHOT</version>
+    <name>Apache CXF Runtime Web Management</name>
+    <url>http://cxf.apache.org</url>
+
+    <parent>
+        <groupId>org.apache.cxf</groupId>
+        <artifactId>cxf-parent</artifactId>
+        <version>2.3.0-SNAPSHOT</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-common-utilities</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+        </dependency>
+
+        
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymockclassextension</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-management</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+
+
+</project>

Propchange: cxf/trunk/rt/management-web/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/trunk/rt/management-web/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlTransient;
+
+/**
+ * Log level of {@link LogRecord}. Based on SLF4J being popular facade for loggers like JUL, Log4J, JCL and so
+ * on. Severities order is: FATAL > ERROR > WARN > INFO > DEBUG > TRACE.
+ * <p>
+ * Mapping of levels:
+ * <ol>
+ * <li>JUL - same as <a href="http://www.slf4j.org/apidocs/org/slf4j/bridge/SLF4JBridgeHandler.html">SLF4J
+ * approach</a>.</li>
+ * <li>Log4J - levels are identical</li>
+ * </ol>
+ */
+@XmlEnum
+public enum LogLevel {
+    ALL,
+    FATAL,
+    ERROR,
+    WARN,
+    INFO,
+    DEBUG,
+    TRACE,
+    OFF;
+
+    @XmlTransient
+    private static Map<Level, LogLevel> fromJul = new HashMap<Level, LogLevel>();
+
+    @XmlTransient
+    private static Map<LogLevel, Level> toJul = new HashMap<LogLevel, Level>();
+
+    static {        
+        fromJul.put(Level.ALL, LogLevel.ALL);
+        fromJul.put(Level.SEVERE, LogLevel.ERROR);
+        fromJul.put(Level.WARNING, LogLevel.WARN);
+        fromJul.put(Level.INFO, LogLevel.INFO);
+        fromJul.put(Level.FINE, LogLevel.DEBUG);
+        fromJul.put(Level.FINER, LogLevel.DEBUG);
+        fromJul.put(Level.FINEST, LogLevel.TRACE);
+        fromJul.put(Level.OFF, LogLevel.OFF);
+
+        toJul.put(LogLevel.ALL, Level.ALL);
+        toJul.put(LogLevel.FATAL, Level.SEVERE);
+        toJul.put(LogLevel.ERROR, Level.SEVERE);
+        toJul.put(LogLevel.WARN, Level.WARNING);
+        toJul.put(LogLevel.INFO, Level.INFO);
+        toJul.put(LogLevel.DEBUG, Level.FINE);
+        toJul.put(LogLevel.TRACE, Level.FINEST);
+        toJul.put(LogLevel.OFF, Level.OFF);
+    }
+
+    /**
+     * Creates this enum from JUL {@link Level}.
+     */
+    public static LogLevel fromJUL(Level level) {
+        return fromJul.get(level);
+    }
+
+    /**
+     * Creates this JUL {@link Level} from this enum.
+     */
+    public static Level toJUL(LogLevel level) {
+        return toJul.get(level);
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogLevel.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 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=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,182 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.MessageFormat;
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.commons.lang.Validate;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+/**
+ * Log entry serializable to XML. Based on common set of {@link java.util.logging.LogRecord} and
+ * {@link org.apache.log4j.spi.LoggingEvent} attributes.
+ * <p>
+ * LogRecord are never null; if some attributes are not set (e.g. logger name, or rendered cause taken from
+ * Throwable) empty strings are returned.
+ */
+@XmlRootElement(namespace = "http://cxf.apache.org/log")
+public class LogRecord {
+
+    private Date eventTimestamp = new Date();
+    private LogLevel level = LogLevel.INFO;
+    private String message = "";
+    private String loggerName = "";
+    private String threadName = "";
+    private String throwable = "";
+
+    public LogRecord() {
+        
+    }
+    
+    public LogRecord(LogRecord copy) {
+        this.eventTimestamp = copy.getEventTimestamp();
+        this.level = copy.getLevel();
+        this.message = copy.getMessage();
+        this.loggerName = copy.getLoggerName();
+        this.threadName = copy.getThreadName();
+        this.throwable = copy.getThrowable();
+    }
+    
+    /**
+     * Creates this object from JUL LogRecord. Most attributes are copied, others are converted as follows:
+     * raw {@link java.util.logging.LogRecord#getMessage() message} is formatted with
+     * {@link java.util.logging.LogRecord#getParameters() parameters} using {@link MessageFormat}, attached
+     * {@link java.util.logging.LogRecord#getThrown() throwable} has full stack trace dumped, and log levels
+     * are mapped as specified in {@link LogRecord}.
+     * 
+     * @param julRecord log record to convert.
+     * @return conversion result.
+     */
+    public static LogRecord fromJUL(java.util.logging.LogRecord julRecord) {
+        Validate.notNull(julRecord, "julRecord is null");
+        LogRecord record = new LogRecord();
+        record.setEventTimestamp(new Date(julRecord.getMillis()));
+        record.setLevel(LogLevel.fromJUL(julRecord.getLevel()));
+        record.setLoggerName(julRecord.getLoggerName());
+        if (julRecord.getThrown() != null) {
+            record.setThrowable(julRecord.getThrown());
+        }
+        if (julRecord.getParameters() != null) {
+            record.setMessage(MessageFormat.format(julRecord.getMessage(), julRecord.getParameters()));
+        } else {
+            record.setMessage(julRecord.getMessage());
+        }
+        record.setThreadName(Integer.toString(julRecord.getThreadID()));
+        return record;
+    }
+
+    @XmlElement(namespace = "http://cxf.apache.org/log")
+    public Date getEventTimestamp() {
+        return eventTimestamp;
+    }
+
+    public void setEventTimestamp(Date eventTimestamp) {
+        Validate.notNull(eventTimestamp, "eventTimestamp is null");
+        this.eventTimestamp = eventTimestamp;
+    }
+
+    @XmlElement(namespace = "http://cxf.apache.org/log")
+    public LogLevel getLevel() {
+        return level;
+    }
+
+    public void setLevel(LogLevel level) {
+        Validate.notNull(level, "level is null");
+        this.level = level;
+    }
+
+    /**
+     * Formatted message with parameters filled in.
+     */
+    @XmlElement(namespace = "http://cxf.apache.org/log")
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String renderedMessage) {
+        Validate.notNull(level, "message is null");
+        this.message = renderedMessage;
+    }
+
+    @XmlElement(namespace = "http://cxf.apache.org/log")
+    public String getLoggerName() {
+        return loggerName;
+    }
+
+    public void setLoggerName(String loggerName) {
+        Validate.notNull(level, "loggerName is null");
+        this.loggerName = loggerName;
+    }
+
+    @XmlElement(namespace = "http://cxf.apache.org/log")
+    public String getThreadName() {
+        return threadName;
+    }
+
+    public void setThreadName(String threadName) {
+        Validate.notNull(level, "threadName is null");
+        this.threadName = threadName;
+    }
+
+    /**
+     * Full stack trace of {@link Throwable} associated with log record.
+     */
+    @XmlElement(namespace = "http://cxf.apache.org/log")
+    public String getThrowable() {
+        return throwable;
+    }
+
+    public void setThrowable(String throwable) {
+        Validate.notNull(throwable, "throwable is null");
+        this.throwable = throwable;
+    }
+
+    public void setThrowable(Throwable thr) {
+        Validate.notNull(thr, "throwable is null");
+        StringWriter sw = new StringWriter();
+        thr.printStackTrace(new PrintWriter(sw));
+        this.throwable = sw.getBuffer().toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return EqualsBuilder.reflectionEquals(obj, this);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+    }
+    
+    
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecord.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.commons.lang.Validate;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+/**
+ * List of {@link LogRecord}s. Necessary wrapper for {@link List} used in JAXB context.
+ */
+@XmlRootElement(namespace = "http://cxf.apache.org/log")
+public class LogRecords {
+
+    private List<LogRecord> logRecords = new ArrayList<LogRecord>();
+
+    @XmlElement(name = "logRecord", namespace = "http://cxf.apache.org/log")
+    public List<LogRecord> getLogRecords() {
+        return logRecords;
+    }
+
+    public void setLogRecords(List<LogRecord> logRecords) {
+        Validate.notNull(logRecords, "logRecords is null");
+        this.logRecords = logRecords;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return EqualsBuilder.reflectionEquals(obj, this);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/LogRecords.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging;
+
+import java.util.List;
+
+/**
+ * Can be used by pull-style loggers to offload/save the records to some external storage 
+ *
+ */
+public interface ReadWriteLogStorage extends ReadableLogStorage {
+
+    /**
+     * Save the records
+     * @param records log records to save
+     */
+    void save(List<LogRecord> records);
+    
+    /**
+     * Clear the storage
+     */
+    void clear();
+    
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadWriteLogStorage.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging;
+
+import java.util.List;
+
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+
+/**
+ * Can be used by pull-style loggers to read the records from some external storage 
+ *
+ */
+public interface ReadableLogStorage {
+
+    
+    /**
+     * Read the records and load them into a provided list
+     * @param list the list saved records should be added to
+     * @param condition the condition loaded records must meet, can be null 
+     * @param loadFrom the initial index of the storage to have records loaded from
+     * @param int maxNumberOfRecords the max number of records to load from the storage
+     */
+    void load(List<LogRecord> list, 
+              SearchCondition<LogRecord> condition,
+              int loadFrom, 
+              int maxNumberOfRecords);
+    
+    
+    /**
+     * Get the size of storage (in records)
+     * @param the size, -1 if not known, for ex, when reading from an open file containing log entries
+     */
+    int getSize();
+    
+    
+    /**
+     * Close the storage
+     */
+    void close();
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 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=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,171 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
+
+import org.apache.commons.lang.Validate;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.management.web.logging.LogLevel;
+
+
+public abstract class AbstractAtomBean {
+
+    private List<LoggerLevel> loggers = new ArrayList<LoggerLevel>();
+    private boolean initialized;
+
+    /**
+     * Creates unconfigured and uninitialized bean. To configure setters must be used, then {@link #init()}
+     * must be called.
+     */
+    public AbstractAtomBean() {
+        initSingleLogger();
+    }
+
+    private void initSingleLogger() {
+        loggers = new ArrayList<LoggerLevel>();
+        loggers.add(new LoggerLevel("", "INFO"));
+    }
+
+
+    /**
+     * Set one or more loggers and levels descriptor. <br>
+     * Parsed input syntax is:
+     * 
+     * <pre>
+     * loggers   := &lt;logger&gt;(&lt;separator&gt;&lt;logger&gt;)*
+     * logger    := &lt;name&gt;[&quot;:&quot;&lt;level&gt;]
+     * separator := &quot;,&quot; | &quot; &quot; | &quot;\n&quot;
+     * </pre>
+     * 
+     * Examples:
+     * <p>
+     * Two loggers and two levels: <br>
+     * <tt>org.apache.cxf:INFO, org.apache.cxf.jaxrs:DEBUG</tt>
+     * <p>
+     * Three loggers, first with default "INFO" level: <br>
+     * <tt>org.apache.cxf, org.apache.cxf.jaxrs:DEBUG, namedLogger:ERROR</tt><br>
+     * <p>
+     * One logger with default "INFO" level: <br>
+     * <tt>org.apache.cxf</tt><br>
+     */
+    public void setLoggers(String loggers) {
+        checkInit();
+        Validate.notNull(loggers, "loggers is null");
+        parseLoggers(loggers);
+    }
+
+    /**
+     * Name of logger to associate with ATOM push handler; empty string for root logger.
+     */
+    public void setLogger(String logger) {
+        checkInit();
+        Validate.notNull(logger, "logger is null");
+        if (loggers.size() != 1) {
+            initSingleLogger();
+        }
+        loggers.get(0).setLogger(logger);
+    }
+
+    /**
+     * Name of level that logger will use publishing log events to ATOM push handler; empty string for default
+     * "INFO" level.
+     */
+    public void setLevel(String level) {
+        checkInit();
+        Validate.notNull(level, "level is null");
+        if (loggers.size() != 1) {
+            initSingleLogger();
+        }
+        loggers.get(0).setLevel(level);
+    }
+
+
+    /**
+     * Initializes bean; creates ATOM handler based on current properties state, and attaches handler to
+     * logger(s).
+     */
+    public void init() {
+        checkInit();
+        initialized = true;
+        Handler h = createHandler();
+        for (int i = 0; i < loggers.size(); i++) {
+            Logger l = LogUtils.getL7dLogger(AbstractAtomBean.class, null, loggers.get(i).getLogger());
+            l.addHandler(h);
+            l.setLevel(LogLevel.toJUL(LogLevel.valueOf(loggers.get(i).getLevel())));
+        }
+    }
+
+    protected abstract Handler createHandler();
+    
+    protected void checkInit() {
+        if (initialized) {
+            throw new IllegalStateException("Bean is already initialized");
+        }
+    }
+
+    private void parseLoggers(String param) {
+        loggers = new ArrayList<LoggerLevel>();
+        StringTokenizer st1 = new StringTokenizer(param, ", \t\n\r\f");
+        while (st1.hasMoreTokens()) {
+            String tok = st1.nextToken();
+            int idx = tok.indexOf(":");
+            if (idx != -1) {
+                loggers.add(new LoggerLevel(tok.substring(0, idx), tok.substring(idx + 1, tok.length())));
+            } else {
+                loggers.add(new LoggerLevel(tok, "INFO"));
+            }
+        }
+    }
+
+    protected List<LoggerLevel> getLoggers() {
+        return loggers;
+    }
+
+    protected static class LoggerLevel {
+        private String logger;
+        private String level;
+
+        public LoggerLevel(String logger, String level) {
+            this.logger = logger;
+            this.level = level;
+        }
+
+        public String getLogger() {
+            return logger;
+        }
+
+        public void setLogger(String logger) {
+            this.logger = logger;
+        }
+
+        public String getLevel() {
+            return level;
+        }
+
+        public void setLevel(String level) {
+            this.level = level;
+        }
+
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AbstractAtomBean.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.util.logging.Handler;
+
+import org.apache.cxf.management.web.logging.LogRecord;
+
+
+public final class AtomPullHandler extends Handler {
+
+    private AtomPullServer engine;
+    /**
+     * Creates handler using (package private).
+     * 
+     * @param engine configured engine.
+     */
+    AtomPullHandler(AtomPullServer engine) {
+        this.engine = engine;
+    }
+
+    @Override
+    public void publish(java.util.logging.LogRecord record) {
+        if (LoggingThread.isSilent()) {
+            return;
+        }
+        LoggingThread.markSilent(true);
+        try {
+            LogRecord rec = LogRecord.fromJUL(record);
+            engine.publish(rec);
+        } finally {
+            LoggingThread.markSilent(false);
+        }
+    }
+
+    @Override
+    public synchronized void close() throws SecurityException {
+        engine.close();
+    }
+
+    @Override
+    public synchronized void flush() {
+        // no-op
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullHandler.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 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=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,328 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.WeakHashMap;
+import java.util.logging.Handler;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+
+import org.apache.abdera.model.Feed;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.search.ConditionType;
+import org.apache.cxf.jaxrs.ext.search.OrSearchCondition;
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+import org.apache.cxf.management.web.logging.LogLevel;
+import org.apache.cxf.management.web.logging.LogRecord;
+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")
+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;
+    private int pageSize = 20;
+    private int maxInMemorySize = 500;
+    private boolean useArchivedFeeds;
+    private int recordsSize;
+    private volatile boolean alreadyClosed;
+    private SearchCondition<LogRecord> condition;
+        
+    @Context
+    private MessageContext context;
+    
+    @Override
+    public void init() {
+        // the storage might've been used to save previous records or it might
+        // point to a file log entries are added to
+        if (storage != null) {
+            //-1 can be returned by read-only storage if it does not know in advance
+            // a number of records it may contain 
+            recordsSize = storage.getSize();
+        }
+        
+        if (storage == null || storage instanceof ReadWriteLogStorage) {
+            super.init();
+        } else {
+            // super.init() results in the additional Handler being created and publish()
+            // method being called as a result. If the storage is read-only it is assumed it points to
+            // the external source of log records thus no need to get the publish events here
+            
+            // instead we create a SearchCondition the external storage will check against when
+            // loading the matching records on request
+            
+            List<SearchCondition<LogRecord>> list = new LinkedList<SearchCondition<LogRecord>>();
+            for (LoggerLevel l : super.getLoggers()) {
+                LogRecord r = new LogRecord();
+                r.setLoggerName(l.getLogger());
+                r.setLevel(LogLevel.valueOf(l.getLevel()));
+                list.add(new SearchConditionImpl(r));
+            }
+            condition = new OrSearchCondition<LogRecord>(list);
+        }
+        
+    }
+    
+    @GET
+    @Produces("application/atom+xml")
+    public Feed getRecords() {
+        int page = getPageValue();
+        
+        // lets check if the Atom reader is asking for a set of records which has already been 
+        // converted to Feed
+        
+        synchronized (feeds) {
+            Feed f = feeds.get(page);
+            if (f != null) {
+                return f;
+            }
+        }
+        
+        Feed feed = null;
+        synchronized (records) {
+            List<LogRecord> list = getSubList(page);
+            feed = (Feed)converter.convert(list).get(0);
+            setFeedPageProperties(feed, page);
+        }
+        // if at the moment we've converted n < pageSize number of records only and
+        // persist a Feed keyed by a page then another reader requesting the same page 
+        // may miss latest records which might've been added since the original request
+        if (feed.getEntries().size() == pageSize) {
+            synchronized (feeds) {
+                feeds.put(page, feed);
+            }
+        }
+        return feed;
+    }
+
+    @GET
+    @Path("records")
+    @Produces("text/plain")
+    public int getNumberOfAvaiableRecords() {
+        return recordsSize;
+    }
+    
+    
+    protected List<LogRecord> getSubList(int page) {
+        
+        if (recordsSize == -1) {
+            // let the external storage load the records it knows about
+            List<LogRecord> list = new LinkedList<LogRecord>();
+            storage.load(list, condition, page == 1 ? 0 : (page - 1) * pageSize, pageSize);
+            return list;
+        }
+        
+        if (recordsSize == 0) {
+            return records;
+        }
+        
+        int fromIndex = 0;
+        int toIndex = 0;
+        // see http://tools.ietf.org/html/draft-nottingham-atompub-feed-history-07
+        if (!useArchivedFeeds) {
+            fromIndex = page == 1 ? 0 : (page - 1) * pageSize;
+            if (fromIndex > recordsSize) {
+                // this should not happen really
+                page = 1;
+                fromIndex = 0;
+            }
+            toIndex = page == 1 ? pageSize : fromIndex + pageSize;
+            if (toIndex > recordsSize) {
+                toIndex = recordsSize;
+            }
+        } else {
+            fromIndex = recordsSize - pageSize * page;
+            if (fromIndex < 0) {
+                fromIndex = 0;
+            }
+            toIndex = pageSize < recordsSize ? recordsSize : pageSize;
+        }
+
+        // if we have the storage then try to load from it
+        if (storage != null) {
+            if (fromIndex < storage.getSize()) {
+                int storageSize = storage.getSize();
+                int maxQuantityToLoad = toIndex > storageSize ? toIndex - storageSize : toIndex - fromIndex;
+                List<LogRecord> list = new LinkedList<LogRecord>();
+                storage.load(list, condition, fromIndex, maxQuantityToLoad);
+                int totalQuantity = toIndex - fromIndex;
+                if (list.size() < totalQuantity) {
+                    int remaining = totalQuantity - list.size();
+                    if (remaining > records.size()) {
+                        remaining = records.size();
+                    }
+                    list.addAll(records.subList(0, remaining));
+                }
+                return list;
+            } else {
+                fromIndex -= storage.getSize();
+                toIndex -= storage.getSize();
+            }
+        } 
+        return records.subList(fromIndex, toIndex);
+        
+    }
+    
+    protected void setFeedPageProperties(Feed feed, int page) {
+        String self = context.getUriInfo().getRequestUri().toString();
+        feed.addLink(self, "self");
+        
+        String uri = context.getUriInfo().getAbsolutePath().toString();
+        
+        if (!useArchivedFeeds) {
+            if (recordsSize != -1) {
+                if (page > 2) {
+                    feed.addLink(uri, "first");
+                }
+                
+                if (page * pageSize < recordsSize) {
+                    feed.addLink(uri + "?page=" + (page + 1), "next");
+                }
+                
+                if (page * (pageSize + 1) < recordsSize) {
+                    feed.addLink(uri + "?page=" + (recordsSize / pageSize + 1), "last");
+                }
+            } else if (feed.getEntries().size() == pageSize) {
+                feed.addLink(uri + "?page=" + (page + 1), "next");
+            }
+            if (page > 1) {
+                uri = page > 2 ? uri + "?page=" + (page - 1) : uri;
+                feed.addLink(uri, "previous");
+            }
+        } else {
+            feed.addLink(uri, "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
+            // it is not current
+        }
+        
+    }
+    
+        
+    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) {
+            System.err.println("AtomPullServer has been closed, the following log record can not be saved : "
+                               + record.toString());
+            return;
+        }
+        synchronized (records) {
+            if (records.size() == maxInMemorySize) {
+                if (storage instanceof ReadWriteLogStorage) {
+                    ((ReadWriteLogStorage)storage).save(records);
+                    records.clear();
+                } else {
+                    LogRecord oldRecord = records.remove(0);
+                    System.err.println("The oldest log record is removed : " + oldRecord.toString());
+                }
+            } 
+            records.add(record);
+            ++recordsSize;
+        }
+    }
+    
+    public void setPageSize(int size) {
+        pageSize = size;
+    }
+
+    public void setMaxInMemorySize(int maxInMemorySize) {
+        this.maxInMemorySize = maxInMemorySize;
+    }
+
+    public void setStorage(ReadableLogStorage storage) {
+        this.storage = storage;
+    }
+    
+    public void close() {
+        if (alreadyClosed) {
+            return;
+        }
+        alreadyClosed = true;
+        if (storage instanceof ReadWriteLogStorage) {
+            ((ReadWriteLogStorage)storage).save(records);
+        }
+    }
+    
+    private static class SearchConditionImpl implements SearchCondition<LogRecord> {
+        private LogRecord template;
+        
+        public SearchConditionImpl(LogRecord l) {
+            this.template = l;
+        }
+
+        public boolean isMet(LogRecord pojo) {
+            
+            return (template.getLevel() == LogLevel.ALL
+                   || pojo.getLevel().compareTo(template.getLevel()) <= 0)
+                   && template.getLoggerName().equals(pojo.getLoggerName());
+        }
+
+        public LogRecord getCondition() {
+            return new LogRecord(template);
+        }
+
+        public ConditionType getConditionType() {
+            return ConditionType.CUSTOM;
+        }
+
+        public List<SearchCondition<LogRecord>> getConditions() {
+            return null;
+        }
+
+        public List<LogRecord> findAll(List<LogRecord> pojos) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+        
+        
+    }
+    
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPullServer.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,194 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.util.logging.Handler;
+
+import org.apache.commons.lang.Validate;
+import org.apache.cxf.management.web.logging.atom.converter.Converter;
+import org.apache.cxf.management.web.logging.atom.deliverer.Deliverer;
+
+/**
+ * Bean used to configure {@link AtomPushHandler JUL handler} with Spring instead of properties file. See
+ * {@link AtomPushHandler} class for detailed description of parameters. Next to configuration of handler,
+ * Spring bean offers simple configuration of associated loggers that share ATOM push-style handler.
+ * <p>
+ * General rules:
+ * <ul>
+ * <li>When {@link #setDeliverer(Deliverer) deliverer} property is not set explicitly, URL must be set to
+ * create default deliverer.</li>
+ * <li>When {@link #setConverter(Converter) converter} property is not set explicitly, default converter is
+ * created.</li>
+ * <li>When {@link #setLoggers(String) loggers} property is used, it overrides pair of
+ * {@link #setLogger(String) logger} and {@link #setLevel(String) level} properties; and vice versa.</li>
+ * <li>When logger is not set, handler is attached to root logger (named ""); when level is not set for
+ * logger, default "INFO" level is used.</li>
+ * <li>When {@link #setBatchSize(String) batchSize} property is not set or set to wrong value, default batch
+ * size of "1" is used.</li>
+ * <li>When deliverer property is NOT set, use of "retryXxx" properties causes creation of retrying default
+ * deliverer.</li>
+ * </ul>
+ * Examples:
+ * <p>
+ * ATOM push handler with registered with root logger for all levels or log events, pushing one feed per event
+ * to specified URL, using default delivery and conversion methods:
+ * 
+ * <pre>
+ *   &lt;bean class=&quot;org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean&quot; 
+ *     init-method=&quot;init&quot;&gt;
+ *       &lt;property name=&quot;url&quot; value=&quot;http://localhost:9080/feed&quot;/&gt;
+ *       &lt;property name=&quot;level&quot; value=&quot;ALL&quot; /&gt;
+ *   &lt;/bean&gt;
+ * </pre>
+ * 
+ * ATOM push handler registered with multiple loggers and listening for different levels (see
+ * {@link #setLoggers(String) loggers} property description for syntax details). Custom deliverer will take
+ * care of feeds, each of which carries batch of 10 log events:
+ * 
+ * <pre>
+ *   &lt;bean id=&quot;soapDeliverer&quot; ...
+ *   ...
+ *   &lt;bean class=&quot;org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean&quot; 
+ *     init-method=&quot;init&quot;&gt;
+ *       &lt;property name=&quot;deliverer&quot;&gt;
+ *           &lt;ref bean=&quot;soapDeliverer&quot;/&gt;
+ *       &lt;/property&gt;
+ *       &lt;property name=&quot;loggers&quot; value=&quot;
+ *           org.apache.cxf:DEBUG,
+ *           org.apache.cxf.jaxrs,
+ *           org.apache.cxf.bus:ERROR&quot; /&gt;
+ *       &lt;property name=&quot;batchSize&quot; value=&quot;10&quot; /&gt;
+ *   &lt;/bean&gt;
+ * </pre>
+ */
+public final class AtomPushBean extends AbstractAtomBean {
+
+    private AtomPushEngineConfigurator conf = new AtomPushEngineConfigurator();
+    
+    /**
+     * Creates unconfigured and uninitialized bean. To configure setters must be used, then {@link #init()}
+     * must be called.
+     */
+    public AtomPushBean() {
+    }
+
+    /**
+     * Set URL used when custom deliverer is not set (default deliverer is being created).
+     */
+    public void setUrl(String url) {
+        checkInit();
+        Validate.notNull(url, "url is null");
+        conf.setUrl(url);
+    }
+
+    /**
+     * Set initialized deliverer.
+     */
+    public void setDeliverer(Deliverer deliverer) {
+        checkInit();
+        Validate.notNull(deliverer, "deliverer is null");
+        conf.setDeliverer(deliverer);
+    }
+
+    /**
+     * Set initialized converter.
+     */
+    public void setConverter(Converter converter) {
+        checkInit();
+        Validate.notNull(converter, "converter is null");
+        conf.setConverter(converter);
+    }
+    
+    /**
+     * Size of batch; empty string for default one element batch.
+     */
+    public void setBatchSize(String batchSize) {
+        checkInit();
+        Validate.notNull(batchSize, "batchSize is null");
+        conf.setBatchSize(batchSize);
+    }
+    
+    /**
+     * Batch cleanup time in minutes
+     */
+    public void setBatchCleanupTime(String batchCleanupTime) {
+        checkInit();
+        Validate.notNull(batchCleanupTime, "batchCleanup is null");
+        conf.setBatchCleanupTime(batchCleanupTime);
+    }
+
+    /**
+     * Retry pause calculation strategy, either "linear" or "exponential".
+     */
+    public void setRetryPause(String retryPause) {
+        checkInit();
+        Validate.notNull(retryPause, "retryPause is null");
+        conf.setRetryPause(retryPause);
+    }
+
+    /**
+     * Retry pause time (in seconds).
+     */
+    public void setRetryPauseTime(String time) {
+        checkInit();
+        Validate.notNull(time, "time is null");
+        conf.setRetryPauseTime(time);
+    }
+
+    /**
+     * Retry timeout (in seconds).
+     */
+    public void setRetryTimeout(String timeout) {
+        checkInit();
+        Validate.notNull(timeout, "timeout is null");
+        conf.setRetryTimeout(timeout);
+    }
+
+    /**
+     * Conversion output type: "feed" or "entry".
+     */
+    public void setOutput(String output) {
+        checkInit();
+        Validate.notNull(output, "output is null");
+        conf.setOutput(output);
+    }
+
+    /**
+     * Multiplicity of subelement of output: "one" or "many".
+     */
+    public void setMultiplicity(String multiplicity) {
+        checkInit();
+        Validate.notNull(multiplicity, "multiplicity is null");
+        conf.setMultiplicity(multiplicity);
+    }
+
+    /**
+     * Entry data format: "content" or "extension".
+     */
+    public void setFormat(String format) {
+        checkInit();
+        Validate.notNull(format, "format is null");
+        conf.setFormat(format);
+    }
+
+    protected Handler createHandler() {
+        return new AtomPushHandler(conf.createEngine());
+    }
+
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushBean.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.abdera.model.Element;
+import org.apache.commons.lang.Validate;
+import org.apache.cxf.management.web.logging.LogRecord;
+import org.apache.cxf.management.web.logging.atom.converter.Converter;
+import org.apache.cxf.management.web.logging.atom.deliverer.Deliverer;
+
+/**
+ * Package private ATOM push-style engine. Engine enqueues log records as they are {@link #publish(LogRecord)
+ * published}. After queue size exceeds {@link #getBatchSize() batch size} processing of collection of these
+ * records (in size of batch size) is triggered.
+ * <p>
+ * Processing is done in separate thread not to block publishing interface. Processing is two step: first list
+ * of log records is transformed by {@link Converter converter} to ATOM {@link Element element} and then it is
+ * pushed out by {@link Deliverer deliverer} to client. Next to transport deliverer is indirectly responsible
+ * for marshaling ATOM element to XML.
+ * <p>
+ * Processing is done by single threaded {@link java.util.concurrent.Executor executor}; next batch of records
+ * is taken from queue only when currently processed batch finishes and queue has enough elements to proceed.
+ * <p>
+ * First failure of any delivery shuts engine down. To avoid this situation engine must have registered
+ * reliable deliverer or use wrapping
+ * {@link org.apache.cxf.jaxrs.ext.logging.atom.deliverer.RetryingDeliverer}.
+ */
+// TODO add internal diagnostics - log messages somewhere except for logger :D
+final class AtomPushEngine {
+    private List<LogRecord> queue = new ArrayList<LogRecord>();
+    private ExecutorService executor = Executors.newSingleThreadExecutor();
+    private int batchSize = 1;
+    private int batchTime;
+    private Converter converter;
+    private Deliverer deliverer;
+    private Timer timer;
+    
+    /**
+     * Put record to publishing queue. Engine accepts published records only if is in proper state - is
+     * properly configured (has deliverer and converter registered) and is not shot down; otherwise calls to
+     * publish are ignored.
+     * 
+     * @param record record to be published.
+     */
+    public synchronized void publish(LogRecord record) {
+        Validate.notNull(record, "record is null");
+        if (isValid()) {
+            if (batchSize > 1 && batchTime > 0 && timer == null) {
+                createTimerTask(batchTime * 60 * 1000);
+            }
+            queue.add(record);
+            if (queue.size() >= batchSize) {
+                publishAndReset();
+            }
+        } else {
+            handleUndeliveredRecords(Collections.singletonList(record), 
+                                     deliverer == null ? "" : deliverer.getEndpointAddress());
+        }
+    }
+    
+    protected synchronized void publishAndReset() {
+        publishBatch(queue, deliverer, converter);
+        queue = new ArrayList<LogRecord>();
+    }
+
+    /**
+     * Shuts engine down.
+     */
+    public synchronized void shutdown() {
+        cancelTimerTask();
+        if (isValid() && queue.size() > 0) {
+            publishAndReset();
+        }
+        executor.shutdown();
+    }
+
+    private boolean isValid() {
+        if (deliverer == null) {
+            // TODO report cause
+            System.err.println("deliverer is not set");
+            return false;
+        }
+        if (converter == null) {
+            System.err.println("converter is not set");
+            return false;
+        }
+        if (executor.isShutdown()) {
+            System.err.println("engine shutdown");
+            return false;
+        }
+        return true;
+    }
+
+    private void publishBatch(final List<LogRecord> batch,
+                              final Deliverer d,
+                              final Converter c) {
+        executor.execute(new Runnable() {
+            public void run() {
+                try {
+                    LoggingThread.markSilent(true);
+                    List<? extends Element> elements = c.convert(batch);
+                    for (int i = 0; i < elements.size(); i++) {
+                        Element element = elements.get(i);
+                        if (!d.deliver(element)) {
+                            System.err.println("Delivery to " + d.getEndpointAddress() 
+                                + " failed, shutting engine down");
+                            List<LogRecord> undelivered = null;
+                            if (i == 0) {
+                                undelivered = batch;
+                            } else {
+                                int index = (batch.size() / elements.size()) * i;
+                                // should not happen but just in case :-)
+                                if (index < batch.size()) {
+                                    undelivered = batch.subList(index, batch.size());
+                                }
+                            }
+                            handleUndeliveredRecords(undelivered, d.getEndpointAddress());
+                            shutdown();
+                            break;
+                        }
+                    }
+                } catch (InterruptedException e) {
+                    // no action
+                } finally {
+                    LoggingThread.markSilent(false);
+                }
+            }
+        });
+    }
+
+    protected void handleUndeliveredRecords(List<LogRecord> records, String address) {
+        // TODO : save them to some transient storage perhaps ?
+        System.err.println("The following records have been undelivered to " + address + " : ");
+        for (LogRecord r : records) {
+            System.err.println(r.toString());
+        }
+    }
+    
+    public int getBatchSize() {
+        return batchSize;
+    }
+
+    public void setBatchSize(int batchSize) {
+        Validate.isTrue(batchSize > 0, "batch size is not greater than zero");
+        this.batchSize = batchSize;
+    }
+    
+    public void setBatchTime(int batchTime) {
+        this.batchTime = batchTime;
+    }
+
+    /**
+     * Creates a timer task which will periodically flush the batch queue
+     * thus ensuring log records won't become too 'stale'. 
+     * Ex, if we have a batch size 10 and only WARN records need to be delivered
+     * then without the periodic cleanup the consumers may not get prompt notifications
+     *  
+     * @param timeout
+     */
+    protected void createTimerTask(long timeout) {
+        timer = new Timer();
+        timer.schedule(new TimerTask() {
+            public void run() {
+                publishAndReset();
+            }
+        }, timeout);
+    }
+    
+    protected void cancelTimerTask() {
+        if (timer != null) {
+            timer.cancel();
+            timer = null;
+        }
+    }
+    
+    public synchronized Converter getConverter() {
+        return converter;
+    }
+
+    public synchronized void setConverter(Converter converter) {
+        Validate.notNull(converter, "converter is null");
+        this.converter = converter;
+    }
+
+    public synchronized Deliverer getDeliverer() {
+        return deliverer;
+    }
+
+    public synchronized void setDeliverer(Deliverer deliverer) {
+        Validate.notNull(deliverer, "deliverer is null");
+        this.deliverer = deliverer;
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngine.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,213 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.cxf.management.web.logging.atom.converter.Converter;
+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;
+import org.apache.cxf.management.web.logging.atom.deliverer.Deliverer;
+import org.apache.cxf.management.web.logging.atom.deliverer.RetryingDeliverer;
+import org.apache.cxf.management.web.logging.atom.deliverer.WebClientDeliverer;
+
+/**
+ * Package private interpreter of incomplete input of engine configuration. Used commonly by
+ * {@link AtomPushHandler properties file} and {@link AtomPushBean spring} configuration schemes.
+ */
+// TODO extract 'general rules' of interpretation in handler and bean and put here
+final class AtomPushEngineConfigurator {
+
+    private Deliverer deliverer;
+    private Converter converter;
+    private String delivererClass;
+    private String converterClass;
+    private String batchSize;
+    private String batchCleanupTime;
+    private String delivererUrl;
+    private String retryTimeout;
+    private String retryPause;
+    private String retryPauseTime;
+    private String output;
+    private String multiplicity;
+    private String format;
+
+    public void setUrl(String url) {
+        this.delivererUrl = url;
+    }
+
+    public void setRetryTimeout(String retryTimeout) {
+        this.retryTimeout = retryTimeout;
+    }
+
+    public void setRetryPause(String retryPause) {
+        this.retryPause = retryPause;
+    }
+
+    public void setRetryPauseTime(String retryPauseTime) {
+        this.retryPauseTime = retryPauseTime;
+    }
+
+    public void setBatchCleanupTime(String cleanupTime) {
+        this.batchCleanupTime = cleanupTime;
+    }
+    
+    public void setBatchSize(String batchSize) {
+        this.batchSize = batchSize;
+    }
+
+    public void setDeliverer(Deliverer deliverer) {
+        this.deliverer = deliverer;
+    }
+
+    public void setConverter(Converter converter) {
+        this.converter = converter;
+    }
+
+    public void setDelivererClass(String delivererClass) {
+        this.delivererClass = delivererClass;
+    }
+
+    public void setConverterClass(String converterClass) {
+        this.converterClass = converterClass;
+    }
+
+    public void setOutput(String output) {
+        this.output = output;
+    }
+
+    public void setMultiplicity(String multiplicity) {
+        this.multiplicity = multiplicity;
+    }
+
+    public void setFormat(String format) {
+        this.format = format;
+    }
+
+    public AtomPushEngine createEngine() {
+        Deliverer d = deliverer;
+        Converter c = converter;
+        int batch = parseInt(batchSize, 1, 1);
+        int batchTime = parseInt(batchCleanupTime, 0);
+        if (d == null) {
+            if (delivererUrl != null) {
+                if (delivererClass != null) {
+                    d = createDeliverer(delivererClass, delivererUrl);
+                } else {
+                    d = new WebClientDeliverer(delivererUrl);
+                }
+            } else {
+                throw new IllegalStateException("Either url, deliverer or "
+                                                + "deliverer class with url must be setup");
+            }
+        }
+        if (c == null) {
+            if (converterClass != null) {
+                c = createConverter(converterClass);
+            } else {
+                Output out = parseEnum(output, Output.FEED, Output.class);
+                Multiplicity defaultMul = out == Output.FEED ? Multiplicity.MANY
+                    : batch > 1 ? Multiplicity.MANY : Multiplicity.ONE; 
+                Multiplicity mul = parseEnum(multiplicity, defaultMul, Multiplicity.class);
+                Format form = parseEnum(format, Format.CONTENT, Format.class);
+                if (out == Output.FEED) {
+                    c = new StandardConverter(out, mul, form);
+                } else {
+                    c = new StandardConverter(out, mul, form);
+                }
+                if (retryPause != null) {
+                    int timeout = parseInt(retryTimeout, 0, 0);
+                    int pause = parseInt(retryPauseTime, 1, 30);
+                    boolean linear = !retryPause.equalsIgnoreCase("exponential");
+                    d = new RetryingDeliverer(d, timeout, pause, linear);
+                }
+            }
+        }
+        AtomPushEngine engine = new AtomPushEngine();
+        engine.setDeliverer(d);
+        engine.setConverter(c);
+        engine.setBatchSize(batch);
+        engine.setBatchTime(batchTime);
+        return engine;
+    }
+
+    private Deliverer createDeliverer(String clazz, String url) {
+        try {
+            Constructor<Deliverer> ctor = loadClass(clazz, Deliverer.class).getConstructor(String.class);
+            return ctor.newInstance(url);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    private Converter createConverter(String clazz) {
+        try {
+            Constructor<Converter> ctor = loadClass(clazz, Converter.class).getConstructor();
+            return ctor.newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> Class<T> loadClass(String clazz, Class<T> ifaceClass) throws ClassNotFoundException {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        try {
+            return (Class<T>)cl.loadClass(clazz);
+        } catch (ClassNotFoundException e) {
+            try {
+                // clazz could be shorted (stripped package name) retry for interface location
+                String pkg = ifaceClass.getPackage().getName();
+                String clazz2 = pkg + "." + clazz;
+                return (Class<T>)cl.loadClass(clazz2);
+            } catch (Exception e1) {
+                throw new ClassNotFoundException(e.getMessage() + " or " + e1.getMessage());
+            }
+        }
+    }
+
+    private int parseInt(String property, int defaultValue) {
+        try {
+            return Integer.parseInt(property);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+    private int parseInt(String property, int lessThan, int defaultValue) {
+        int ret = parseInt(property, defaultValue);
+        if (ret < lessThan) {
+            ret = defaultValue;
+        }
+        return ret;
+    }
+
+    private <T extends Enum<T>> T parseEnum(String value, T defaultValue, Class<T> enumClass) {
+        if (value == null | "".equals(value)) {
+            return defaultValue;
+        }
+        try {
+            return Enum.valueOf(enumClass, value.toUpperCase());
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushEngineConfigurator.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java?rev=902834&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java Mon Jan 25 14:51:51 2010
@@ -0,0 +1,185 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.management.web.logging.atom;
+
+import java.util.logging.Handler;
+import java.util.logging.LogManager;
+
+import org.apache.cxf.management.web.logging.LogRecord;
+import org.apache.cxf.management.web.logging.atom.converter.Converter;
+import org.apache.cxf.management.web.logging.atom.deliverer.Deliverer;
+
+/**
+ * Handler pushing log records in batches as Atom Feeds or Entries to registered client. Handler
+ * responsibility is to adapt to JUL framework while most of job is delegated to {@link AtomPushEngine}.
+ * <p>
+ * For simple configuration using properties file (one global root-level handler of this class) following
+ * properties prefixed with full name of this class can be used:
+ * <ul>
+ * <li><b>url</b> - URL where feeds will be pushed (mandatory parameter)</li>
+ * <li><b>batchSize</b> - integer number specifying minimal number of published log records that trigger
+ * processing and pushing ATOM document. If parameter is not set, is not greater than zero or is not a number,
+ * batch size is set to 1.</li>
+ * </ul>
+ * Conversion of log records into ATOM Elements can be tuned up using following parameters. Note that not all
+ * combinations are meaningful, see {@link org.apache.cxf.jaxrs.ext.logging.atom.converter.StandardConverter}
+ * for details:
+ * <ul>
+ * <li><b>output</b> - ATOM Element type pushed out, either "feed" or "entry"; when not specified or invalid
+ * value provided "feed" is used.</li>
+ * <li><b>multiplicity</b> - multiplicity of subelement(entries in feed for output=="feed" or log records in
+ * entry for output=="entry"), either "one" or "many"; when not specified or invalid value provided "one" is
+ * used.</li>
+ * <li><b>format</b> - method of embedding data in entry, either "content" or "extension"; when not specified
+ * or invalid value provided "content" is used.</li>
+ * </ul>
+ * By default delivery is served by WebClientDeliverer which does not support reliability of transport.
+ * Availability of any of this parameters enables retrying of default delivery. Detailed explanation of these
+ * parameter, see {@link org.apache.cxf.jaxrs.ext.logging.atom.deliverer.RetryingDeliverer} class description.
+ * <ul>
+ * <li><b>retry.pause</b> - pausing strategy of delivery retries, either <b>linear</b> or <b>exponential</b>
+ * value (mandatory parameter). If mispelled linear is used.</li>
+ * <li><b>retry.pause.time</b> - pause time (in seconds) between retries. If parameter is not set, pause is
+ * set to 30 seconds.</li>
+ * <li><b>retry.timeout</b> - maximum time (in seconds) retrying will be continued. If not set timeout is not
+ * set (infinite loop of retries).</li>
+ * </ul>
+ * Ultimate control on conversion and delivery is obtained specifying own implementation classes:
+ * <ul>
+ * <li><b>converter</b> - name of class implementing {@link Converter} class replacing default conversion and
+ * its specific parameters ("output", "multiplicity" and "format") are ignored. For classes located in same
+ * package as Converter interface only class name can be given e.g. instead of
+ * "org.apache.cxf.jaxrs.ext.logging.atom.converter.FooBarConverter" one can specify "FooBarConverter".</li>
+ * <li><b>deliverer</b> - name of class implementing {@link Deliverer} class replacing default delivery and
+ * its specific parameters ("retry.Xxx") are ignored. For classes located in same package as Deliverer
+ * interface only class name can be given e.g. instead of
+ * "org.apache.cxf.jaxrs.ext.logging.atom.deliverer.WebClientDeliverer" one can specify 
+ * "WebClientDeliverer".</li>
+ * </ul>
+ * Example:
+ * 
+ * <pre>
+ * handlers = org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler, java.util.logging.ConsoleHandler
+ * .level = INFO
+ * 
+ * # deliver to given URL triggering after each batch of 10 log records
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.url = http://localhost:9080
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.batchSize = 10
+ * 
+ * # enable retrying delivery every 10 seconds for 5 minutes
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.retry.pause = linear
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.retry.pause.time = 10
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.retry.timeout = 300
+ * 
+ * # output for AtomPub: push entries not feeds, each entry with one log record as &quot;atom:extension&quot; 
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.output = entry
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.multiplicity = one
+ * org.apache.cxf.jaxrs.ext.logging.atom.AtomPushHandler.format = extension
+ * ...
+ * </pre>
+ */
+public final class AtomPushHandler extends Handler {
+
+    private AtomPushEngine engine;
+    private boolean lazyConfig;
+
+    /**
+     * Creates handler with configuration taken from properties file.
+     */
+    public AtomPushHandler() {
+        // deferred configuration: configure() called from here would use utilities that attempt to log
+        // and create this handler instance in recursion; configure() will be called on first publish()
+        lazyConfig = true;
+    }
+
+    /**
+     * Creates handler with custom parameters.
+     * 
+     * @param batchSize batch size, see {@link AtomPushEngine#getBatchSize()}
+     * @param converter converter transforming logs into ATOM elements
+     * @param deliverer deliverer pushing ATOM elements to client
+     */
+    public AtomPushHandler(int batchSize, Converter converter, Deliverer deliverer) {
+        engine = new AtomPushEngine();
+        engine.setBatchSize(batchSize);
+        engine.setConverter(converter);
+        engine.setDeliverer(deliverer);
+    }
+
+    /**
+     * Creates handler using (package private).
+     * 
+     * @param engine configured engine.
+     */
+    AtomPushHandler(AtomPushEngine engine) {
+        this.engine = engine;
+    }
+
+    @Override
+    public synchronized void publish(java.util.logging.LogRecord record) {
+        if (LoggingThread.isSilent()) {
+            return;
+        }
+        LoggingThread.markSilent(true);
+        try {
+            if (lazyConfig) {
+                lazyConfig = false;
+                configure();
+            }
+            LogRecord rec = LogRecord.fromJUL(record);
+            engine.publish(rec);
+        } finally {
+            LoggingThread.markSilent(false);
+        }
+    }
+
+    @Override
+    public synchronized void close() throws SecurityException {
+        engine.shutdown();
+    }
+
+    @Override
+    public synchronized void flush() {
+        // no-op
+    }
+
+    /**
+     * Configuration from properties. Aligned to JUL strategy - properties file is only for simple
+     * configuration: it allows configure one root handler with its parameters. What is even more dummy, JUL
+     * does not allow to iterate over configuration properties to make interpretation automated (e.g. using
+     * commons-beanutils)
+     */
+    private void configure() {
+        LogManager manager = LogManager.getLogManager();
+        String cname = getClass().getName();
+        AtomPushEngineConfigurator conf = new AtomPushEngineConfigurator();
+        conf.setUrl(manager.getProperty(cname + ".url"));
+        conf.setDelivererClass(manager.getProperty(cname + ".deliverer"));
+        conf.setConverterClass(manager.getProperty(cname + ".converter"));
+        conf.setBatchSize(manager.getProperty(cname + ".batchSize"));
+        conf.setBatchCleanupTime(manager.getProperty(cname + ".batchCleanupTime"));
+        conf.setRetryPause(manager.getProperty(cname + ".retry.pause"));
+        conf.setRetryPauseTime(manager.getProperty(cname + ".retry.pause.time"));
+        conf.setRetryTimeout(manager.getProperty(cname + ".retry.timeout"));
+        conf.setOutput(manager.getProperty(cname + ".output"));
+        conf.setMultiplicity(manager.getProperty(cname + ".multiplicity"));
+        conf.setFormat(manager.getProperty(cname + ".format"));
+        engine = conf.createEngine();
+    }
+}

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/atom/AtomPushHandler.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date



Mime
View raw message