You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by lq...@apache.org on 2016/11/22 14:02:49 UTC

svn commit: r1770842 - in /qpid/java/trunk/broker-plugins/logging-logback/src: main/java/org/apache/qpid/server/logging/logback/ test/java/org/apache/qpid/server/logging/logback/

Author: lquack
Date: Tue Nov 22 14:02:49 2016
New Revision: 1770842

URL: http://svn.apache.org/viewvc?rev=1770842&view=rev
Log:
QPID-7539: [Java Broker] Support connection and user level logging

Added:
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractPredicateLogInclusionRule.java
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRule.java
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRuleImpl.java
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicate.java
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/PredicateAndLoggerNameAndLevelFilter.java
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRule.java
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRuleImpl.java
    qpid/java/trunk/broker-plugins/logging-logback/src/test/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicateTest.java
Modified:
    qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/LoggerNameAndLevelFilter.java

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractPredicateLogInclusionRule.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractPredicateLogInclusionRule.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractPredicateLogInclusionRule.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractPredicateLogInclusionRule.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.util.Map;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.Filter;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.apache.qpid.server.logging.LogLevel;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+
+public abstract class AbstractPredicateLogInclusionRule<X extends AbstractPredicateLogInclusionRule<X>> extends AbstractConfiguredObject<X>
+{
+    @ManagedAttributeField
+    private String _loggerName;
+    @ManagedAttributeField(afterSet = "logLevelAfterSet")
+    private LogLevel _level;
+
+    private PredicateAndLoggerNameAndLevelFilter _filter;
+
+    protected AbstractPredicateLogInclusionRule(final Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> parents,
+                                                Map<String, Object> attributes)
+    {
+        super(parents, attributes);
+    }
+
+    @Override
+    protected void postResolve()
+    {
+        super.postResolve();
+        _filter = new PredicateAndLoggerNameAndLevelFilter(getLoggerName(), Level.toLevel(getLevel().name()), getPredicate());
+    }
+
+    protected abstract PredicateAndLoggerNameAndLevelFilter.Predicate getPredicate();
+
+
+    public String getLoggerName()
+    {
+        return _loggerName;
+    }
+
+    public LogLevel getLevel()
+    {
+        return _level;
+    }
+
+    @SuppressWarnings("unused")
+    private void logLevelAfterSet()
+    {
+        if (_filter != null)
+        {
+            _filter.setLevel(Level.toLevel(getLevel().name()));
+            QpidLoggerTurboFilter.filterChangedOnRootContext(_filter);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public Filter<ILoggingEvent> asFilter()
+    {
+        return _filter;
+    }
+
+    @SuppressWarnings("unused")
+    @StateTransition( currentState = { State.ACTIVE, State.ERRORED, State.UNINITIALIZED }, desiredState = State.DELETED )
+    private ListenableFuture<Void> doDelete()
+    {
+        return doAfterAlways(closeAsync(), new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                deleted();
+                QpidLoggerTurboFilter.filterRemovedFromRootContext(_filter);
+                setState(State.DELETED);
+
+            }
+        });
+    }
+
+    @SuppressWarnings("unused")
+    @StateTransition( currentState = { State.ERRORED, State.UNINITIALIZED }, desiredState = State.ACTIVE )
+    private ListenableFuture<Void> doActivate()
+    {
+        setState(State.ACTIVE);
+        QpidLoggerTurboFilter.filterAddedToRootContext(_filter);
+        return Futures.immediateFuture(null);
+    }
+
+}

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRule.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRule.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRule.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRule.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.qpid.server.logging.LogLevel;
+import org.apache.qpid.server.model.BrokerLogInclusionRule;
+import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedObject;
+
+@ManagedObject( category = false, type = BrokerUserOrConnectionLogInclusionRule.TYPE)
+public interface BrokerUserOrConnectionLogInclusionRule<X extends BrokerUserOrConnectionLogInclusionRule<X>>
+        extends BrokerLogInclusionRule<X>, LogBackLogInclusionRule
+{
+
+    String TYPE = "UserOrConnectionSpecific";
+    String LOGGER_NAME = "loggerName";
+    String LEVEL = "level";
+
+    @ManagedAttribute( defaultValue = "ROOT", immutable = true )
+    String getLoggerName();
+
+    @ManagedAttribute(defaultValue = "INFO", validValues = {"org.apache.qpid.server.logging.LogLevel#validValues()"})
+    LogLevel getLevel();
+
+    @ManagedAttribute( defaultValue = ".*" )
+    String getConnectionName();
+
+    @ManagedAttribute( defaultValue = ".*" )
+    String getRemoteContainerId();
+
+    @ManagedAttribute( defaultValue = ".*" )
+    String getUsername();
+}

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRuleImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRuleImpl.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRuleImpl.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/BrokerUserOrConnectionLogInclusionRuleImpl.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,112 @@
+/*
+ *
+ * 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.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+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;
+
+class BrokerUserOrConnectionLogInclusionRuleImpl
+        extends AbstractPredicateLogInclusionRule<BrokerUserOrConnectionLogInclusionRuleImpl>
+        implements BrokerUserOrConnectionLogInclusionRule<BrokerUserOrConnectionLogInclusionRuleImpl>
+{
+
+    @ManagedAttributeField(afterSet = "afterAttributeSet")
+    private String _connectionName;
+    @ManagedAttributeField(afterSet = "afterAttributeSet")
+    private String _remoteContainerId;
+    @ManagedAttributeField(afterSet = "afterAttributeSet")
+    private String _username;
+
+    private ConnectionAndUserPredicate _predicate = new ConnectionAndUserPredicate();
+
+    @ManagedObjectFactoryConstructor
+    BrokerUserOrConnectionLogInclusionRuleImpl(final Map<String, Object> attributes,
+                                               BrokerLogger<?> logger)
+    {
+        super(parentsMap(logger), attributes);
+    }
+
+    @Override
+    protected void validateChange(ConfiguredObject<?> proxyForValidation, Set<String> changedAttributes)
+    {
+        super.validateChange(proxyForValidation, changedAttributes);
+        BrokerUserOrConnectionLogInclusionRule proxy =
+                (BrokerUserOrConnectionLogInclusionRule) proxyForValidation;
+        if (changedAttributes.contains(LOGGER_NAME) &&
+            ((getLoggerName() != null && !getLoggerName().equals(proxy.getLoggerName())) ||
+             (getLoggerName() == null && proxy.getLoggerName() != null)))
+        {
+            throw new IllegalConfigurationException("Attribute '" + LOGGER_NAME + " cannot be changed");
+        }
+    }
+
+    @Override
+    protected void postResolve()
+    {
+        updatePredicate();
+        super.postResolve();
+    }
+
+    @Override
+    protected PredicateAndLoggerNameAndLevelFilter.Predicate getPredicate()
+    {
+        return _predicate;
+    }
+
+    @SuppressWarnings("unused")
+    @Override
+    public String getConnectionName()
+    {
+        return _connectionName;
+    }
+
+    @SuppressWarnings("unused")
+    public String getRemoteContainerId()
+    {
+        return _remoteContainerId;
+    }
+
+    @SuppressWarnings("unused")
+    @Override
+    public String getUsername()
+    {
+        return _username;
+    }
+
+    @SuppressWarnings("unused")
+    private void afterAttributeSet()
+    {
+        updatePredicate();
+    }
+
+    private void updatePredicate()
+    {
+        _predicate.setRemoteContainerIdPattern(_remoteContainerId);
+        _predicate.setConnectionNamePattern(_connectionName);
+        _predicate.setUsernamePattern(_username);
+    }
+}

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicate.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicate.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicate.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicate.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,110 @@
+/*
+ * 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.security.AccessController;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.security.auth.Subject;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+
+import org.apache.qpid.server.connection.ConnectionPrincipal;
+import org.apache.qpid.server.model.preferences.GenericPrincipal;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.auth.SocketConnectionPrincipal;
+
+class ConnectionAndUserPredicate implements PredicateAndLoggerNameAndLevelFilter.Predicate
+{
+    private static final Pattern MATCH_ALL = Pattern.compile(".*");
+    private Pattern _usernamePattern = MATCH_ALL;
+    private Pattern _connectionNamePattern = MATCH_ALL;
+    private Pattern _remoteContainerIdPattern = MATCH_ALL;
+
+    @Override
+    public boolean evaluate(final ILoggingEvent event)
+    {
+        String userPrincipalString = "";
+        String connectionString = "";
+        String remoteContainerName = "";
+
+        Subject subject = Subject.getSubject(AccessController.getContext());
+        Set<SocketConnectionPrincipal> connectionPrincipals = subject.getPrincipals(SocketConnectionPrincipal.class);
+        Set<AuthenticatedPrincipal> userPrincipals = subject.getPrincipals(AuthenticatedPrincipal.class);
+        if (!connectionPrincipals.isEmpty())
+        {
+            SocketConnectionPrincipal socketConnectionPrincipal = connectionPrincipals.iterator().next();
+            connectionString = socketConnectionPrincipal.getName();
+            if (socketConnectionPrincipal instanceof ConnectionPrincipal)
+            {
+                remoteContainerName = ((ConnectionPrincipal) socketConnectionPrincipal).getConnection().getRemoteContainerName();
+                if (remoteContainerName == null)
+                {
+                    remoteContainerName = "";
+                }
+            }
+        }
+        if (!userPrincipals.isEmpty())
+        {
+            userPrincipalString = new GenericPrincipal(userPrincipals.iterator().next()).toExternalForm();
+        }
+
+        return _usernamePattern.matcher(userPrincipalString).matches()
+               && _connectionNamePattern.matcher(connectionString).matches()
+               && _remoteContainerIdPattern.matcher(remoteContainerName).matches();
+    }
+
+    void setConnectionNamePattern(final String connectionName)
+    {
+        if (connectionName != null)
+        {
+            _connectionNamePattern = Pattern.compile(connectionName);
+        }
+        else
+        {
+            _connectionNamePattern = MATCH_ALL;
+        }
+    }
+
+    void setRemoteContainerIdPattern(final String remoteContainerId)
+    {
+        if (remoteContainerId != null)
+        {
+            _remoteContainerIdPattern = Pattern.compile(remoteContainerId);
+        }
+        else
+        {
+            _remoteContainerIdPattern = MATCH_ALL;
+        }
+    }
+
+    void setUsernamePattern(final String usernamePattern)
+    {
+        if (usernamePattern != null)
+        {
+            _usernamePattern = Pattern.compile(usernamePattern);
+        }
+        else
+        {
+            _usernamePattern = MATCH_ALL;
+        }
+    }
+}

Modified: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/LoggerNameAndLevelFilter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/LoggerNameAndLevelFilter.java?rev=1770842&r1=1770841&r2=1770842&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/LoggerNameAndLevelFilter.java (original)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/LoggerNameAndLevelFilter.java Tue Nov 22 14:02:49 2016
@@ -61,7 +61,7 @@ public class LoggerNameAndLevelFilter ex
         return _loggerName;
     }
 
-    private Filter<ILoggingEvent> createFilter(final String loggerName)
+    protected Filter<ILoggingEvent> createFilter(final String loggerName)
     {
         if(loggerName == null || "".equals(loggerName) || Logger.ROOT_LOGGER_NAME.equals(loggerName))
         {

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/PredicateAndLoggerNameAndLevelFilter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/PredicateAndLoggerNameAndLevelFilter.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/PredicateAndLoggerNameAndLevelFilter.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/PredicateAndLoggerNameAndLevelFilter.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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 ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.FilterReply;
+
+class PredicateAndLoggerNameAndLevelFilter extends LoggerNameAndLevelFilter
+{
+    private final Filter<ILoggingEvent> _filter;
+    private final Predicate _predicate;
+
+    interface Predicate
+    {
+        boolean evaluate(final ILoggingEvent event);
+    }
+
+    PredicateAndLoggerNameAndLevelFilter(String loggerName, Level level, final Predicate predicate)
+    {
+        super(loggerName, level);
+        _filter = createFilter(loggerName);
+        _predicate = predicate;
+    }
+
+    @Override
+    public FilterReply decide(ILoggingEvent event)
+    {
+        return _filter.decide(event);
+    }
+
+    protected Filter<ILoggingEvent> createFilter(final String loggerName)
+    {
+        final Filter<ILoggingEvent> filter = super.createFilter(loggerName);
+        return new Filter<ILoggingEvent>()
+        {
+            @Override
+            public FilterReply decide(final ILoggingEvent event)
+            {
+                final FilterReply result = filter.decide(event);
+                if (result == FilterReply.ACCEPT)
+                {
+                    if (_predicate.evaluate(event))
+                    {
+                        return FilterReply.ACCEPT;
+                    }
+                    else
+                    {
+                        return FilterReply.NEUTRAL;
+                    }
+                }
+                else
+                {
+                    return result;
+                }
+            }
+        };
+    }
+}

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRule.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRule.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRule.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRule.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.qpid.server.logging.LogLevel;
+import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.VirtualHostLogInclusionRule;
+
+@ManagedObject( category = false, type = VirtualHostUserOrConnectionLogInclusionRule.TYPE)
+public interface VirtualHostUserOrConnectionLogInclusionRule<X extends VirtualHostUserOrConnectionLogInclusionRule<X>>
+        extends VirtualHostLogInclusionRule<X>, LogBackLogInclusionRule
+{
+
+    String TYPE = "UserOrConnectionSpecific";
+    String LOGGER_NAME = "loggerName";
+    String LEVEL = "level";
+
+    @ManagedAttribute( defaultValue = "ROOT", immutable = true )
+    String getLoggerName();
+
+    @ManagedAttribute(defaultValue = "INFO", validValues = {"org.apache.qpid.server.logging.LogLevel#validValues()"})
+    LogLevel getLevel();
+
+    @ManagedAttribute( defaultValue = ".*" )
+    String getConnectionName();
+
+    @ManagedAttribute( defaultValue = ".*" )
+    String getRemoteContainerId();
+
+    @ManagedAttribute( defaultValue = ".*" )
+    String getUsername();
+}

Added: qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRuleImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRuleImpl.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRuleImpl.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/VirtualHostUserOrConnectionLogInclusionRuleImpl.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+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;
+
+class VirtualHostUserOrConnectionLogInclusionRuleImpl
+        extends AbstractPredicateLogInclusionRule<VirtualHostUserOrConnectionLogInclusionRuleImpl>
+        implements VirtualHostUserOrConnectionLogInclusionRule<VirtualHostUserOrConnectionLogInclusionRuleImpl>
+{
+
+    @ManagedAttributeField(afterSet = "afterAttributeSet")
+    private String _connectionName;
+    @ManagedAttributeField(afterSet = "afterAttributeSet")
+    private String _remoteContainerId;
+    @ManagedAttributeField(afterSet = "afterAttributeSet")
+    private String _username;
+
+    private ConnectionAndUserPredicate _predicate = new ConnectionAndUserPredicate();
+
+    @ManagedObjectFactoryConstructor
+    protected VirtualHostUserOrConnectionLogInclusionRuleImpl(final Map<String, Object> attributes,
+                                                              BrokerLogger<?> logger)
+    {
+        super(parentsMap(logger), attributes);
+    }
+
+    @Override
+    protected void validateChange(ConfiguredObject<?> proxyForValidation, Set<String> changedAttributes)
+    {
+        super.validateChange(proxyForValidation, changedAttributes);
+        BrokerUserOrConnectionLogInclusionRule proxy =
+                (BrokerUserOrConnectionLogInclusionRule) proxyForValidation;
+        if (changedAttributes.contains(LOGGER_NAME) &&
+            ((getLoggerName() != null && !getLoggerName().equals(proxy.getLoggerName())) ||
+             (getLoggerName() == null && proxy.getLoggerName() != null)))
+        {
+            throw new IllegalConfigurationException("Attribute '" + LOGGER_NAME + " cannot be changed");
+        }
+    }
+
+    @Override
+    protected void postResolve()
+    {
+        updatePredicate();
+        super.postResolve();
+    }
+
+    @Override
+    protected PredicateAndLoggerNameAndLevelFilter.Predicate getPredicate()
+    {
+        return _predicate;
+    }
+
+    @SuppressWarnings("unused")
+    @Override
+    public String getConnectionName()
+    {
+        return _connectionName;
+    }
+
+    @SuppressWarnings("unused")
+    @Override
+    public String getRemoteContainerId()
+    {
+        return _remoteContainerId;
+    }
+
+    @SuppressWarnings("unused")
+    @Override
+    public String getUsername()
+    {
+        return _username;
+    }
+
+    @SuppressWarnings("unused")
+    private void afterAttributeSet()
+    {
+        updatePredicate();
+    }
+
+    private void updatePredicate()
+    {
+        _predicate.setRemoteContainerIdPattern(_remoteContainerId);
+        _predicate.setConnectionNamePattern(_connectionName);
+        _predicate.setUsernamePattern(_username);
+    }
+}

Added: qpid/java/trunk/broker-plugins/logging-logback/src/test/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicateTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/logging-logback/src/test/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicateTest.java?rev=1770842&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/logging-logback/src/test/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicateTest.java (added)
+++ qpid/java/trunk/broker-plugins/logging-logback/src/test/java/org/apache/qpid/server/logging/logback/ConnectionAndUserPredicateTest.java Tue Nov 22 14:02:49 2016
@@ -0,0 +1,179 @@
+/*
+ *
+ * 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.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashSet;
+
+import javax.security.auth.Subject;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+
+import org.apache.qpid.server.connection.ConnectionPrincipal;
+import org.apache.qpid.server.model.preferences.GenericPrincipal;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.auth.ManagementConnectionPrincipal;
+import org.apache.qpid.server.transport.AMQPConnection;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ConnectionAndUserPredicateTest extends QpidTestCase
+{
+    private static final String TEST_USER = "testUser@foo('bar')";
+    private ConnectionAndUserPredicate _predicate;
+    private Subject _subject;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _predicate = new ConnectionAndUserPredicate();
+        _subject = new Subject(false,
+                               new HashSet<>(Collections.singleton(new AuthenticatedPrincipal(new GenericPrincipal(
+                                       TEST_USER)))),
+                               Collections.emptySet(),
+                               Collections.emptySet());
+    }
+
+
+    public void testEvaluateUsername()
+    {
+        _predicate.setUsernamePattern("testUser.*");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertTrue("predicate unexpectedly did not match", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+        _predicate.setUsernamePattern("nonmatching.*");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertFalse("predicate unexpectedly matched", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+    }
+
+    public void testEvaluateRemoteContainerIdAndUsername()
+    {
+        AMQPConnection connection = mock(AMQPConnection.class);
+        when(connection.getRemoteAddressString()).thenReturn("foo:1234");
+        when(connection.getRemoteContainerName()).thenReturn("TestClientId");
+        _subject.getPrincipals().add(new ConnectionPrincipal(connection));
+        _predicate.setRemoteContainerIdPattern(".*Client.*");
+        _predicate.setUsernamePattern("testUser.*");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertTrue("predicate unexpectedly did not match", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+        _predicate.setRemoteContainerIdPattern(".*noMatchingClient.*");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertFalse("predicate unexpectedly matched", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+        _predicate.setRemoteContainerIdPattern(".*Client.*");
+        _predicate.setUsernamePattern("noMatchingUsername.*");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertFalse("predicate unexpectedly matched", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+    }
+
+
+    public void testEvaluateConnectionNameForAmqp()
+    {
+        AMQPConnection connection = mock(AMQPConnection.class);
+        when(connection.getRemoteAddressString()).thenReturn("foo:1234");
+        when(connection.getRemoteContainerName()).thenReturn(null);
+        _subject.getPrincipals().add(new ConnectionPrincipal(connection));
+        _predicate.setConnectionNamePattern(".*:1234");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertTrue("predicate unexpectedly did not match", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+        _predicate.setConnectionNamePattern(".*:4321");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertFalse("predicate unexpectedly matched", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+    }
+
+    public void testEvaluateConnectionNameForHttp()
+    {
+        ManagementConnectionPrincipal principal = mock(ManagementConnectionPrincipal.class);
+        when(principal.getName()).thenReturn("foo:1234");
+        _subject.getPrincipals().add(principal);
+        _predicate.setConnectionNamePattern(".*:1234");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertTrue("predicate unexpectedly did not match", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+        _predicate.setConnectionNamePattern(".*:4321");
+        Subject.doAs(_subject, new PrivilegedAction<Void>()
+        {
+            @Override
+            public Void run()
+            {
+                assertFalse("predicate unexpectedly matched", _predicate.evaluate(mock(ILoggingEvent.class)));
+                return null;
+            }
+        });
+    }
+}




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