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/01/25 15:51:52 UTC
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/...
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 := <logger>(<separator><logger>)*
+ * logger := <name>[":"<level>]
+ * separator := "," | " " | "\n"
+ * </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>
+ * <bean class="org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean"
+ * init-method="init">
+ * <property name="url" value="http://localhost:9080/feed"/>
+ * <property name="level" value="ALL" />
+ * </bean>
+ * </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>
+ * <bean id="soapDeliverer" ...
+ * ...
+ * <bean class="org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean"
+ * init-method="init">
+ * <property name="deliverer">
+ * <ref bean="soapDeliverer"/>
+ * </property>
+ * <property name="loggers" value="
+ * org.apache.cxf:DEBUG,
+ * org.apache.cxf.jaxrs,
+ * org.apache.cxf.bus:ERROR" />
+ * <property name="batchSize" value="10" />
+ * </bean>
+ * </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 "atom:extension"
+ * 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