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 2011/03/04 14:48:18 UTC
svn commit: r1077946 - in /cxf/trunk/rt/management-web/src:
main/java/org/apache/cxf/management/web/logging/ test/java/org/
test/java/org/apache/ test/java/org/apache/cxf/
test/java/org/apache/cxf/management/
test/java/org/apache/cxf/management/web/ te...
Author: sergeyb
Date: Fri Mar 4 13:48:18 2011
New Revision: 1077946
URL: http://svn.apache.org/viewvc?rev=1077946&view=rev
Log:
[CXF-3372] Adding a helper for reading arbitrary log files with an optional scanning
Added:
cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorage.java (with props)
cxf/trunk/rt/management-web/src/test/java/org/
cxf/trunk/rt/management-web/src/test/java/org/apache/
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java (with props)
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log
cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log.1
Modified:
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/ReadOnlyFileStorage.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorage.java?rev=1077946&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorage.java (added)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorage.java Fri Mar 4 13:48:18 2011
@@ -0,0 +1,477 @@
+/**
+ * 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.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+
+/**
+ * Facilitates reading the log entries from the existing log files
+ */
+public class ReadOnlyFileStorage implements ReadableLogStorage {
+
+ public static final String LEVEL_PROPERTY = "level";
+ public static final String DATE_PROPERTY = "date";
+ public static final String MESSAGE_PROPERTY = "message";
+ public static final String CATEGORY_PROPERTY = "category";
+ public static final String THREAD_PROPERTY = "thread";
+
+ public static final String DATE_ONLY_FORMAT = "yyyy_MM_dd";
+
+ private static final String LINE_SEP = System.getProperty("line.separator");
+
+ private String columnSep;
+ private int numberOfColumns;
+ private boolean startsFromSeparator;
+ private boolean endsWithSeparator;
+
+ private SimpleDateFormat recordDateFormat;
+ private boolean useFileModifiedDate;
+ private Pattern fileNameDatePattern;
+ private String fileNameDateFormat;
+
+ private File logDirectory;
+ private Comparator<String> fileNameComparator;
+
+ private Map<Integer, String> columnsMap;
+ private List<FileInfo> logFiles
+ = Collections.synchronizedList(new LinkedList<FileInfo>());
+ private Map<String, String> levelsMap;
+ private ConcurrentHashMap<Integer, PageInfo> pagesMap
+ = new ConcurrentHashMap<Integer, PageInfo>();
+
+
+ @Override
+ public int getSize() {
+ return -1;
+ }
+
+ @Override
+ public void load(List<LogRecord> list,
+ SearchCondition<LogRecord> condition,
+ int pageNumber,
+ int pageSize) {
+ FileInfo logFileInfo = getLogFileInfo(pageNumber, true);
+ if (logFileInfo == null) {
+ return;
+ }
+
+ int count = 0;
+ while (true) {
+ LogRecord record = readRecord(logFileInfo);
+ if (record == null) {
+ logFileInfo = getNextLogFileInfo(logFileInfo, true);
+ if (logFileInfo != null) {
+ continue;
+ } else {
+ return;
+ }
+ }
+ if (condition == null || condition.isMet(record)) {
+ list.add(record);
+ if (++count == pageSize) {
+ break;
+ }
+ }
+ }
+ savePagePosition(pageNumber, logFileInfo);
+
+ }
+
+ private FileInfo getNextLogFileInfo(FileInfo logFileInfo, boolean firstTry) {
+ for (Iterator<FileInfo> it = logFiles.iterator(); it.hasNext();) {
+ FileInfo fileInfo = it.next();
+ if (fileInfo == logFileInfo && it.hasNext()) {
+ return it.next();
+ } else {
+ break;
+ }
+ }
+ if (firstTry && logDirectory != null && scanLogDirectory()) {
+ return getNextLogFileInfo(logFileInfo, false);
+ }
+ return null;
+ }
+
+ private FileInfo getLogFileInfo(int pageNumber, boolean firstTry) {
+ PageInfo pageInfo = pagesMap.get(pageNumber);
+ if (pageInfo != null) {
+ FileInfo fileInfo = pageInfo.getFileInfo();
+ try {
+ fileInfo.getFile().seek(pageInfo.getPosition());
+ } catch (IOException ex) {
+ System.err.println("Problem setting a page position in " + fileInfo.getFileName());
+ return null;
+ }
+ return pageInfo.getFileInfo();
+ }
+ if (pageNumber == 1
+ && logDirectory != null
+ && firstTry
+ && logFiles.size() == 0
+ && scanLogDirectory()) {
+ FileInfo fileInfo = logFiles.get(0);
+ savePagePosition(0, fileInfo);
+ return fileInfo;
+ }
+ return null;
+ }
+
+
+ private void savePagePosition(int pageNumber, FileInfo fileInfo) {
+ try {
+ long pos = fileInfo.getFile().getFilePointer();
+ pagesMap.put(pageNumber + 1, new PageInfo(fileInfo, pos));
+ } catch (IOException ex) {
+ // ignore
+ }
+
+ }
+
+ protected LogRecord readRecord(FileInfo logFileInfo) {
+ try {
+ Map<Integer, String> map = new HashMap<Integer, String>(numberOfColumns);
+ readTheLine(logFileInfo.getFile(), map, 1);
+ return createRecord(map, logFileInfo);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+ protected LogRecord createRecord(Map<Integer, String> map, FileInfo logFileInfo) {
+ if (map.isEmpty()) {
+ return null;
+ }
+ LogRecord record = new LogRecord();
+ for (Map.Entry<Integer, String> entry : map.entrySet()) {
+ String propertyName = columnsMap.get(entry.getKey());
+ if (LEVEL_PROPERTY.equals(propertyName)) {
+ setLogRecordLevel(record, entry.getValue());
+ } else if (DATE_PROPERTY.equals(propertyName)) {
+ setLogRecordDate(record, entry.getValue(), logFileInfo);
+ } else if (MESSAGE_PROPERTY.equals(propertyName)) {
+ record.setMessage(entry.getValue());
+ } else if (CATEGORY_PROPERTY.equals(propertyName)) {
+ record.setLoggerName(entry.getValue());
+ } else if (THREAD_PROPERTY.equals(propertyName)) {
+ record.setThreadName(entry.getValue());
+ }
+ }
+ return record;
+ }
+
+ protected void setLogRecordLevel(LogRecord record, String logLevel) {
+ if (levelsMap != null) {
+ logLevel = levelsMap.get(logLevel);
+ }
+ if (logLevel != null) {
+ record.setLevel(LogLevel.valueOf(logLevel));
+ }
+ }
+
+ protected void setLogRecordDate(LogRecord record, String logDate, FileInfo logFileInfo) {
+ if (recordDateFormat != null) {
+ try {
+ String fileModifiedDate = logFileInfo.getFileModified();
+ logDate = fileModifiedDate != null ? fileModifiedDate + " " + logDate : logDate;
+ Date date = recordDateFormat.parse(logDate);
+ record.setEventTimestamp(date);
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+ }
+
+ protected void readTheLine(RandomAccessFile logFile, Map<Integer, String> map, int columnIndex)
+ throws IOException {
+
+ long nextPos = logFile.getFilePointer();
+ if (nextPos >= logFile.length()) {
+ return;
+ }
+
+ String line = logFile.readLine();
+
+ int lastIndex = 0;
+ if (columnIndex == 1 && startsFromSeparator) {
+ lastIndex = 1;
+ }
+
+ Set<Integer> requestedColumns = columnsMap.keySet();
+ int startingColumn = columnIndex;
+ while (lastIndex < line.length()) {
+
+ int sepIndex = line.indexOf(columnSep, lastIndex);
+
+ if (sepIndex != -1 && startingColumn == numberOfColumns && !endsWithSeparator) {
+ logFile.seek(nextPos);
+ return;
+ }
+
+ int actualIndex = sepIndex == -1 ? line.length() : sepIndex;
+
+ if (requestedColumns.contains(columnIndex)) {
+ String value = line.substring(lastIndex, actualIndex).trim();
+ String existingValue = map.get(columnIndex);
+ map.put(columnIndex, existingValue == null
+ ? value : existingValue + LINE_SEP + value);
+ }
+
+ lastIndex = actualIndex + 1;
+ if (sepIndex != -1 && columnIndex != numberOfColumns) {
+ columnIndex++;
+ }
+ }
+
+ if (columnIndex == numberOfColumns) {
+ readTheLine(logFile, map, columnIndex);
+ }
+ }
+
+ public void setColumnSep(String columnSep) {
+ this.columnSep = columnSep;
+ }
+
+ public void setNumberOfColums(String number) {
+ this.numberOfColumns = Integer.parseInt(number);
+ }
+
+ public void setColumnsMap(Map<Integer, String> columnsMap) {
+ this.columnsMap = columnsMap;
+ }
+
+ public void setLogLocations(List<String> locations) {
+ logFiles = new LinkedList<FileInfo>();
+ for (int i = 0; i < locations.size(); i++) {
+ String realPath = getRealLocation(locations.get(i));
+
+ try {
+ processNewLogFile(new File(realPath));
+ } catch (IOException ex) {
+ throw new RuntimeException("The log file " + realPath + " can not be opened: "
+ + ex.getMessage());
+ }
+ }
+ }
+
+ private void processNewLogFile(File file) throws IOException {
+ RandomAccessFile logFile = new RandomAccessFile(file, "r");
+
+ String fileModifiedDate = null;
+ if (useFileModifiedDate) {
+ String dateFormat = fileNameDateFormat == null ? DATE_ONLY_FORMAT : fileNameDateFormat;
+
+ if (fileNameDatePattern != null) {
+ Matcher m = fileNameDatePattern.matcher(file.getName());
+ if (m.find()) {
+ fileModifiedDate = m.group();
+ }
+ }
+ if (fileModifiedDate == null) {
+ Date fileDate = new Date(file.lastModified());
+ fileModifiedDate = new SimpleDateFormat(dateFormat).format(fileDate);
+ }
+ }
+
+ FileInfo fileInfo = new FileInfo(logFile, file.getName(), fileModifiedDate);
+ skipIgnorableRecords(fileInfo, logFiles.size() == 0);
+ logFiles.add(fileInfo);
+ }
+
+ private String getRealLocation(String location) {
+ int indexOpen = location.indexOf("{");
+ int indexClose = location.indexOf("}");
+ String realPath = null;
+ if (indexOpen == 0 && indexClose != -1) {
+ realPath = location.substring(1, indexClose)
+ + location.substring(indexClose + 1);
+
+ } else {
+ realPath = location;
+ }
+ return realPath;
+ }
+
+ public void setLogLocation(String location) {
+ String realPath = getRealLocation(location);
+ File file = new File(realPath);
+ if (file.isDirectory()) {
+ logDirectory = file;
+ } else {
+ setLogLocations(Collections.singletonList(realPath));
+ }
+ }
+
+ private void skipIgnorableRecords(FileInfo fInfo, boolean first) throws IOException {
+ long nextPos = fInfo.getFile().getFilePointer();
+ String line = fInfo.getFile().readLine();
+ if (line.contains(columnSep)) {
+ fInfo.getFile().seek(nextPos);
+ if (first) {
+ pagesMap.put(1, new PageInfo(fInfo, nextPos));
+ }
+ } else {
+ skipIgnorableRecords(fInfo, first);
+ }
+
+ }
+
+ public void setRecordDateFormat(String format) {
+ recordDateFormat = new SimpleDateFormat(format);
+ }
+
+ public void setLevelsMap(Map<String, String> map) {
+ this.levelsMap = map;
+ }
+
+ public void setFileNameComparator(Comparator<String> comp) {
+ this.fileNameComparator = comp;
+ }
+
+ public void close() {
+ for (FileInfo fileInfo : logFiles) {
+ try {
+ fileInfo.getFile().close();
+ } catch (IOException ex) {
+ // ignore
+ }
+ }
+ }
+
+ public void setUseFileModifiedDate(boolean useFileModifiedDate) {
+ this.useFileModifiedDate = useFileModifiedDate;
+ }
+
+ private boolean scanLogDirectory() {
+ int oldSize = logFiles.size();
+ for (File file : logDirectory.listFiles()) {
+ // just in case
+ if (file.isDirectory()) {
+ // continue
+ }
+ boolean isNew = true;
+ for (FileInfo fInfo : logFiles) {
+ if (fInfo.getFileName().equalsIgnoreCase(file.getName())) {
+ isNew = false;
+ break;
+ }
+ }
+ if (isNew) {
+ try {
+ processNewLogFile(file);
+ } catch (IOException ex) {
+ System.out.println("Log file " + file.getName() + " can not be opened");
+ }
+ }
+ }
+ if (logFiles.size() > oldSize) {
+ Collections.sort(logFiles, new FileInfoComparator());
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void setFileNameDatePattern(String fileNameDatePattern) {
+ this.fileNameDatePattern = Pattern.compile(fileNameDatePattern);
+ }
+
+ public void setFileNameDateFormat(String fileNameDateFormat) {
+ this.fileNameDateFormat = fileNameDateFormat;
+ }
+
+ protected static class PageInfo {
+ private FileInfo fileInfo;
+ private long pos;
+ public PageInfo(FileInfo fileInfo, long pos) {
+ this.fileInfo = fileInfo;
+ this.pos = pos;
+ }
+
+ public FileInfo getFileInfo() {
+ return fileInfo;
+ }
+ public long getPosition() {
+ return pos;
+ }
+ }
+
+ protected static class FileInfo {
+ private RandomAccessFile file;
+ private String fileModified;
+ private String fileName;
+
+ public FileInfo(RandomAccessFile file, String fileName, String fileModified) {
+ this.file = file;
+ this.fileModified = fileModified;
+ this.fileName = fileName;
+ }
+
+ public RandomAccessFile getFile() {
+ return file;
+ }
+ public String getFileModified() {
+ return fileModified;
+ }
+ public String getFileName() {
+ return fileName;
+ }
+ }
+
+ protected class FileInfoComparator implements Comparator<FileInfo> {
+
+ @Override
+ public int compare(FileInfo info1, FileInfo info2) {
+ String name1 = info1.getFileName();
+ String name2 = info2.getFileName();
+ if (fileNameComparator != null) {
+ return fileNameComparator.compare(name1, name2);
+ }
+ Integer logIndex1 = getLogIndex(name1);
+ Integer logIndex2 = getLogIndex(name2);
+ return logIndex1.compareTo(logIndex2) * -1;
+ }
+
+ private int getLogIndex(String name) {
+ int index = name.lastIndexOf('.');
+ try {
+ return Integer.valueOf(name.substring(index + 1));
+ } catch (Exception ex) {
+ return 0;
+ }
+ }
+ }
+}
Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorage.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorage.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: 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=1077946&r1=1077945&r2=1077946&view=diff
==============================================================================
--- cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java (original)
+++ cxf/trunk/rt/management-web/src/main/java/org/apache/cxf/management/web/logging/ReadableLogStorage.java Fri Mar 4 13:48:18 2011
@@ -33,13 +33,13 @@ 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
+ * @param pageNumber the initial page to have records loaded from
+ * @param int pageSize the max number of records to load from the storage
*/
void load(List<LogRecord> list,
SearchCondition<LogRecord> condition,
- int loadFrom,
- int maxNumberOfRecords);
+ int pageNumber,
+ int pageSize);
/**
Added: cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java?rev=1077946&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java (added)
+++ cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java Fri Mar 4 13:48:18 2011
@@ -0,0 +1,175 @@
+/**
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ReadOnlyFileStorageTest extends Assert {
+
+ private ReadOnlyFileStorage storage;
+
+ @Before
+ public void setUp() throws Exception {
+ storage = new ReadOnlyFileStorage();
+
+ storage.setNumberOfColums("7");
+ storage.setColumnSep("|");
+
+ Map<Integer, String> columnsMap = new HashMap<Integer, String>();
+ columnsMap.put(1, ReadOnlyFileStorage.DATE_PROPERTY);
+ columnsMap.put(2, ReadOnlyFileStorage.LEVEL_PROPERTY);
+ columnsMap.put(7, ReadOnlyFileStorage.MESSAGE_PROPERTY);
+
+ storage.setColumnsMap(columnsMap);
+
+ storage.setRecordDateFormat(ReadOnlyFileStorage.DATE_ONLY_FORMAT
+ + " " + "kk:mm:ss,SSS");
+ storage.setUseFileModifiedDate(true);
+
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ storage.close();
+ }
+
+ @Test
+ public void testReadRecords() throws Exception {
+
+ storage.setLogLocation(getClass().getResource("logs/karaf.log.1").toURI().getPath());
+ List<LogRecord> recordsFirstPage1 = readPage(1, 10, 10);
+
+ readPage(2, 10, 10);
+ readPage(3, 10, 10);
+ List<LogRecord> recordsLastPage1 = readPage(4, 10, 2);
+
+ List<LogRecord> recordsFirstPage2 = readPage(1, 10, 10);
+ compareRecords(recordsFirstPage1, recordsFirstPage2);
+
+ List<LogRecord> recordsLastPage2 = readPage(4, 10, 2);
+ compareRecords(recordsLastPage1, recordsLastPage2);
+
+ LogRecord lastRecord = recordsLastPage1.get(1);
+ assertTrue(lastRecord.getMessage().contains("Pax Web available at"));
+ }
+
+ @Test
+ public void testReadRecordsWithMultiLines() throws Exception {
+
+ storage.setLogLocation(getClass().getResource("logs/karaf.log").toURI().getPath());
+ List<LogRecord> recordsFirstPage1 = readPage(1, 10, 10);
+
+ List<LogRecord> recordsLastPage1 = readPage(2, 10, 10);
+
+ List<LogRecord> recordsFirstPage2 = readPage(1, 10, 10);
+ compareRecords(recordsFirstPage1, recordsFirstPage2);
+
+ List<LogRecord> recordsLastPage2 = readPage(2, 10, 10);
+ compareRecords(recordsLastPage1, recordsLastPage2);
+
+ LogRecord recordWithExceptionInMessage = recordsFirstPage1.get(2);
+ assertEquals(LogLevel.ERROR, recordWithExceptionInMessage.getLevel());
+ assertTrue(recordWithExceptionInMessage.getMessage()
+ .contains("mvn:org.apache.cxf/cxf-bundle/"));
+ assertTrue(recordWithExceptionInMessage.getMessage()
+ .contains("Caused by: org.osgi.framework.BundleException"));
+ }
+
+ @Test
+ public void testReadRecordsWithMultipleFiles() throws Exception {
+
+ List<String> locations = new ArrayList<String>();
+ locations.add(getClass().getResource("logs/karaf.log.1").toURI().getPath());
+ locations.add(getClass().getResource("logs/karaf.log").toURI().getPath());
+ storage.setLogLocations(locations);
+ List<LogRecord> recordsFirstPage1 = readPage(1, 10, 10);
+ readPage(2, 10, 10);
+ readPage(3, 10, 10);
+ List<LogRecord> recordsPage4 = readPage(4, 10, 10);
+ readPage(5, 10, 10);
+ List<LogRecord> recordsLastPage1 = readPage(6, 10, 2);
+
+ LogRecord recordWithExceptionInMessage = recordsPage4.get(4);
+ assertEquals(LogLevel.ERROR, recordWithExceptionInMessage.getLevel());
+ assertTrue(recordWithExceptionInMessage.getMessage()
+ .contains("mvn:org.apache.cxf/cxf-bundle/"));
+ assertTrue(recordWithExceptionInMessage.getMessage()
+ .contains("Caused by: org.osgi.framework.BundleException"));
+
+ List<LogRecord> recordsFirstPage2 = readPage(1, 10, 10);
+ compareRecords(recordsFirstPage1, recordsFirstPage2);
+
+ List<LogRecord> recordsLastPage2 = readPage(6, 10, 2);
+ compareRecords(recordsLastPage1, recordsLastPage2);
+ }
+
+ @Test
+ public void testReadRecordsWithScanDirectory() throws Exception {
+
+ String dir = getClass().getResource("logs").toURI().getPath();
+ storage.setLogLocation(dir);
+ List<LogRecord> recordsFirstPage1 = readPage(1, 10, 10);
+ readPage(2, 10, 10);
+ readPage(3, 10, 10);
+ List<LogRecord> recordsPage4 = readPage(4, 10, 10);
+ readPage(5, 10, 10);
+ List<LogRecord> recordsLastPage1 = readPage(6, 10, 2);
+
+ LogRecord recordWithExceptionInMessage = recordsPage4.get(4);
+ assertEquals(LogLevel.ERROR, recordWithExceptionInMessage.getLevel());
+ assertTrue(recordWithExceptionInMessage.getMessage()
+ .contains("mvn:org.apache.cxf/cxf-bundle/"));
+ assertTrue(recordWithExceptionInMessage.getMessage()
+ .contains("Caused by: org.osgi.framework.BundleException"));
+
+ List<LogRecord> recordsFirstPage2 = readPage(1, 10, 10);
+ compareRecords(recordsFirstPage1, recordsFirstPage2);
+
+ List<LogRecord> recordsLastPage2 = readPage(6, 10, 2);
+ compareRecords(recordsLastPage1, recordsLastPage2);
+ }
+
+ private void compareRecords(List<LogRecord> records1, List<LogRecord> records2) {
+ for (int i = 0; i < records1.size(); i++) {
+ LogRecord r1 = records1.get(i);
+ LogRecord r2 = records2.get(i);
+ assertEquals(r1.getLevel(), r2.getLevel());
+ assertEquals(r1.getEventTimestamp(), r2.getEventTimestamp());
+ assertEquals(r1.getMessage(), r2.getMessage());
+ }
+ }
+
+ private List<LogRecord> readPage(int page, int pageSize, int expected) {
+ List<LogRecord> records = new ArrayList<LogRecord>();
+ storage.load(records, null, page, pageSize);
+ assertEquals(expected, records.size());
+ return records;
+
+ }
+
+}
Propchange: cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/ReadOnlyFileStorageTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log?rev=1077946&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log (added)
+++ cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log Fri Mar 4 13:48:18 2011
@@ -0,0 +1,31 @@
+11:49:17,821 | INFO | Thread-11 | HttpServiceFactoryImpl | .internal.HttpServiceFactoryImpl 33 | 67 - org.ops4j.pax.web.pax-web-runtime - 0.7.4 | Binding bundle: [org.apache.karaf.deployer.features_2.1.4 [27]] to http service
+11:49:17,865 | INFO | guration Updater | JettyServerImpl | e.jetty.internal.JettyServerImpl 100 | 68 - org.ops4j.pax.web.pax-web-jetty - 0.7.4 | Pax Web available at [0.0.0.0]:[8080]
+11:49:18,356 | ERROR | Thread-4 | FeaturesServiceImpl | s.internal.FeaturesServiceImpl$1 814 | 26 - org.apache.karaf.features.core - 2.1.4 | Error installing boot features
+java.lang.Exception: Could not start bundle mvn:org.apache.cxf/cxf-bundle/2.4.0-SNAPSHOT in feature(s) cxf-2.4.0-SNAPSHOT: The bundle "org.apache.cxf.bundle_2.4.0.SNAPSHOT [110]" could not be resolved. Reason: Missing Constraint: Import-Package: org.apache.neethi; version="[3.0.0,4.0.0)"
+ at org.apache.karaf.features.internal.FeaturesServiceImpl.installFeatures(FeaturesServiceImpl.java:326)[26:org.apache.karaf.features.core:2.1.4]
+ at org.apache.karaf.features.internal.FeaturesServiceImpl$1.run(FeaturesServiceImpl.java:812)[26:org.apache.karaf.features.core:2.1.4]
+Caused by: org.osgi.framework.BundleException: The bundle "org.apache.cxf.bundle_2.4.0.SNAPSHOT [110]" could not be resolved. Reason: Missing Constraint: Import-Package: org.apache.neethi; version="[3.0.0,4.0.0)"
+ at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverError(AbstractBundle.java:1317)[osgi-3.6.0.v20100517.jar:]
+ at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolutionFailureException(AbstractBundle.java:1301)[osgi-3.6.0.v20100517.jar:]
+ at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:319)[osgi-3.6.0.v20100517.jar:]
+ at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:284)[osgi-3.6.0.v20100517.jar:]
+ at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:276)[osgi-3.6.0.v20100517.jar:]
+ at org.apache.karaf.features.internal.FeaturesServiceImpl.installFeatures(FeaturesServiceImpl.java:323)[26:org.apache.karaf.features.core:2.1.4]
+ ... 1 more
+11:49:24,415 | INFO | Bundle Shutdown | ContextLoaderListener | .activator.ContextLoaderListener 447 | 42 - org.springframework.osgi.extender - 1.2.1 | Stopping [org.springframework.osgi.extender] bundle v.[1.2.1]
+11:49:24,423 | INFO | Bundle Shutdown | TimerTaskExecutor | heduling.timer.TimerTaskExecutor 179 | 37 - org.springframework.context - 3.0.5.RELEASE | Cancelling Timer
+11:49:24,498 | INFO | Bundle Shutdown | Activator | x.web.service.internal.Activator 93 | 67 - org.ops4j.pax.web.pax-web-runtime - 0.7.4 | Pax Web stopped
+11:49:24,499 | INFO | Bundle Shutdown | HttpServiceFactoryImpl | .internal.HttpServiceFactoryImpl 40 | 67 - org.ops4j.pax.web.pax-web-runtime - 0.7.4 | Unbinding bundle: [org.apache.karaf.deployer.features_2.1.4 [27]]
+11:49:24,533 | INFO | Bundle Shutdown | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Stopping JMX OSGi agent
+11:49:24,534 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering org.osgi.jmx.framework.PackageStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=packageState,version=1.5
+11:49:24,534 | INFO | Bundle Shutdown | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering MBean with ObjectName [osgi.compendium:service=cm,version=1.3] for service with service.id [33]
+11:49:24,534 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering org.osgi.jmx.framework.FrameworkMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=framework,version=1.5
+11:49:24,534 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering org.osgi.jmx.framework.ServiceStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=serviceState,version=1.5
+11:49:24,534 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering org.osgi.jmx.service.cm.ConfigurationAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.compendium:service=cm,version=1.3
+11:49:24,535 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering org.osgi.jmx.service.permissionadmin.PermissionAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:service=permissionadmin,version=1.2
+11:49:24,535 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering org.osgi.jmx.framework.BundleStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=bundleState,version=1.5
+11:49:24,534 | INFO | Bundle Shutdown | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Unregistering MBean with ObjectName [osgi.core:service=permissionadmin,version=1.2] for service with service.id [3]
+11:49:24,539 | WARN | rint Extender: 1 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.jaas.modules is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/jaas/v1.0.0))]
+11:49:24,541 | WARN | rint Extender: 3 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.packages is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:24,543 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.commands is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:24,544 | WARN | rint Extender: 1 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.dev is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
Added: cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log.1
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log.1?rev=1077946&view=auto
==============================================================================
--- cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log.1 (added)
+++ cxf/trunk/rt/management-web/src/test/java/org/apache/cxf/management/web/logging/logs/karaf.log.1 Fri Mar 4 13:48:18 2011
@@ -0,0 +1,34 @@
+03-Mar-2011 11:49:12 org.apache.karaf.main.SimpleFileLock lock
+INFO: locking
+11:49:13,031 | INFO | Event Dispatcher | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Starting JMX OSGi agent
+11:49:13,037 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.packages is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,102 | INFO | Event Dispatcher | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering MBean with ObjectName [osgi.core:service=permissionadmin,version=1.2] for service with service.id [3]
+11:49:13,143 | INFO | Event Dispatcher | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering MBean with ObjectName [osgi.compendium:service=cm,version=1.3] for service with service.id [33]
+11:49:13,153 | WARN | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | There are no MBean servers registred, can't register MBeans
+11:49:13,154 | WARN | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | There are no MBean servers registred, can't register MBeans
+11:49:13,233 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.commands is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,239 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.management is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0)), (&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0))]
+11:49:13,242 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.dev is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,272 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.jaas.modules is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0)), (&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0)), (&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/jaas/v1.0.0))]
+11:49:13,277 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.console is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0))]
+11:49:13,365 | WARN | rint Extender: 3 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.admin.core is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0))]
+11:49:13,395 | WARN | rint Extender: 3 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.admin.command is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,408 | WARN | rint Extender: 1 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.osgi is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,553 | WARN | rint Extender: 3 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.ssh is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,602 | WARN | rint Extender: 2 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.features.command is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:13,635 | WARN | rint Extender: 3 | BlueprintContainerImpl | container.BlueprintContainerImpl 252 | 7 - org.apache.aries.blueprint - 0.2.0.incubating | Bundle org.apache.karaf.shell.log is waiting for namespace handlers [(&(objectClass=org.apache.aries.blueprint.NamespaceHandler)(osgi.service.blueprint.namespace=http://karaf.apache.org/xmlns/shell/v1.0.0))]
+11:49:14,206 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering org.osgi.jmx.framework.PackageStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=packageState,version=1.5
+11:49:14,208 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering org.osgi.jmx.framework.FrameworkMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=framework,version=1.5
+11:49:14,208 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering org.osgi.jmx.framework.ServiceStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=serviceState,version=1.5
+11:49:14,211 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering org.osgi.jmx.service.cm.ConfigurationAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.compendium:service=cm,version=1.3
+11:49:14,211 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering org.osgi.jmx.service.permissionadmin.PermissionAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:service=permissionadmin,version=1.2
+11:49:14,212 | INFO | JMX OSGi Agent | jmx | ? ? | 20 - org.apache.aries.jmx - 0.2.0.incubating | Registering org.osgi.jmx.framework.BundleStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@c5c3ac with name osgi.core:type=bundleState,version=1.5
+11:49:14,931 | INFO | rint Extender: 1 | SecurityUtils | e.sshd.common.util.SecurityUtils 80 | 28 - sshd-core - 0.4.0 | BouncyCastle not registered, using the default JCE provider
+11:49:16,463 | INFO | Thread-4 | FeaturesServiceImpl | res.internal.FeaturesServiceImpl 293 | 26 - org.apache.karaf.features.core - 2.1.4 | Bundles to refresh:
+11:49:16,843 | INFO | Thread-4 | ContextLoaderListener | .activator.ContextLoaderListener 354 | 42 - org.springframework.osgi.extender - 1.2.1 | Starting [org.springframework.osgi.extender] bundle v.[1.2.1]
+11:49:17,068 | WARN | Thread-4 | NamespaceManager | nternal.support.NamespaceManager 132 | 42 - org.springframework.osgi.extender - 1.2.1 | Bundle activemq-ra (org.apache.activemq.activemq-ra) cannot see class [org.springframework.beans.factory.xml.NamespaceHandlerResolver]; ignoring its namespace handlers
+11:49:17,172 | INFO | Thread-4 | ExtenderConfiguration | al.support.ExtenderConfiguration 150 | 42 - org.springframework.osgi.extender - 1.2.1 | No custom extender configuration detected; using defaults...
+11:49:17,184 | INFO | Thread-4 | TimerTaskExecutor | heduling.timer.TimerTaskExecutor 106 | 37 - org.springframework.context - 3.0.5.RELEASE | Initializing Timer
+11:49:17,497 | WARN | Thread-4 | NamespaceManager | nternal.support.NamespaceManager 132 | 42 - org.springframework.osgi.extender - 1.2.1 | Bundle activemq-ra (org.apache.activemq.activemq-ra) cannot see class [org.springframework.beans.factory.xml.NamespaceHandlerResolver]; ignoring its namespace handlers
+11:49:17,535 | INFO | Thread-4 | Activator | x.web.service.internal.Activator 80 | 67 - org.ops4j.pax.web.pax-web-runtime - 0.7.4 | Pax Web started
+11:49:17,775 | INFO | Thread-11 | JettyServerImpl | e.jetty.internal.JettyServerImpl 100 | 68 - org.ops4j.pax.web.pax-web-jetty - 0.7.4 | Pax Web available at [0.0.0.0]:[8080]