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/09 13:14:08 UTC

svn commit: r1684380 - in /qpid/java/trunk: broker-core/src/main/java/org/apache/qpid/server/logging/ broker-core/src/main/java/org/apache/qpid/server/security/ broker-core/src/test/java/org/apache/qpid/server/logging/ broker-core/src/test/java/org/apa...

Author: orudyy
Date: Tue Jun  9 11:14:07 2015
New Revision: 1684380

URL: http://svn.apache.org/r1684380
Log:
QPID-6578: [Java Broker] Add the ability for logging filters to be added/removed/changed dynamically

Added:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/AbstractBrokerLogger.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/CompositeFilter.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/BrokerNameAndLevelFilterTest.java
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/CompositeFilterTest.java
Modified:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerConsoleLoggerImpl.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/BrokerMemoryLoggerImpl.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilter.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterImpl.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
    qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/AbstractBrokerLogger.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/AbstractBrokerLogger.java?rev=1684380&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/AbstractBrokerLogger.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/AbstractBrokerLogger.java Tue Jun  9 11:14:07 2015
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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.i
+ *
+ */
+package org.apache.qpid.server.logging;
+
+import java.util.Map;
+
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerLogger;
+import org.apache.qpid.server.model.BrokerLoggerFilter;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractBrokerLogger<X extends AbstractBrokerLogger<X>> extends AbstractConfiguredObject<X> implements BrokerLogger<X>, ConfigurationChangeListener
+{
+    protected CompositeFilter _compositeFilter = new CompositeFilter();
+
+    protected AbstractBrokerLogger(Map<String, Object> attributes, Broker<?> broker)
+    {
+        super(parentsMap(broker), attributes);
+    }
+
+    protected CompositeFilter getCompositeFilter()
+    {
+        return _compositeFilter;
+    }
+
+    @Override
+    protected <C extends ConfiguredObject> ListenableFuture<C> addChildAsync(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+    {
+        final ListenableFuture<C> filterFuture = getObjectFactory().createAsync(childClass, attributes, this);
+        doAfter(filterFuture, new CallableWithArgument<ListenableFuture<C>, C>()
+        {
+            @Override
+            public ListenableFuture<C> call(final C child) throws Exception
+            {
+                BrokerLoggerFilter<?> filter = (BrokerLoggerFilter) child;
+                filter.addChangeListener(AbstractBrokerLogger.this);
+                getCompositeFilter().addFilter(filter);
+                return Futures.immediateFuture(child);
+            }
+        });
+        return filterFuture;
+    }
+
+    @Override
+    public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
+    {
+        if (newState == State.DELETED && object instanceof BrokerLoggerFilter)
+        {
+            getCompositeFilter().removeFilter((BrokerLoggerFilter)object);
+            object.removeChangeListener(this);
+        }
+    }
+
+    @Override
+    public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
+    {
+        // no-op
+    }
+
+    @Override
+    public void childRemoved(ConfiguredObject<?> object, ConfiguredObject<?> child)
+    {
+        // no-op
+    }
+
+    @Override
+    public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
+    {
+        // no-op
+    }
+
+    @Override
+    public void bulkChangeStart(ConfiguredObject<?> object)
+    {
+        // no-op
+    }
+
+    @Override
+    public void bulkChangeEnd(ConfiguredObject<?> object)
+    {
+        // no-op
+    }
+
+    protected void initializeAppender(Appender<ILoggingEvent> appender)
+    {
+        ch.qos.logback.classic.Logger rootLogger =
+                (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+        LoggerContext loggerContext = rootLogger.getLoggerContext();
+
+        appender.setContext(loggerContext);
+
+        CompositeFilter compositeFilter = getCompositeFilter();
+        compositeFilter.addFilters(getChildren(BrokerLoggerFilter.class));
+        appender.addFilter(compositeFilter);
+        appender.setName(getName());
+    }
+}

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerConsoleLoggerImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerConsoleLoggerImpl.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerConsoleLoggerImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerConsoleLoggerImpl.java Tue Jun  9 11:14:07 2015
@@ -29,13 +29,11 @@ import ch.qos.logback.core.ConsoleAppend
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerLoggerFilter;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
 
-public class BrokerConsoleLoggerImpl extends AbstractConfiguredObject<BrokerConsoleLoggerImpl> implements BrokerConsoleLogger<BrokerConsoleLoggerImpl>
+public class BrokerConsoleLoggerImpl extends AbstractBrokerLogger<BrokerConsoleLoggerImpl> implements BrokerConsoleLogger<BrokerConsoleLoggerImpl>
 {
     @ManagedAttributeField
     private String _layout;
@@ -43,7 +41,7 @@ public class BrokerConsoleLoggerImpl ext
     @ManagedObjectFactoryConstructor
     protected BrokerConsoleLoggerImpl(final Map<String, Object> attributes, Broker<?> broker)
     {
-        super(parentsMap(broker),attributes);
+        super(attributes, broker);
     }
 
     @Override
@@ -55,24 +53,14 @@ public class BrokerConsoleLoggerImpl ext
     @Override
     public Appender<ILoggingEvent> asAppender()
     {
-        ch.qos.logback.classic.Logger rootLogger =
-                (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+        ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
+        initializeAppender(consoleAppender);
 
         final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
         encoder.setPattern(getLayout());
-        encoder.setContext(rootLogger.getLoggerContext());
+        encoder.setContext(consoleAppender.getContext());
         encoder.start();
 
-        ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
-        consoleAppender.setContext(rootLogger.getLoggerContext());
-
-        for(BrokerLoggerFilter<?> filter : getChildren(BrokerLoggerFilter.class))
-        {
-            consoleAppender.addFilter(filter.asFilter());
-        }
-        consoleAppender.addFilter(DenyAllFilter.getInstance());
-        consoleAppender.setName(getName());
-
         consoleAppender.setEncoder(encoder);
         consoleAppender.start();
 

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=1684380&r1=1684379&r2=1684380&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 Tue Jun  9 11:14:07 2015
@@ -27,6 +27,7 @@ import ch.qos.logback.classic.LoggerCont
 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
+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.SizeAndTimeBasedFNATP;
@@ -35,13 +36,11 @@ import ch.qos.logback.core.rolling.TimeB
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerLoggerFilter;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
 
-public class BrokerFileLoggerImpl extends AbstractConfiguredObject<BrokerFileLoggerImpl> implements BrokerFileLogger<BrokerFileLoggerImpl>
+public class BrokerFileLoggerImpl extends AbstractBrokerLogger<BrokerFileLoggerImpl> implements BrokerFileLogger<BrokerFileLoggerImpl>
 {
     @ManagedAttributeField
     private String _layout;
@@ -63,7 +62,7 @@ public class BrokerFileLoggerImpl extend
     @ManagedObjectFactoryConstructor
     protected BrokerFileLoggerImpl(final Map<String, Object> attributes, Broker<?> broker)
     {
-        super(parentsMap(broker),attributes);
+        super(attributes, broker);
     }
 
     @Override
@@ -117,20 +116,12 @@ public class BrokerFileLoggerImpl extend
     @Override
     public Appender<ILoggingEvent> asAppender()
     {
-        ch.qos.logback.classic.Logger rootLogger =
-                (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
-        LoggerContext loggerContext = rootLogger.getLoggerContext();
         RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<>();
         appender.setFile(getFileName());
         appender.setAppend(true);
-        appender.setContext(loggerContext);
 
-        for(BrokerLoggerFilter<?> filter : getChildren(BrokerLoggerFilter.class))
-        {
-            appender.addFilter(filter.asFilter());
-        }
-        appender.addFilter(DenyAllFilter.getInstance());
-        appender.setName(getName());
+        initializeAppender(appender);
+        Context loggerContext = appender.getContext();
 
         if(isRollDaily())
         {

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerMemoryLoggerImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerMemoryLoggerImpl.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerMemoryLoggerImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerMemoryLoggerImpl.java Tue Jun  9 11:14:07 2015
@@ -28,13 +28,11 @@ import ch.qos.logback.core.Appender;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerLoggerFilter;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
 
-public class BrokerMemoryLoggerImpl extends AbstractConfiguredObject<BrokerMemoryLoggerImpl> implements BrokerMemoryLogger<BrokerMemoryLoggerImpl>
+public class BrokerMemoryLoggerImpl extends AbstractBrokerLogger<BrokerMemoryLoggerImpl> implements BrokerMemoryLogger<BrokerMemoryLoggerImpl>
 {
 
     @ManagedAttributeField
@@ -43,7 +41,7 @@ public class BrokerMemoryLoggerImpl exte
     @ManagedObjectFactoryConstructor
     protected BrokerMemoryLoggerImpl(final Map<String, Object> attributes, Broker<?> broker)
     {
-        super(parentsMap(broker),attributes);
+        super(attributes, broker);
     }
 
     @Override
@@ -55,19 +53,8 @@ public class BrokerMemoryLoggerImpl exte
     @Override
     public Appender<ILoggingEvent> asAppender()
     {
-        ch.qos.logback.classic.Logger rootLogger =
-                (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
-        LoggerContext loggerContext = rootLogger.getLoggerContext();
-
         final RecordEventAppender appender = new RecordEventAppender(getMaxRecords());
-        appender.setName(getName());
-        appender.setContext(loggerContext);
-
-        for(BrokerLoggerFilter<?> filter : getChildren(BrokerLoggerFilter.class))
-        {
-            appender.addFilter(filter.asFilter());
-        }
-        appender.addFilter(DenyAllFilter.getInstance());
+        initializeAppender(appender);
         appender.start();
         return appender;
     }

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilter.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilter.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilter.java Tue Jun  9 11:14:07 2015
@@ -29,6 +29,8 @@ public interface BrokerNameAndLevelFilte
 {
 
     String TYPE = "NameAndLevel";
+    String LOGGER_NAME = "loggerName";
+    String LEVEL = "level";
 
     @ManagedAttribute( defaultValue = "" )
     String getLoggerName();

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterImpl.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterImpl.java Tue Jun  9 11:14:07 2015
@@ -21,6 +21,7 @@
 package org.apache.qpid.server.logging;
 
 import java.util.Map;
+import java.util.Set;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
@@ -28,20 +29,28 @@ import ch.qos.logback.classic.spi.ILoggi
 import ch.qos.logback.core.filter.Filter;
 import ch.qos.logback.core.spi.FilterReply;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.BrokerLogger;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
 
 public class BrokerNameAndLevelFilterImpl extends AbstractConfiguredObject<BrokerNameAndLevelFilterImpl>
         implements BrokerNameAndLevelFilter<BrokerNameAndLevelFilterImpl>
 {
     @ManagedAttributeField
     private String _loggerName;
-    @ManagedAttributeField
+    @ManagedAttributeField(afterSet = "logLevelAfterSet")
     private LogLevel _level;
 
+    private volatile Level _logbackLevel;
+
     @ManagedObjectFactoryConstructor
     protected BrokerNameAndLevelFilterImpl(final Map<String, Object> attributes, BrokerLogger<?> logger)
     {
@@ -49,6 +58,19 @@ public class BrokerNameAndLevelFilterImp
     }
 
     @Override
+    protected void validateChange(ConfiguredObject<?> proxyForValidation, Set<String> changedAttributes)
+    {
+        super.validateChange(proxyForValidation, changedAttributes);
+        BrokerNameAndLevelFilter proxyFilter = (BrokerNameAndLevelFilter)proxyForValidation;
+        if (changedAttributes.contains(LOGGER_NAME) &&
+                ((getLoggerName() != null && !getLoggerName().equals(proxyFilter.getLoggerName())) ||
+                        (getLoggerName() == null && proxyFilter.getLoggerName() != null)))
+        {
+            throw new IllegalConfigurationException("Attribute '" + LOGGER_NAME + " cannot be changed");
+        }
+    }
+
+    @Override
     public String getLoggerName()
     {
         return _loggerName;
@@ -60,10 +82,14 @@ public class BrokerNameAndLevelFilterImp
         return _level;
     }
 
+    private void logLevelAfterSet()
+    {
+        _logbackLevel = Level.toLevel(getLevel().name());
+    }
+
     @Override
     public Filter<ILoggingEvent> asFilter()
     {
-        final Level level = Level.toLevel(getLevel().name());
         final String loggerName = getLoggerName();
         if("".equals(loggerName) || Logger.ROOT_LOGGER_NAME.equals(loggerName))
         {
@@ -72,7 +98,7 @@ public class BrokerNameAndLevelFilterImp
                 @Override
                 public FilterReply decide(final ILoggingEvent event)
                 {
-                    return event.getLevel().isGreaterOrEqual(level) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
+                    return event.getLevel().isGreaterOrEqual(_logbackLevel) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
                 }
             };
         }
@@ -84,7 +110,7 @@ public class BrokerNameAndLevelFilterImp
                 @Override
                 public FilterReply decide(final ILoggingEvent event)
                 {
-                    return event.getLevel().isGreaterOrEqual(level) && event.getLoggerName().startsWith(prefixName) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
+                    return event.getLevel().isGreaterOrEqual(_logbackLevel) && event.getLoggerName().startsWith(prefixName) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
                 }
             };
         }
@@ -95,9 +121,33 @@ public class BrokerNameAndLevelFilterImp
                 @Override
                 public FilterReply decide(final ILoggingEvent event)
                 {
-                    return event.getLevel().isGreaterOrEqual(level) && event.getLoggerName().equals(loggerName) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
+                    return event.getLevel().isGreaterOrEqual(_logbackLevel) && event.getLoggerName().equals(loggerName) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
                 }
             };
         }
     }
+
+    @StateTransition( currentState = { State.ACTIVE, State.ERRORED, State.UNINITIALIZED }, desiredState = State.DELETED )
+    private ListenableFuture<Void> doDelete()
+    {
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        closeAsync().addListener(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                setState(State.DELETED);
+                returnVal.set(null);
+
+            }
+        }, getTaskExecutor().getExecutor());
+        return returnVal;
+    }
+
+    @StateTransition( currentState = { State.ERRORED, State.UNINITIALIZED }, desiredState = State.ACTIVE )
+    private ListenableFuture<Void> doActivate()
+    {
+        setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
+    }
 }

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/CompositeFilter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/CompositeFilter.java?rev=1684380&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/CompositeFilter.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/logging/CompositeFilter.java Tue Jun  9 11:14:07 2015
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.FilterReply;
+import org.apache.qpid.server.model.BrokerLoggerFilter;
+
+public class CompositeFilter extends Filter<ILoggingEvent>
+{
+    private List<Filter<ILoggingEvent>> _filterList = new CopyOnWriteArrayList<>();
+
+    public void addFilter(BrokerLoggerFilter filter)
+    {
+        Filter f = filter.asFilter();
+        f.setName(filter.getName());
+        _filterList.add(f);
+    }
+
+    public void addFilters(Collection<BrokerLoggerFilter> filters)
+    {
+        for(BrokerLoggerFilter<?> filter : filters)
+        {
+            addFilter(filter);
+        }
+    }
+
+    public void removeFilter(BrokerLoggerFilter filter)
+    {
+        Iterator<Filter<ILoggingEvent>> it = _filterList.iterator();
+        while(it.hasNext())
+        {
+            Filter f = it.next();
+            if (f.getName().equals(filter.getName()))
+            {
+                _filterList.remove(f);
+                break;
+            }
+        }
+    }
+
+    @Override
+    public FilterReply decide(ILoggingEvent event)
+    {
+        for(Filter filter : _filterList)
+        {
+            FilterReply reply = filter.decide(event);
+            if (reply == FilterReply.DENY || reply == FilterReply.ACCEPT)
+            {
+                return reply;
+            }
+        }
+        return FilterReply.DENY;
+    }
+}

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java Tue Jun  9 11:14:07 2015
@@ -32,7 +32,6 @@ import java.security.AccessController;
 import java.security.Principal;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -42,6 +41,7 @@ import javax.security.auth.Subject;
 import org.apache.qpid.server.model.AccessControlProvider;
 import org.apache.qpid.server.model.Binding;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerLoggerFilter;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Connection;
 import org.apache.qpid.server.model.Consumer;
@@ -365,7 +365,7 @@ public class SecurityManager
                 // CREATE GROUP MEMBER is transformed into UPDATE GROUP rule
                 return Operation.UPDATE;
             }
-            else if (isBrokerOrBrokerChildOrPreferencesProvider(category))
+            else if (isBrokerType(category))
             {
                 // CREATE/UPDATE broker child is transformed into CONFIGURE BROKER rule
                 return Operation.CONFIGURE;
@@ -378,7 +378,7 @@ public class SecurityManager
                 // DELETE BINDING is transformed into UNBIND EXCHANGE rule
                 return Operation.UNBIND;
             }
-            else if (isBrokerOrBrokerChildOrPreferencesProvider(category))
+            else if (isBrokerType(category))
             {
                 // DELETE broker child is transformed into CONFIGURE BROKER rule
                 return Operation.CONFIGURE;
@@ -393,10 +393,11 @@ public class SecurityManager
         return operation;
     }
 
-    private boolean isBrokerOrBrokerChildOrPreferencesProvider(Class<? extends ConfiguredObject> category)
+    private boolean isBrokerType(Class<? extends ConfiguredObject> category)
     {
         return Broker.class.isAssignableFrom(category) ||
                PreferencesProvider.class.isAssignableFrom(category) ||
+               BrokerLoggerFilter.class.isAssignableFrom(category) ||
                ( !VirtualHostNode.class.isAssignableFrom(category) && getModel().getChildTypes(Broker.class).contains(category));
     }
 
@@ -438,7 +439,7 @@ public class SecurityManager
             Queue<?> queue = (Queue<?>)configuredObject.getParent(Queue.class);
             setQueueProperties(queue, properties);
         }
-        else if (isBrokerOrBrokerChildOrPreferencesProvider(configuredObjectType))
+        else if (isBrokerType(configuredObjectType))
         {
             String description = String.format("%s %s '%s'",
                     configuredObjectOperation == null? null : configuredObjectOperation.name().toLowerCase(),
@@ -484,7 +485,7 @@ public class SecurityManager
         {
             return ObjectType.VIRTUALHOSTNODE;
         }
-        else if (isBrokerOrBrokerChildOrPreferencesProvider(category))
+        else if (isBrokerType(category))
         {
             return ObjectType.BROKER;
         }

Added: 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=1684380&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerLoggerTest.java Tue Jun  9 11:14:07 2015
@@ -0,0 +1,188 @@
+/*
+ *
+ * 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerLoggerFilter;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BrokerLoggerTest extends QpidTestCase
+{
+
+    private AbstractBrokerLogger<?> _brokerLogger;
+    private ListAppender _loggerAppender;
+    private TaskExecutor _taskExecutor;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _loggerAppender = new ListAppender();
+
+        ch.qos.logback.classic.Logger rootLogger =
+                (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+        rootLogger.addAppender(_loggerAppender);
+
+        _taskExecutor = new TaskExecutorImpl();
+        _taskExecutor.start();
+
+        Model model = BrokerModel.getInstance();
+
+        org.apache.qpid.server.security.SecurityManager securityManager = mock(SecurityManager.class);
+        Broker<?> broker = mock(Broker.class);
+        when(broker.getSecurityManager()).thenReturn(securityManager);
+        when(broker.getModel()).thenReturn(model);
+        when(broker.getChildExecutor()).thenReturn(_taskExecutor);
+        doReturn(Broker.class).when(broker).getCategoryClass();
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put("name", "test");
+        _brokerLogger = new AbstractBrokerLogger(attributes, broker)
+        {
+            @Override
+            public Appender<ILoggingEvent> asAppender()
+            {
+                return _loggerAppender;
+            }
+        };
+        _brokerLogger.open();
+        _loggerAppender.addFilter(_brokerLogger.getCompositeFilter());
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            _taskExecutor.stopImmediately();
+
+            ch.qos.logback.classic.Logger rootLogger =
+                    (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+
+            _loggerAppender.clearAllFilters();
+
+            _loggerAppender.stop();
+            rootLogger.detachAppender(_loggerAppender);
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testAddNewFilter()
+    {
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put("loggerName", "org.apache.qpid");
+        attributes.put("level", LogLevel.INFO);
+        attributes.put("name", "test");
+        attributes.put("type", BrokerNameAndLevelFilter.TYPE);
+
+        Collection<BrokerLoggerFilter> filtersBefore = _brokerLogger.getChildren(BrokerLoggerFilter.class);
+        assertEquals("Unexpected number of filters before creation", 0, filtersBefore.size());
+
+        BrokerLoggerFilter<?> createdFilter = _brokerLogger.createChild(BrokerLoggerFilter.class, attributes);
+        assertEquals("Unexpected filter name", "test", createdFilter.getName());
+
+        Collection<BrokerLoggerFilter> filtersAfter = _brokerLogger.getChildren(BrokerLoggerFilter.class);
+        assertEquals("Unexpected number of filters after creation", 1, filtersAfter.size());
+
+        BrokerLoggerFilter filter = filtersAfter.iterator().next();
+        assertEquals("Unexpected filter", createdFilter, filter);
+
+        Logger logger = LoggerFactory.getLogger("org.apache.qpid");
+
+        _loggerAppender.start();
+        logger.debug("Test2");
+        logger.info("Test3");
+        _loggerAppender.stop();
+
+        assertLoggedEvent(false, "Test2", logger.getName(), Level.DEBUG);
+        assertLoggedEvent(true, "Test3", logger.getName(), Level.INFO);
+    }
+
+    public void testRemoveExistingFilter()
+    {
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put("loggerName", "org.apache.qpid");
+        attributes.put("level", LogLevel.INFO);
+        attributes.put("name", "test");
+        attributes.put("type", BrokerNameAndLevelFilter.TYPE);
+        BrokerLoggerFilter<?> createdFilter = _brokerLogger.createChild(BrokerLoggerFilter.class, attributes);
+        Logger logger = LoggerFactory.getLogger("org.apache.qpid");
+
+        _loggerAppender.start();
+        logger.info("Test1");
+        _loggerAppender.stop();
+
+        assertLoggedEvent(true, "Test1", logger.getName(), Level.INFO);
+
+        createdFilter.delete();
+
+        _loggerAppender.start();
+        logger.info("Test2");
+        _loggerAppender.stop();
+
+        assertLoggedEvent(false, "Test2", logger.getName(), Level.INFO);
+    }
+
+    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);
+    }
+}

Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterTest.java?rev=1684380&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/BrokerNameAndLevelFilterTest.java Tue Jun  9 11:14:07 2015
@@ -0,0 +1,207 @@
+/*
+ *
+ * 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.ListAppender;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerLogger;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BrokerNameAndLevelFilterTest extends QpidTestCase
+{
+    private Logger _logger = null;
+    private Logger _nonQpidLogger = null;
+
+    private BrokerLogger<?> _brokerLogger;
+    private BrokerNameAndLevelFilter<?> _brokerNameAndLevelFilter;
+    private ListAppender _loggerAppender;
+    private TaskExecutor _taskExecutor;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _loggerAppender = new ListAppender();
+
+        _taskExecutor =  new TaskExecutorImpl();
+        _taskExecutor.start();
+
+        Model model = BrokerModel.getInstance();
+
+        SecurityManager securityManager = mock(SecurityManager.class);
+        Broker<?> broker = mock(Broker.class);
+        when(broker.getSecurityManager()).thenReturn(securityManager);
+        when(broker.getModel()).thenReturn(model);
+        doReturn(Broker.class).when(broker).getCategoryClass();
+
+        _brokerLogger = mock(BrokerLogger.class);
+        when(_brokerLogger.getModel()).thenReturn(model);
+        when(_brokerLogger.getChildExecutor()).thenReturn(_taskExecutor);
+        when(_brokerLogger.getParent(Broker.class)).thenReturn(broker);
+        doReturn(BrokerLogger.class).when(_brokerLogger).getCategoryClass();
+
+
+        _logger = LoggerFactory.getLogger("org.apache.qpid.server.test");
+        _nonQpidLogger = LoggerFactory.getLogger("org.apache.qpid.test");
+    }
+
+    private void setUpFilterAndAppender(String loggerName, LogLevel logLevel)
+    {
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put("loggerName", loggerName);
+        attributes.put("level", logLevel);
+        attributes.put("name", "test");
+
+        _brokerNameAndLevelFilter = new BrokerNameAndLevelFilterImplFactory().createInstance(attributes, _brokerLogger);
+        _brokerNameAndLevelFilter.open();
+        ch.qos.logback.classic.Logger rootLogger =
+                (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+        rootLogger.addAppender(_loggerAppender);
+        _loggerAppender.setContext(rootLogger.getLoggerContext());
+        _loggerAppender.addFilter(_brokerNameAndLevelFilter.asFilter());
+        _loggerAppender.addFilter(DenyAllFilter.getInstance());
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            _brokerNameAndLevelFilter.close();
+            _taskExecutor.stopImmediately();
+
+            ch.qos.logback.classic.Logger rootLogger =
+                    (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+
+            _loggerAppender.clearAllFilters();
+
+            _loggerAppender.stop();
+            rootLogger.detachAppender(_loggerAppender);
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testSetNameOnWildcardFilter() throws Exception
+    {
+        setUpFilterAndAppender("org.apache.qpid.server.*", LogLevel.DEBUG);
+        _loggerAppender.start();
+        _logger.debug("Test1");
+        _nonQpidLogger.debug("Test2");
+        _loggerAppender.stop();
+
+        assertLoggedEvent(true, "Test1", _logger.getName(), Level.DEBUG);
+        assertLoggedEvent(false, "Test2", _nonQpidLogger.getName(), Level.DEBUG);
+
+        try
+        {
+            _brokerNameAndLevelFilter.setAttributes(Collections.<String, Object>singletonMap("loggerName", "org.apache.qpid.*"));
+            fail("Changing of logger name is unsupported");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            // pass
+        }
+    }
+
+    public void testSetLevelOnWildcardFilter() throws Exception
+    {
+        setUpFilterAndAppender("org.apache.qpid.server.*", LogLevel.DEBUG);
+        doChangeLevelTest();
+    }
+
+    public void testSetLevelOnEmptyLogNameFilter() throws Exception
+    {
+        setUpFilterAndAppender("", LogLevel.DEBUG);
+        doChangeLevelTest();
+    }
+
+    public void testSetLevelOnNonEmptyAndNonWildCardLogNameFilter() throws Exception
+    {
+        setUpFilterAndAppender(_logger.getName(), LogLevel.DEBUG);
+        doChangeLevelTest();
+    }
+
+    private void doChangeLevelTest()
+    {
+        _loggerAppender.start();
+        _logger.debug("Test1");
+        _loggerAppender.stop();
+
+        assertLoggedEvent(true, "Test1", _logger.getName(), Level.DEBUG);
+
+        _brokerNameAndLevelFilter.setAttributes(Collections.<String, Object>singletonMap("level", LogLevel.INFO));
+        assertEquals("Unexpected log level attribute", LogLevel.INFO, _brokerNameAndLevelFilter.getLevel());
+
+        _loggerAppender.start();
+        _logger.debug("Test2");
+        _logger.info("Test3");
+        _loggerAppender.stop();
+
+        assertLoggedEvent(false, "Test2", _logger.getName(), Level.DEBUG);
+        assertLoggedEvent(true, "Test3", _logger.getName(), Level.INFO);
+    }
+
+    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);
+    }
+
+}

Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/CompositeFilterTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/CompositeFilterTest.java?rev=1684380&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/CompositeFilterTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/logging/CompositeFilterTest.java Tue Jun  9 11:14:07 2015
@@ -0,0 +1,157 @@
+/*
+ *
+ * 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;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.FilterReply;
+import org.apache.qpid.server.model.BrokerLoggerFilter;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class CompositeFilterTest extends QpidTestCase
+{
+    public void testDecideWithNoFilterAdded()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+        FilterReply reply = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply with no filter added", FilterReply.DENY, reply);
+    }
+
+    public void testDecideWithAcceptFilter()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+
+        compositeFilter.addFilter(createBrokerFilter(FilterReply.ACCEPT));
+
+        FilterReply reply = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply with ACCEPT filter added", FilterReply.ACCEPT, reply);
+    }
+
+    public void testDecideWithNeutralFilter()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+
+        compositeFilter.addFilter(createBrokerFilter(FilterReply.NEUTRAL));
+
+        FilterReply reply = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply with NEUTRAL filter added", FilterReply.DENY, reply);
+    }
+
+    public void testDecideWithFilterChain()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+
+        BrokerLoggerFilter brokerFilterNeutral = createBrokerFilter(FilterReply.NEUTRAL);
+        compositeFilter.addFilter(brokerFilterNeutral);
+
+        BrokerLoggerFilter brokerFilterDeny = createBrokerFilter(FilterReply.DENY);
+        compositeFilter.addFilter(brokerFilterDeny);
+
+        BrokerLoggerFilter brokerFilterAccept = createBrokerFilter(FilterReply.ACCEPT);
+        compositeFilter.addFilter(brokerFilterAccept);
+
+        FilterReply reply = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply", FilterReply.DENY, reply);
+
+        verify(brokerFilterNeutral.asFilter()).decide(any());
+        verify(brokerFilterDeny.asFilter()).decide(any());
+        verify(brokerFilterAccept.asFilter(), never()).decide(any());
+    }
+
+    public void testRemoveFilterFromChain()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+
+        BrokerLoggerFilter brokerFilterNeutral = createBrokerFilter(FilterReply.NEUTRAL, "neutral");
+        compositeFilter.addFilter(brokerFilterNeutral);
+
+        BrokerLoggerFilter brokerFilterDeny = createBrokerFilter(FilterReply.DENY, "deny");
+        compositeFilter.addFilter(brokerFilterDeny);
+
+        BrokerLoggerFilter brokerFilterAccept = createBrokerFilter(FilterReply.ACCEPT, "accept");
+        compositeFilter.addFilter(brokerFilterAccept);
+
+        FilterReply reply = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply", FilterReply.DENY, reply);
+
+        compositeFilter.removeFilter(brokerFilterDeny);
+
+        FilterReply reply2 = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply", FilterReply.ACCEPT, reply2);
+
+        verify(brokerFilterNeutral.asFilter(), times(2)).decide(any());
+        verify(brokerFilterDeny.asFilter()).decide(any());
+        verify(brokerFilterAccept.asFilter()).decide(any());
+    }
+
+    public void testAddFilter()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+
+        BrokerLoggerFilter brokerFilter = createBrokerFilter(FilterReply.ACCEPT, "accept");
+        compositeFilter.addFilter(brokerFilter);
+
+        verify(brokerFilter.asFilter()).setName("accept");
+    }
+
+    public void testAddFilters()
+    {
+        CompositeFilter compositeFilter = new CompositeFilter();
+
+        BrokerLoggerFilter brokerFilterNeutral = createBrokerFilter(FilterReply.NEUTRAL, "neutral");
+        BrokerLoggerFilter brokerFilterAccept = createBrokerFilter(FilterReply.ACCEPT, "accept");
+        BrokerLoggerFilter brokerFilterDeny = createBrokerFilter(FilterReply.DENY, "deny");
+
+        compositeFilter.addFilters(Arrays.asList(brokerFilterNeutral, brokerFilterAccept, brokerFilterDeny));
+
+        FilterReply reply = compositeFilter.decide(mock(ILoggingEvent.class));
+        assertEquals("Unexpected reply", FilterReply.ACCEPT, reply);
+
+        verify(brokerFilterNeutral.asFilter()).decide(any());
+        verify(brokerFilterAccept.asFilter()).decide(any());
+        verify(brokerFilterDeny.asFilter(), never()).decide(any());
+    }
+
+    private BrokerLoggerFilter createBrokerFilter(FilterReply decision)
+    {
+        return createBrokerFilter(decision, "UNNAMED");
+    }
+
+    private BrokerLoggerFilter createBrokerFilter(final FilterReply decision, String name)
+    {
+        BrokerLoggerFilter brokerFilter = mock(BrokerLoggerFilter.class);
+        when(brokerFilter.getName()).thenReturn(name);
+        Filter filter = mock(Filter.class);
+        when(filter.getName()).thenReturn(name);
+        when(filter.decide(any())).thenReturn(decision);
+        when(brokerFilter.asFilter()).thenReturn(filter);
+        return brokerFilter;
+    }
+}

Modified: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java (original)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java Tue Jun  9 11:14:07 2015
@@ -36,6 +36,8 @@ import org.apache.qpid.server.model.Acce
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.Binding;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerLogger;
+import org.apache.qpid.server.model.BrokerLoggerFilter;
 import org.apache.qpid.server.model.BrokerModel;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Consumer;
@@ -273,7 +275,7 @@ public class SecurityManagerTest extends
         when(exchange.getCategoryClass()).thenReturn(Exchange.class);
         when(exchange.getParent(VirtualHost.class)).thenReturn(vh);
 
-        assertCreateAuthorization( exchange, Operation.CREATE, ObjectType.EXCHANGE, expectedProperties, vh);
+        assertCreateAuthorization(exchange, Operation.CREATE, ObjectType.EXCHANGE, expectedProperties, vh);
     }
 
     public void testAuthoriseCreateQueue()
@@ -815,6 +817,32 @@ public class SecurityManagerTest extends
         assertDeleteAuthorization(binding, Operation.UNBIND, ObjectType.EXCHANGE, properties, exchange, queue);
     }
 
+    public void testAuthoriseBrokerLoggerOperations()
+    {
+        BrokerLogger mock = mock(BrokerLogger.class);
+        when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST");
+        when(mock.getCategoryClass()).thenReturn(BrokerLogger.class);
+        when(mock.getParent(Broker.class)).thenReturn(_broker);
+        assertBrokerChildCreateAuthorization(mock);
+
+        when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test");
+        assertBrokerChildUpdateAuthorization(mock);
+        assertBrokerChildDeleteAuthorization(mock);
+    }
+
+    public void testAuthoriseBrokerLoggerFilterOperations()
+    {
+        BrokerLoggerFilter mock = mock(BrokerLoggerFilter.class);
+        when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST");
+        when(mock.getCategoryClass()).thenReturn(BrokerLogger.class);
+        when(mock.getParent(Broker.class)).thenReturn(_broker);
+        assertBrokerChildCreateAuthorization(mock);
+
+        when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test");
+        assertBrokerChildUpdateAuthorization(mock);
+        assertBrokerChildDeleteAuthorization(mock);
+    }
+
     private VirtualHost getMockVirtualHost()
     {
         VirtualHost vh = mock(VirtualHost.class);

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java Tue Jun  9 11:14:07 2015
@@ -323,6 +323,9 @@ public class HttpManagement extends Abst
         addRestServlet(root, "binding", VirtualHostNode.class, VirtualHost.class, Exchange.class, Queue.class, Binding.class);
         addRestServlet(root, "session", VirtualHostNode.class, VirtualHost.class, Connection.class, Session.class);
 
+        addRestServlet(root, "brokerlogger", BrokerLogger.class);
+        addRestServlet(root, "brokerloggerfilter", BrokerLogger.class, BrokerLoggerFilter.class);
+
         ServletHolder apiDocsServlet = new ServletHolder(new ApiDocsServlet(getModel(), Collections.<String>emptyList()));
         root.addServlet(apiDocsServlet, "/apidocs");
         root.addServlet(apiDocsServlet, "/apidocs/");

Modified: qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java?rev=1684380&r1=1684379&r2=1684380&view=diff
==============================================================================
--- qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java (original)
+++ qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java Tue Jun  9 11:14:07 2015
@@ -29,7 +29,9 @@ import java.util.Map;
 
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.qpid.server.logging.BrokerNameAndLevelFilter;
 import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet;
+import org.apache.qpid.server.model.ConfiguredObject;
 import org.codehaus.jackson.JsonGenerationException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.apache.qpid.server.management.plugin.HttpManagement;
@@ -832,6 +834,74 @@ public class BrokerACLTest extends QpidR
                 details.get(HttpManagement.HTTPS_SASL_AUTHENTICATION_ENABLED));
     }
 
+    /* === Broker Logger Filters === */
+
+    public void testCreateBrokerLoggerFilterAllowedDenied() throws Exception
+    {
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/1", "GET", HttpServletResponse.SC_OK);
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(BrokerNameAndLevelFilter.NAME, "2");
+        attributes.put(ConfiguredObject.TYPE, BrokerNameAndLevelFilter.TYPE);
+        attributes.put(BrokerNameAndLevelFilter.LEVEL, "DEBUG");
+
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory", "PUT", attributes, HttpServletResponse.SC_CREATED);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/2", "GET", HttpServletResponse.SC_OK);
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+        attributes.put(BrokerNameAndLevelFilter.NAME, "3");
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory", "PUT", attributes, HttpServletResponse.SC_FORBIDDEN);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/3", "GET", HttpServletResponse.SC_NOT_FOUND);
+    }
+
+    public void testUpdateBrokerLoggerFilterAllowedDenied() throws Exception
+    {
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+        Map<String,Object> result = getRestTestHelper().getJsonAsSingletonList("brokerloggerfilter/memory/1");
+        assertEquals("Log level was not as expected", "INFO", result.get(BrokerNameAndLevelFilter.LEVEL));
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(BrokerNameAndLevelFilter.NAME, "1");
+        attributes.put(ConfiguredObject.TYPE, BrokerNameAndLevelFilter.TYPE);
+        attributes.put(BrokerNameAndLevelFilter.LEVEL, "DEBUG");
+
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/1", "PUT", attributes, HttpServletResponse.SC_OK);
+        Map<String,Object> resultAfterUpdate = getRestTestHelper().getJsonAsSingletonList("brokerloggerfilter/memory/1");
+        assertEquals("Log level was not changed", "DEBUG", resultAfterUpdate.get(BrokerNameAndLevelFilter.LEVEL));
+
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+        attributes.put(BrokerNameAndLevelFilter.LEVEL, "INFO");
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/1", "PUT", attributes, HttpServletResponse.SC_FORBIDDEN);
+
+        Map<String,Object> resultAfterDeniedUpdate = getRestTestHelper().getJsonAsSingletonList("brokerloggerfilter/memory/1");
+        assertEquals("Log level was changed by not allowed user", "DEBUG", resultAfterDeniedUpdate.get(BrokerNameAndLevelFilter.LEVEL));
+    }
+
+    public void testDeleteBrokerLoggerFilterAllowedDenied() throws Exception
+    {
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(BrokerNameAndLevelFilter.NAME, "2");
+        attributes.put(ConfiguredObject.TYPE, BrokerNameAndLevelFilter.TYPE);
+        attributes.put(BrokerNameAndLevelFilter.LEVEL, "DEBUG");
+
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory", "PUT", attributes, HttpServletResponse.SC_CREATED);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/2", "GET", HttpServletResponse.SC_OK);
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/2", "DELETE", null, HttpServletResponse.SC_FORBIDDEN);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/2", "GET", HttpServletResponse.SC_OK);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/2", "DELETE", null, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("brokerloggerfilter/memory/2", "GET", HttpServletResponse.SC_NOT_FOUND);
+    }
+
     /* === Utility Methods === */
 
     private int createPort(String portName) throws Exception



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org