You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2015/06/29 12:55:25 UTC
svn commit: r1688178 - in /qpid/java/trunk:
broker-core/src/main/java/org/apache/qpid/server/logging/
broker-core/src/main/java/org/apache/qpid/server/logging/logback/
broker-core/src/main/java/org/apache/qpid/server/model/
broker-core/src/main/java/or...
Author: orudyy
Date: Mon Jun 29 10:55:24 2015
New Revision: 1688178
URL: http://svn.apache.org/r1688178
Log:
QPID-6614: [Java Broker] Make BrokerFileLogger and VirtualHostFileLogger implementations expose content of the current file and the names/content of any previously rolled files
Added:
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/PathTypedContent.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RollingPolicyDecorator.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RolloverWatcher.java
qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/
qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RollingPolicyDecoratorTest.java
qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RolloverWatcherTest.java
qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/util/LoggerTestHelper.java
Modified:
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLogger.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLoggerImpl.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/FileLoggerSettings.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/RollingFileAppenderFactory.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLogger.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLoggerImpl.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/TypedContent.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java
qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/RollingFileAppenderFactoryTest.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLogger.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLogger.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLogger.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLogger.java Mon Jun 29 10:55:24 2015
@@ -20,9 +20,18 @@
*/
package org.apache.qpid.server.logging;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Collection;
+
import org.apache.qpid.server.model.BrokerLogger;
+import org.apache.qpid.server.model.DerivedAttribute;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedOperation;
+import org.apache.qpid.server.model.Param;
+import org.apache.qpid.server.model.TypedContent;
@ManagedObject( category = false, type = BrokerFileLogger.TYPE)
public interface BrokerFileLogger<X extends BrokerFileLogger<X>> extends BrokerLogger<X>
@@ -49,4 +58,10 @@ public interface BrokerFileLogger<X exte
@ManagedAttribute(defaultValue = "%d %-5p [%t] \\(%c{2}\\) - %m%n")
String getLayout();
+
+ @DerivedAttribute
+ Collection<String> getRolledFiles();
+
+ @ManagedOperation(nonModifying = true)
+ TypedContent getFile(@Param(name = "fileName") String fileName);
}
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLoggerImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLoggerImpl.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLoggerImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerFileLoggerImpl.java Mon Jun 29 10:55:24 2015
@@ -20,18 +20,38 @@
*/
package org.apache.qpid.server.logging;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import javax.activation.MimetypesFileTypeMap;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.Context;
+import org.apache.qpid.server.logging.logback.RollingPolicyDecorator;
+import org.apache.qpid.server.logging.logback.RolloverWatcher;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.DerivedAttribute;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.TypedContent;
+import org.apache.qpid.server.util.DaemonThreadFactory;
public class BrokerFileLoggerImpl extends AbstractBrokerLogger<BrokerFileLoggerImpl> implements BrokerFileLogger<BrokerFileLoggerImpl>, FileLoggerSettings
{
+ private final RolloverWatcher _rolloverWatcher;
+ private final ScheduledExecutorService _rolledPolicyExecutor;
+
@ManagedAttributeField
private String _layout;
@ManagedAttributeField
@@ -46,11 +66,15 @@ public class BrokerFileLoggerImpl extend
private int _maxHistory;
@ManagedAttributeField
private String _maxFileSize;
+ private Collection<String> _rolledFiles;
+ private Path _baseFolder;
@ManagedObjectFactoryConstructor
protected BrokerFileLoggerImpl(final Map<String, Object> attributes, Broker<?> broker)
{
super(attributes, broker);
+ _rolloverWatcher = new RolloverWatcher();
+ _rolledPolicyExecutor = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("RolledFileScanner-" + getName()));
}
@Override
@@ -94,6 +118,36 @@ public class BrokerFileLoggerImpl extend
{
return _layout;
}
+ @Override
+ public Collection<String> getRolledFiles()
+ {
+ return _rolloverWatcher.getRolledFiles();
+ }
+
+ @Override
+ public TypedContent getFile(final String fileName)
+ {
+ return _rolloverWatcher.getTypedContent(fileName, _fileName.equals(fileName));
+ }
+
+ @Override
+ public void stopLogging()
+ {
+ super.stopLogging();
+ _rolledPolicyExecutor.shutdown();
+ }
+
+ @Override
+ public RollingPolicyDecorator.RolloverListener getRolloverListener()
+ {
+ return _rolloverWatcher;
+ }
+
+ @Override
+ public ScheduledExecutorService getExecutorService()
+ {
+ return _rolledPolicyExecutor;
+ }
@Override
protected Appender<ILoggingEvent> createAppenderInstance(Context loggerContext)
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/FileLoggerSettings.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/FileLoggerSettings.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/FileLoggerSettings.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/FileLoggerSettings.java Mon Jun 29 10:55:24 2015
@@ -20,6 +20,10 @@
*/
package org.apache.qpid.server.logging;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.qpid.server.logging.logback.RollingPolicyDecorator;
+
public interface FileLoggerSettings
{
String getFileName();
@@ -35,4 +39,8 @@ public interface FileLoggerSettings
String getMaxFileSize();
String getLayout();
+
+ RollingPolicyDecorator.RolloverListener getRolloverListener();
+
+ ScheduledExecutorService getExecutorService();
}
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/RollingFileAppenderFactory.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/RollingFileAppenderFactory.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/RollingFileAppenderFactory.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/RollingFileAppenderFactory.java Mon Jun 29 10:55:24 2015
@@ -27,9 +27,11 @@ import ch.qos.logback.classic.spi.ILoggi
import ch.qos.logback.core.Context;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
+import ch.qos.logback.core.rolling.RollingPolicyBase;
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
+import org.apache.qpid.server.logging.logback.RollingPolicyDecorator;
public class RollingFileAppenderFactory
{
@@ -40,34 +42,35 @@ public class RollingFileAppenderFactory
appender.setAppend(true);
appender.setContext(loggerContext);
+ RollingPolicyBase policy;
if(fileLoggerSettings.isRollDaily())
{
DailyTriggeringPolicy triggeringPolicy = new DailyTriggeringPolicy(fileLoggerSettings.isRollOnRestart(), fileLoggerSettings.getMaxFileSize());
triggeringPolicy.setContext(loggerContext);
TimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new TimeBasedRollingPolicy<>();
- rollingPolicy.setContext(loggerContext);
rollingPolicy.setMaxHistory(fileLoggerSettings.getMaxHistory());
rollingPolicy.setTimeBasedFileNamingAndTriggeringPolicy(triggeringPolicy);
rollingPolicy.setFileNamePattern(fileLoggerSettings.getFileName() + ".%d{yyyy-MM-dd}.%i" + (fileLoggerSettings.isCompressOldFiles()
? ".gz"
: ""));
- appender.setRollingPolicy(rollingPolicy);
- rollingPolicy.setParent(appender);
- rollingPolicy.start();
+ policy = rollingPolicy;
}
else
{
SizeTriggeringPolicy sizeTriggeringPolicy = new SizeTriggeringPolicy(fileLoggerSettings.isRollOnRestart(), fileLoggerSettings.getMaxFileSize());
sizeTriggeringPolicy.setContext(loggerContext);
SimpleRollingPolicy rollingPolicy = new SimpleRollingPolicy(fileLoggerSettings.getMaxHistory());
- rollingPolicy.setContext(loggerContext);
rollingPolicy.setFileNamePattern(fileLoggerSettings.getFileName() + ".%i" + (fileLoggerSettings.isCompressOldFiles() ? ".gz" : ""));
- appender.setRollingPolicy(rollingPolicy);
appender.setTriggeringPolicy(sizeTriggeringPolicy);
- rollingPolicy.setParent(appender);
- rollingPolicy.start();
sizeTriggeringPolicy.start();
+ policy = rollingPolicy;
}
+ policy.setContext(loggerContext);
+ RollingPolicyDecorator decorator = new RollingPolicyDecorator(policy, fileLoggerSettings.getRolloverListener(), fileLoggerSettings.getExecutorService());
+ decorator.setParent(appender);
+ appender.setRollingPolicy(decorator);
+ decorator.start();
+
final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setPattern(fileLoggerSettings.getLayout());
encoder.setContext(loggerContext);
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLogger.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLogger.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLogger.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLogger.java Mon Jun 29 10:55:24 2015
@@ -21,8 +21,15 @@
package org.apache.qpid.server.logging;
+import java.nio.file.Path;
+import java.util.Collection;
+
+import org.apache.qpid.server.model.DerivedAttribute;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedOperation;
+import org.apache.qpid.server.model.Param;
+import org.apache.qpid.server.model.TypedContent;
import org.apache.qpid.server.model.VirtualHostLogger;
@ManagedObject( category = false, type = VirtualHostFileLogger.TYPE)
@@ -51,4 +58,10 @@ public interface VirtualHostFileLogger<X
@ManagedAttribute(defaultValue = "%d %-5p [%t] \\(%c{2}\\) - %m%n")
String getLayout();
+
+ @DerivedAttribute
+ Collection<String> getRolledFiles();
+
+ @ManagedOperation(nonModifying = true)
+ TypedContent getFile(@Param(name = "fileName") String fileName);
}
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLoggerImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLoggerImpl.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLoggerImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/VirtualHostFileLoggerImpl.java Mon Jun 29 10:55:24 2015
@@ -21,19 +21,28 @@
package org.apache.qpid.server.logging;
import java.security.Principal;
+import java.util.Collection;
import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.Context;
+import org.apache.qpid.server.logging.logback.RollingPolicyDecorator;
+import org.apache.qpid.server.logging.logback.RolloverWatcher;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.TypedContent;
import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.util.DaemonThreadFactory;
public class VirtualHostFileLoggerImpl extends AbstractVirtualHostLogger<VirtualHostFileLoggerImpl> implements VirtualHostFileLogger<VirtualHostFileLoggerImpl>, FileLoggerSettings
{
private final Principal _principal;
+ private final RolloverWatcher _rolloverWatcher;
+ private final ScheduledExecutorService _rolledPolicyExecutor;
@ManagedAttributeField
private String _layout;
@@ -57,6 +66,8 @@ public class VirtualHostFileLoggerImpl e
{
super(attributes, virtualHost);
_principal = virtualHost.getPrincipal();
+ _rolloverWatcher = new RolloverWatcher();
+ _rolledPolicyExecutor = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("RolledFileScanner-" + getName()));
}
@Override
@@ -102,6 +113,37 @@ public class VirtualHostFileLoggerImpl e
}
@Override
+ public Collection<String> getRolledFiles()
+ {
+ return _rolloverWatcher.getRolledFiles();
+ }
+
+ @Override
+ public TypedContent getFile(final String fileName)
+ {
+ return _rolloverWatcher.getTypedContent(fileName, _fileName.equals(fileName));
+ }
+
+ @Override
+ public void stopLogging()
+ {
+ super.stopLogging();
+ _rolledPolicyExecutor.shutdown();
+ }
+
+ @Override
+ public RollingPolicyDecorator.RolloverListener getRolloverListener()
+ {
+ return _rolloverWatcher;
+ }
+
+ @Override
+ public ScheduledExecutorService getExecutorService()
+ {
+ return _rolledPolicyExecutor;
+ }
+
+ @Override
protected Appender<ILoggingEvent> createAppenderInstance(Context loggerContext)
{
return new RollingFileAppenderFactory().createRollingFileAppender(this, loggerContext);
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/PathTypedContent.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/PathTypedContent.java?rev=1688178&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/PathTypedContent.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/PathTypedContent.java Mon Jun 29 10:55:24 2015
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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.qpid.server.logging.logback;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+
+import org.apache.qpid.server.model.TypedContent;
+
+public class PathTypedContent implements TypedContent
+{
+ private final Path _path;
+ private final String _contentType;
+
+ public PathTypedContent(Path path, String contentType)
+ {
+ _path = path;
+ _contentType = contentType;
+ }
+
+ @Override
+ public String getContentType()
+ {
+ return _contentType;
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException
+ {
+ return _path == null ? null : new FileInputStream(_path.toFile());
+ }
+
+ @Override
+ public long getSize()
+ {
+ return _path == null ? 0 : _path.toFile().length();
+ }
+
+ @Override
+ public String getFileName()
+ {
+ return _path == null ? null : _path.getFileName().toString();
+ }
+}
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RollingPolicyDecorator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RollingPolicyDecorator.java?rev=1688178&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RollingPolicyDecorator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RollingPolicyDecorator.java Mon Jun 29 10:55:24 2015
@@ -0,0 +1,312 @@
+/*
+ *
+ * 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.qpid.server.logging.logback;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.regex.Pattern;
+
+import ch.qos.logback.core.FileAppender;
+import ch.qos.logback.core.rolling.RollingPolicy;
+import ch.qos.logback.core.rolling.RollingPolicyBase;
+import ch.qos.logback.core.rolling.RolloverFailure;
+import ch.qos.logback.core.rolling.helper.CompressionMode;
+import ch.qos.logback.core.rolling.helper.FileNamePattern;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RollingPolicyDecorator implements RollingPolicy
+{
+ public static final int DEFAULT_RESCAN_DELAY = 5000;
+ public static final String ROLLOVER_RESCAN_DELAY_MS_PROPERTY_NAME = "qpid.logger_rollover_rescan_delay_ms";
+ public static final int DEFAULT_RESCAN_LIMIT = 60;
+ public static final String ROLLOVER_RESCAN_LIMIT_PROPERTY_NAME = "qpid.logger_rollover_rescan_limit";
+ private static final Logger LOGGER = LoggerFactory.getLogger(RollingPolicyDecorator.class);
+ public static final String WARNING_MESSAGE = "Exceeded maximum number of rescans without detecting rolled over log file.";
+
+ private final RollingPolicyBase _decorated;
+ private final RolloverListener _listener;
+ private final Path _rolledFilesBaseFolder;
+ private final Pattern _rolledFileRegExp;
+ private final ScheduledExecutorService _executorService;
+ private final long _rescanDelayMillis = Long.getLong(ROLLOVER_RESCAN_DELAY_MS_PROPERTY_NAME, DEFAULT_RESCAN_DELAY);
+ private final long _rescanLimit = Long.getLong(ROLLOVER_RESCAN_LIMIT_PROPERTY_NAME, DEFAULT_RESCAN_LIMIT);
+ private final Lock _publishResultsLock = new ReentrantLock();
+ private ScanTask _currentScanTask;
+ private String[] _previousScanResults;
+
+ public RollingPolicyDecorator(RollingPolicyBase decorated, RolloverListener listener, ScheduledExecutorService executorService)
+ {
+ _decorated = decorated;
+ _listener = listener;
+ _executorService = executorService;
+
+ String filePathPattern = _decorated.getFileNamePattern();
+ String filePathRegExp = new FileNamePattern(filePathPattern, _decorated.getContext()).toRegex();
+ _rolledFilesBaseFolder = getRolledFilesBaseFolderFromRegExp(filePathRegExp);
+ _rolledFileRegExp = Pattern.compile(filePathRegExp);
+ _currentScanTask = null;
+ }
+
+ @Override
+ public void rollover() throws RolloverFailure
+ {
+ ScanTask task = createScanTaskAndCancelInProgress();
+ _decorated.rollover();
+ _executorService.execute(task);
+ }
+
+ @Override
+ public String getActiveFileName()
+ {
+ return _decorated.getActiveFileName();
+ }
+
+ @Override
+ public CompressionMode getCompressionMode()
+ {
+ return _decorated.getCompressionMode();
+ }
+
+ @Override
+ public void setParent(FileAppender appender)
+ {
+ _decorated.setParent(appender);
+ }
+
+ @Override
+ public void start()
+ {
+ ScanTask task = createScanTaskAndCancelInProgress();
+ _decorated.start();
+ _executorService.execute(task);
+ }
+
+ @Override
+ public void stop()
+ {
+ _decorated.stop();
+ synchronized (_publishResultsLock)
+ {
+ if (_currentScanTask != null)
+ {
+ _currentScanTask.cancel();
+ }
+ _previousScanResults = null;
+ }
+ }
+
+ @Override
+ public boolean isStarted()
+ {
+ return _decorated.isStarted();
+ }
+
+
+ public interface RolloverListener
+ {
+ void onRollover(Path baseFolder, String[] relativeFileNames);
+ }
+
+ public RollingPolicyBase getDecorated()
+ {
+ return _decorated;
+ }
+
+ private ScanTask createScanTaskAndCancelInProgress()
+ {
+ ScanTask task = new ScanTask();
+ synchronized (_publishResultsLock)
+ {
+ if (_currentScanTask != null)
+ {
+ _currentScanTask.cancel();
+ }
+ _currentScanTask = task;
+ }
+ return task;
+ }
+
+ private Path getRolledFilesBaseFolderFromRegExp(String fileNamePattern)
+ {
+ int firstDigitPatternPosition= fileNamePattern.indexOf("\\d");
+ if (firstDigitPatternPosition == -1)
+ {
+ throw new RuntimeException("Rolling policy file pattern does not seem to contain date or integer token");
+ }
+ int slashBeforeDigitPatternPosition = fileNamePattern.lastIndexOf("/", firstDigitPatternPosition);
+ if (slashBeforeDigitPatternPosition != -1)
+ {
+ return new File(fileNamePattern.substring(0, slashBeforeDigitPatternPosition)).toPath().toAbsolutePath();
+ }
+ else
+ {
+ return new File(System.getProperty("user.dir")).toPath().toAbsolutePath();
+ }
+ }
+
+ private class ScanTask implements Runnable
+ {
+ private int _rescanCounter;
+ private volatile boolean _canceled;
+
+ @Override
+ public void run()
+ {
+ if (!isCanceled() )
+ {
+ String[] rolloverFiles = scan();
+
+ if (!publishScanResults(rolloverFiles) && !isCanceled())
+ {
+ if (_rescanCounter < _rescanLimit)
+ {
+ ++_rescanCounter;
+ _executorService.schedule(this, _rescanDelayMillis, TimeUnit.MILLISECONDS);
+ }
+ else
+ {
+ LOGGER.warn(WARNING_MESSAGE);
+ }
+ }
+ }
+ }
+
+ private boolean publishScanResults(String[] rolloverFiles)
+ {
+ boolean published = false;
+
+ if (rolloverFiles != null && !isCanceled() )
+ {
+ synchronized (_publishResultsLock)
+ {
+ if (!isCanceled() && (_previousScanResults == null || !Arrays.equals(rolloverFiles, _previousScanResults)))
+ {
+ _previousScanResults = rolloverFiles;
+ published = true;
+ }
+ }
+ }
+
+ if (published)
+ {
+ _listener.onRollover(_rolledFilesBaseFolder, rolloverFiles);
+ }
+
+ return published;
+ }
+
+ public String[] scan()
+ {
+ final List<Path> rolledFiles = new ArrayList<>();
+ try
+ {
+ Files.walkFileTree(_rolledFilesBaseFolder, new FileVisitor<Path>()
+ {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ {
+ return (isCanceled() ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE);
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ {
+ String absolutePath = file.toAbsolutePath().toString();
+ if (File.separatorChar == '\\')
+ {
+ absolutePath = absolutePath.replace('\\', '/');
+ }
+
+ if (_rolledFileRegExp.matcher(absolutePath).matches())
+ {
+ rolledFiles.add(file);
+ }
+ return (isCanceled() ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE);
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc)
+ {
+ return (isCanceled() ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+ {
+ return (isCanceled() ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE);
+ }
+ });
+ }
+ catch(IOException e)
+ {
+ LOGGER.warn("Unexpected IOException while scanning for rollover files.", e);
+ }
+ return (isCanceled() ? null : relativizeAndSort(_rolledFilesBaseFolder, rolledFiles));
+ }
+
+ public void cancel()
+ {
+ _canceled = true;
+ }
+
+
+ private String[] relativizeAndSort(Path parent, List<Path> rolledFiles)
+ {
+ String[] results = new String[rolledFiles.size()];
+ int i = 0;
+ for (Path f : rolledFiles)
+ {
+ results[i++] = parent.relativize(f).toString();
+ }
+
+ Arrays.sort(results, new Comparator<String>()
+ {
+ @Override
+ public int compare(String o1, String o2)
+ {
+ return o1.compareTo(o2);
+ }
+ });
+ return results;
+ }
+
+ public boolean isCanceled()
+ {
+ return _canceled || Thread.currentThread().isInterrupted();
+ }
+
+ }
+}
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RolloverWatcher.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RolloverWatcher.java?rev=1688178&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RolloverWatcher.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/logback/RolloverWatcher.java Mon Jun 29 10:55:24 2015
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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.qpid.server.logging.logback;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public class RolloverWatcher implements RollingPolicyDecorator.RolloverListener
+{
+ private volatile Collection<String> _rolledFiles;
+ private volatile Path _baseFolder;
+
+ public RolloverWatcher()
+ {
+ _rolledFiles = Collections.emptyList();
+ }
+
+ @Override
+ public void onRollover(Path baseFolder, String[] relativeFileNames)
+ {
+ _rolledFiles = Collections.unmodifiableCollection(Arrays.asList(relativeFileNames));
+ _baseFolder = baseFolder;
+ }
+
+ public PathTypedContent getTypedContent(String fileName, boolean activeFile)
+ {
+ if (fileName == null)
+ {
+ throw new IllegalArgumentException("File name cannot be null");
+ }
+
+ Path path = null;
+ if (activeFile)
+ {
+ path = new File(fileName).toPath();
+ }
+ else if (_rolledFiles.contains(fileName))
+ {
+ path = _baseFolder.resolve(fileName);
+ }
+ return new PathTypedContent(path, getContentType(fileName));
+ }
+
+ public Collection<String> getRolledFiles()
+ {
+ return _rolledFiles;
+ }
+
+ public String getContentType(String fileName)
+ {
+ String fileNameLower = fileName.toLowerCase();
+ if (fileNameLower.endsWith(".gz"))
+ {
+ return "application/x-gzip";
+ }
+ else if (fileNameLower.endsWith(".zip"))
+ {
+ return "application/x-zip";
+ }
+ else
+ {
+ return "text/plain";
+ }
+ }
+}
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/TypedContent.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/TypedContent.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/TypedContent.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/TypedContent.java Mon Jun 29 10:55:24 2015
@@ -20,9 +20,17 @@
*/
package org.apache.qpid.server.model;
+import java.io.IOException;
+import java.io.InputStream;
+
@ManagedAttributeValueType
public interface TypedContent
{
String getContentType();
- byte[] getData();
+
+ InputStream openInputStream() throws IOException;
+
+ long getSize();
+
+ String getFileName();
}
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java Mon Jun 29 10:55:24 2015
@@ -18,6 +18,8 @@
*/
package org.apache.qpid.server.queue;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import java.nio.ByteBuffer;
import java.security.AccessControlException;
import java.security.AccessController;
@@ -3267,11 +3269,23 @@ public abstract class AbstractQueue<X ex
}
@Override
- public byte[] getData()
+ public InputStream openInputStream()
{
- return messageFinder.getContent();
+ return new ByteArrayInputStream(messageFinder.getContent());
}
- };
+
+ @Override
+ public long getSize()
+ {
+ return messageFinder.getContent().length;
+ }
+
+ @Override
+ public String getFileName()
+ {
+ return null;
+ }
+ };
}
else
{
Modified: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java (original)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java Mon Jun 29 10:55:24 2015
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.logging;
+import static org.apache.qpid.server.util.LoggerTestHelper.assertLoggedEvent;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -125,8 +126,8 @@ public class BrokerLoggerTest extends Qp
logger.debug("Test2");
logger.info("Test3");
- assertLoggedEvent(false, "Test2", logger.getName(), Level.DEBUG);
- assertLoggedEvent(true, "Test3", logger.getName(), Level.INFO);
+ assertLoggedEvent(_loggerAppender, false, "Test2", logger.getName(), Level.DEBUG);
+ assertLoggedEvent(_loggerAppender, true, "Test3", logger.getName(), Level.INFO);
}
public void testRemoveExistingFilter()
@@ -140,12 +141,12 @@ public class BrokerLoggerTest extends Qp
Logger logger = LoggerFactory.getLogger("org.apache.qpid");
logger.info("Test1");
- assertLoggedEvent(true, "Test1", logger.getName(), Level.INFO);
+ assertLoggedEvent(_loggerAppender, true, "Test1", logger.getName(), Level.INFO);
createdFilter.delete();
logger.info("Test2");
- assertLoggedEvent(false, "Test2", logger.getName(), Level.INFO);
+ assertLoggedEvent(_loggerAppender, false, "Test2", logger.getName(), Level.INFO);
}
public void testDeleteLogger()
@@ -158,24 +159,4 @@ public class BrokerLoggerTest extends Qp
assertNull("Appender found when it should have been deleted", rootLogger.getAppender(_brokerLogger.getName()));
}
- private void assertLoggedEvent(boolean exists, String message, String loggerName, Level level)
- {
- List<ILoggingEvent> events;
- synchronized(_loggerAppender)
- {
- events = new ArrayList<>(_loggerAppender.list);
- }
-
- boolean logged = false;
- for (ILoggingEvent event: events)
- {
- if (event.getFormattedMessage().equals(message) && event.getLoggerName().equals(loggerName) && event.getLevel() == level)
- {
- logged = true;
- break;
- }
- }
- assertEquals("Event " + message + " from logger " + loggerName + " of log level " + level
- + " is " + (exists ? "not" : "") + " found", exists, logged);
- }
}
Modified: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/RollingFileAppenderFactoryTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/RollingFileAppenderFactoryTest.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/RollingFileAppenderFactoryTest.java (original)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/RollingFileAppenderFactoryTest.java Mon Jun 29 10:55:24 2015
@@ -23,6 +23,8 @@ package org.apache.qpid.server.logging;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.util.concurrent.ScheduledExecutorService;
+
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
@@ -32,6 +34,7 @@ import ch.qos.logback.core.rolling.Rolli
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.rolling.TriggeringPolicy;
import ch.qos.logback.core.rolling.helper.CompressionMode;
+import org.apache.qpid.server.logging.logback.RollingPolicyDecorator;
import org.apache.qpid.test.utils.QpidTestCase;
public class RollingFileAppenderFactoryTest extends QpidTestCase
@@ -57,6 +60,7 @@ public class RollingFileAppenderFactoryT
when(_settings.isRollDaily()).thenReturn(Boolean.TRUE);
when(_settings.isRollOnRestart()).thenReturn(Boolean.TRUE);
when(_settings.getMaxHistory()).thenReturn(MAX_HISTORY);
+ when(_settings.getExecutorService()).thenReturn(mock(ScheduledExecutorService.class));
}
public void testCreateRollingFileAppenderDailyRolling()
@@ -66,7 +70,9 @@ public class RollingFileAppenderFactoryT
assertEquals("Unexpected appender file name", FILE_NAME, appender.getFile());
RollingPolicy rollingPolicy = appender.getRollingPolicy();
- assertTrue("Unexpected rolling policy", rollingPolicy instanceof TimeBasedRollingPolicy);
+ assertTrue("Unexpected rolling policy", rollingPolicy instanceof RollingPolicyDecorator);
+ rollingPolicy = ((RollingPolicyDecorator)rollingPolicy).getDecorated();
+ assertTrue("Unexpected decorated rolling policy", rollingPolicy instanceof TimeBasedRollingPolicy);
assertEquals("Unexpected max history", MAX_HISTORY, ((TimeBasedRollingPolicy) rollingPolicy).getMaxHistory());
assertEquals("Unexpected file name pattern", FILE_NAME + ".%d{yyyy-MM-dd}.%i.gz", ((TimeBasedRollingPolicy) rollingPolicy).getFileNamePattern());
assertEquals("Unexpected compression mode", CompressionMode.GZ, rollingPolicy.getCompressionMode());
@@ -87,7 +93,9 @@ public class RollingFileAppenderFactoryT
assertEquals("Unexpected appender file name", FILE_NAME, appender.getFile());
RollingPolicy rollingPolicy = appender.getRollingPolicy();
- assertTrue("Unexpected rolling policy", rollingPolicy instanceof RollingFileAppenderFactory.SimpleRollingPolicy);
+ assertTrue("Unexpected rolling policy", rollingPolicy instanceof RollingPolicyDecorator);
+ rollingPolicy = ((RollingPolicyDecorator)rollingPolicy).getDecorated();
+ assertTrue("Unexpected decorated rolling policy", rollingPolicy instanceof RollingFileAppenderFactory.SimpleRollingPolicy);
assertEquals("Unexpected max history", MAX_HISTORY, ((RollingFileAppenderFactory.SimpleRollingPolicy) rollingPolicy).getMaxIndex());
assertEquals("Unexpected file name pattern", FILE_NAME + ".%i", ((RollingFileAppenderFactory.SimpleRollingPolicy) rollingPolicy).getFileNamePattern());
assertEquals("Unexpected compression mode", CompressionMode.NONE, rollingPolicy.getCompressionMode());
Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RollingPolicyDecoratorTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RollingPolicyDecoratorTest.java?rev=1688178&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RollingPolicyDecoratorTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RollingPolicyDecoratorTest.java Mon Jun 29 10:55:24 2015
@@ -0,0 +1,216 @@
+/*
+ *
+ * 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.qpid.server.logging.logback;
+
+import static org.apache.qpid.server.util.LoggerTestHelper.assertLoggedEvent;
+import static org.apache.qpid.server.util.LoggerTestHelper.createAndRegisterAppender;
+import static org.apache.qpid.server.util.LoggerTestHelper.deleteAndUnregisterAppender;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.concurrent.*;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.FileAppender;
+import ch.qos.logback.core.read.ListAppender;
+import ch.qos.logback.core.rolling.RollingPolicyBase;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class RollingPolicyDecoratorTest extends QpidTestCase
+{
+ private RollingPolicyBase _delegate;
+ private RollingPolicyDecorator _policy;
+ private RollingPolicyDecorator.RolloverListener _listener;
+ private File _baseFolder;
+ private File _testFile;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _baseFolder = TestFileUtils.createTestDirectory("rollover", true);
+ _testFile = createTestFile("test.2015-06-25.0.gz");
+ Context mockContext = mock(Context.class);
+ _delegate = mock(RollingPolicyBase.class);
+ when(_delegate.getFileNamePattern()).thenReturn( _baseFolder + File.separator + "test.%d{yyyy-MM-dd}.%i.gz");
+ when(_delegate.getContext()).thenReturn(mockContext);
+ _listener = mock(RollingPolicyDecorator.RolloverListener.class);
+
+ _policy = new RollingPolicyDecorator(_delegate, _listener, createMockExecutorService());
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+ if (_baseFolder.exists())
+ {
+ FileUtils.delete(_baseFolder, true);
+ }
+ }
+
+ public File createTestFile(String fileName) throws IOException
+ {
+ File testFile = new File(_baseFolder, fileName);
+ testFile.createNewFile();
+ return testFile;
+ }
+
+ private ScheduledExecutorService createMockExecutorService()
+ {
+ ScheduledExecutorService executorService = mock(ScheduledExecutorService.class);
+ doAnswer(new Answer() {
+ public Object answer(InvocationOnMock invocation) {
+ Object[] args = invocation.getArguments();
+ ((Runnable)args[0]).run();
+ return null;
+ }}).when(executorService).schedule(any(Runnable.class), any(long.class), any(TimeUnit.class));
+ doAnswer(new Answer() {
+ public Object answer(InvocationOnMock invocation) {
+ Object[] args = invocation.getArguments();
+ ((Runnable)args[0]).run();
+ return null;
+ }}).when(executorService).execute(any(Runnable.class));
+ return executorService;
+ }
+
+ public void testRollover()
+ {
+ _policy.rollover();
+ verify(_delegate).rollover();
+ }
+
+ public void testRolloverListener() throws InterruptedException
+ {
+ _policy.rollover();
+ verify(_listener).onRollover(any(Path.class), any(String[].class));
+ }
+
+ public void testRolloverWithFile() throws IOException
+ {
+ _policy.rollover();
+ verify(_delegate).rollover();
+
+ Matcher<String[]> matcher = getMatcher(new String[]{_testFile.getName()});
+ verify(_listener).onRollover(eq(_baseFolder.toPath()), argThat(matcher));
+ }
+
+ public void testRolloverRescanLimit() throws IOException
+ {
+ ListAppender loggerAppender = createAndRegisterAppender("testAppender");
+ try
+ {
+ _policy.rollover();
+ verify(_delegate).rollover();
+ _policy.rollover();
+ assertLoggedEvent(loggerAppender, true, RollingPolicyDecorator.WARNING_MESSAGE, RollingPolicyDecorator.class.getName(), Level.WARN);
+ }
+ finally
+ {
+ deleteAndUnregisterAppender(loggerAppender);
+ }
+ }
+
+ public void testSequentialRollover() throws IOException
+ {
+ _policy.rollover();
+ verify(_delegate).rollover();
+
+ Matcher<String[]> matcher = getMatcher(new String[]{ _testFile.getName() });
+ verify(_listener).onRollover(eq(_baseFolder.toPath()), argThat(matcher));
+
+ File secondFile = createTestFile("test.2015-06-25.1.gz");
+ _policy.rollover();
+ verify(_delegate, times(2)).rollover();
+ Matcher<String[]> matcher2 = getMatcher(new String[]{_testFile.getName(), secondFile.getName()});
+ verify(_listener).onRollover(eq(_baseFolder.toPath()), argThat(matcher2));
+ }
+
+ private Matcher<String[]> getMatcher(final String[] expected)
+ {
+ return new BaseMatcher<String[]>()
+ {
+ @Override
+ public boolean matches(Object item)
+ {
+ return Arrays.equals(expected, (String[]) item);
+ }
+ @Override
+ public void describeTo(Description description)
+ {
+ description.appendValueList("[", ",", "]", expected);
+ }
+ };
+ }
+
+ public void testGetActiveFileName()
+ {
+ _policy.getActiveFileName();
+ verify(_delegate).getActiveFileName();
+ }
+
+ public void testGetCompressionMode()
+ {
+ _policy.getCompressionMode();
+ verify(_delegate).getCompressionMode();
+ }
+
+ public void testSetParent()
+ {
+ FileAppender appender = mock(FileAppender.class);
+ _policy.setParent(appender);
+ verify(_delegate).setParent(appender);
+ }
+
+ public void testStart()
+ {
+ _policy.start();
+ verify(_delegate).start();
+ }
+
+ public void testStop()
+ {
+ _policy.stop();
+ verify(_delegate).stop();
+ }
+
+ public void testIsStarted()
+ {
+ _policy.isStarted();
+ verify(_delegate).isStarted();
+ }
+
+}
Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RolloverWatcherTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RolloverWatcherTest.java?rev=1688178&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RolloverWatcherTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/logback/RolloverWatcherTest.java Mon Jun 29 10:55:24 2015
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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.qpid.server.logging.logback;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.apache.qpid.server.model.TypedContent;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class RolloverWatcherTest extends QpidTestCase
+{
+ private RolloverWatcher _rolloverWatcher;
+ private File _baseFolder;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _rolloverWatcher = new RolloverWatcher();
+ _baseFolder = TestFileUtils.createTestDirectory("rollover", true);
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+ if (_baseFolder.exists())
+ {
+ FileUtils.delete(_baseFolder, true);
+ }
+ }
+
+ public void testOnRollover() throws Exception
+ {
+ String[] files = {"test1", "test2"};
+ _rolloverWatcher.onRollover(_baseFolder.toPath(), files);
+
+ assertEquals("Unexpected rolled files. Expected " + Arrays.toString(files) + " but got "
+ + _rolloverWatcher.getRolledFiles(), new HashSet<>(Arrays.asList(files)),
+ new HashSet<>(_rolloverWatcher.getRolledFiles()));
+ }
+
+ public void testGetTypedContentForActiveFile() throws Exception
+ {
+ _rolloverWatcher.onRollover(_baseFolder.toPath(), new String[]{});
+
+ final File activeFile = new File(_baseFolder, "test.log");
+ TestFileUtils.saveTextContentInFile("test", activeFile);
+ TypedContent content = _rolloverWatcher.getTypedContent(activeFile.getAbsolutePath(), true);
+
+ assertEquals("Unexpected content type", "text/plain", content.getContentType());
+ assertEquals("Unexpected data", "test", readStream(content.openInputStream()));
+ assertEquals("Unexpected size", 4, content.getSize());
+ }
+
+ public void testGetTypedForNullFile() throws Exception
+ {
+ try
+ {
+ _rolloverWatcher.getTypedContent(null, true);
+ fail("IllegalArgumentException is expected for null file name");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testGetTypedContentForExistingRolledFile() throws Exception
+ {
+ String[] files = {"test1.gz", "test2.gz"};
+ _rolloverWatcher.onRollover(_baseFolder.toPath(), files);
+
+ TestFileUtils.saveTextContentInFile("test.gz", new File(_baseFolder, "test1.gz"));
+
+ TypedContent content = _rolloverWatcher.getTypedContent("test1.gz", false);
+
+ assertEquals("Unexpected content type", "application/x-gzip", content.getContentType());
+ assertEquals("Unexpected data", "test.gz", readStream(content.openInputStream()));
+ assertEquals("Unexpected size", 7, content.getSize());
+ }
+
+ public void testGetTypedContentForNonExistingRolledFile() throws Exception
+ {
+ String[] files = {"test1.gz", "test2.gz"};
+ Path baseFolder = new File(getTestName()).toPath();
+ _rolloverWatcher.onRollover(baseFolder, files);
+
+ TypedContent content = _rolloverWatcher.getTypedContent("test3.zip", false);
+
+ assertEquals("Unexpected content type", "application/x-zip", content.getContentType());
+ assertNull("Unexpected content stream", content.openInputStream());
+ assertEquals("Unexpected size", 0, content.getSize());
+ }
+
+ public void testGetContentType() throws Exception
+ {
+ assertEquals("Unexpected content type for log file", "text/plain", _rolloverWatcher.getContentType("test.log"));
+ assertEquals("Unexpected content type for gzip file", "application/x-gzip", _rolloverWatcher.getContentType("test.gz"));
+ assertEquals("Unexpected content type for zip file", "application/x-zip", _rolloverWatcher.getContentType("test.zip"));
+ }
+
+ private String readStream(InputStream contentStream) throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = contentStream.read(buffer)) > 0)
+ {
+ os.write(buffer, 0, length);
+ }
+ return new String(os.toByteArray());
+ }
+}
Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/util/LoggerTestHelper.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/util/LoggerTestHelper.java?rev=1688178&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/util/LoggerTestHelper.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/util/LoggerTestHelper.java Mon Jun 29 10:55:24 2015
@@ -0,0 +1,83 @@
+/*
+ * 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.qpid.server.util;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.read.ListAppender;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class LoggerTestHelper
+{
+ private final static ch.qos.logback.classic.Logger ROOT_LOGGER = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));
+
+ public static ListAppender createAndRegisterAppender(String appenderName)
+ {
+ ListAppender appender = new ListAppender();
+ appender.setName(appenderName);
+ ROOT_LOGGER.addAppender(appender);
+ appender.start();
+ return appender;
+ }
+
+ public static void deleteAndUnregisterAppender(Appender appender)
+ {
+ appender.stop();
+ ROOT_LOGGER.detachAppender(appender);
+ }
+
+ public static void deleteAndUnregisterAppender(String appenderName)
+ {
+ Appender appender = ROOT_LOGGER.getAppender(appenderName);
+ if (appender != null)
+ {
+ deleteAndUnregisterAppender(appender);
+ }
+ }
+
+ public static void assertLoggedEvent(ListAppender appender, boolean exists, String message, String loggerName, Level level)
+ {
+ List<ILoggingEvent> events;
+ synchronized(appender)
+ {
+ events = new ArrayList<>(appender.list);
+ }
+
+ boolean logged = false;
+ for (ILoggingEvent event: events)
+ {
+ if (event.getFormattedMessage().equals(message) && event.getLoggerName().equals(loggerName) && event.getLevel() == level)
+ {
+ logged = true;
+ break;
+ }
+ }
+ assertEquals("Event " + message + " from logger " + loggerName + " of log level " + level
+ + " is " + (exists ? "not" : "") + " found", exists, logged);
+ }
+
+}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java Mon Jun 29 10:55:24 2015
@@ -20,7 +20,9 @@
*/
package org.apache.qpid.server.management.plugin.servlet.rest;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@@ -37,6 +39,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.qpid.server.model.TypedContent;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.slf4j.Logger;
@@ -328,4 +331,45 @@ public abstract class AbstractServlet ex
}
return null;
}
+
+ protected void writeTypedContent(TypedContent typedContent, HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ response.setContentType(typedContent.getContentType());
+ response.setContentLength((int) typedContent.getSize());
+ String fileName = typedContent.getFileName();
+ if (fileName != null)
+ {
+ response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");
+ }
+
+ try (InputStream contentStream = typedContent.openInputStream())
+ {
+ writeStreamContent(contentStream, request, response);
+ }
+ catch (FileNotFoundException e)
+ {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ }
+ }
+
+ protected void writeStreamContent(InputStream contentStream, HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ if (contentStream == null)
+ {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_OK);
+ try (OutputStream os = getOutputStream(request, response))
+ {
+ byte[] buffer = new byte[8192];
+ int length;
+ while ((length = contentStream.read(buffer)) > 0)
+ {
+ os.write(buffer, 0, length);
+ }
+ }
+ }
+ }
}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java Mon Jun 29 10:55:24 2015
@@ -52,9 +52,7 @@ public class MessageContentServlet exten
TypedContent content = queue.getMessageContent(Long.parseLong(path[2]));
if(content != null)
{
- response.setContentType(content.getContentType());
- response.setContentLength(content.getData().length);
- getOutputStream(request, response).write(content.getData());
+ writeTypedContent(content, request, response);
}
}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java?rev=1688178&r1=1688177&r2=1688178&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Mon Jun 29 10:55:24 2015
@@ -16,7 +16,9 @@
*/
package org.apache.qpid.server.management.plugin.servlet.rest;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@@ -608,10 +610,7 @@ public class RestServlet extends Abstrac
if(returnVal instanceof TypedContent)
{
TypedContent typedContent = (TypedContent)returnVal;
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentType(typedContent.getContentType());
- response.setContentLength(typedContent.getData().length);
- getOutputStream(request, response).write(typedContent.getData());
+ writeTypedContent(typedContent, request, response);
}
else
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org