You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by el...@apache.org on 2009/08/05 14:08:59 UTC
svn commit: r801159 [1/2] - in
/mina/trunk/core/src/main/java/org/apache/mina:
core/future/DefaultIoFuture.java filter/logging/MdcInjectionFilter.java
filter/statistic/ProfilerTimerFilter.java filter/util/CommonEventFilter.java
Author: elecharny
Date: Wed Aug 5 12:08:58 2009
New Revision: 801159
URL: http://svn.apache.org/viewvc?rev=801159&view=rev
Log:
Removed ^M from those files
Modified:
mina/trunk/core/src/main/java/org/apache/mina/core/future/DefaultIoFuture.java
mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java
mina/trunk/core/src/main/java/org/apache/mina/filter/statistic/ProfilerTimerFilter.java
mina/trunk/core/src/main/java/org/apache/mina/filter/util/CommonEventFilter.java
Modified: mina/trunk/core/src/main/java/org/apache/mina/core/future/DefaultIoFuture.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/core/future/DefaultIoFuture.java?rev=801159&r1=801158&r2=801159&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/core/future/DefaultIoFuture.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/core/future/DefaultIoFuture.java Wed Aug 5 12:08:58 2009
@@ -1,382 +1,382 @@
-/*
- * 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.mina.core.future;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.mina.core.polling.AbstractPollingIoProcessor;
-import org.apache.mina.core.service.IoProcessor;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.util.ExceptionMonitor;
-
-
-/**
- * A default implementation of {@link IoFuture} associated with
- * an {@link IoSession}.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class DefaultIoFuture implements IoFuture {
-
- /** A number of seconds to wait between two deadlock controls ( 5 seconds ) */
- private static final long DEAD_LOCK_CHECK_INTERVAL = 5000L;
-
- /** The associated session */
- private final IoSession session;
-
- /** A lock used by the wait() method */
- private final Object lock;
- private IoFutureListener<?> firstListener;
- private List<IoFutureListener<?>> otherListeners;
- private Object result;
- private boolean ready;
- private int waiters;
-
- /**
- * Creates a new instance associated with an {@link IoSession}.
- *
- * @param session an {@link IoSession} which is associated with this future
- */
- public DefaultIoFuture(IoSession session) {
- this.session = session;
- this.lock = this;
- }
-
- /**
- * {@inheritDoc}
- */
- public IoSession getSession() {
- return session;
- }
-
- /**
- * @deprecated Replaced with {@link #awaitUninterruptibly()}.
- */
- @Deprecated
- public void join() {
- awaitUninterruptibly();
- }
-
- /**
- * @deprecated Replaced with {@link #awaitUninterruptibly(long)}.
- */
- @Deprecated
- public boolean join(long timeoutMillis) {
- return awaitUninterruptibly(timeoutMillis);
- }
-
- /**
- * {@inheritDoc}
- */
- public IoFuture await() throws InterruptedException {
- synchronized (lock) {
- while (!ready) {
- waiters++;
- try {
- // Wait for a notify, or if no notify is called,
- // assume that we have a deadlock and exit the
- // loop to check for a potential deadlock.
- lock.wait(DEAD_LOCK_CHECK_INTERVAL);
- } finally {
- waiters--;
- if (!ready) {
- checkDeadLock();
- }
- }
- }
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean await(long timeout, TimeUnit unit)
- throws InterruptedException {
- return await(unit.toMillis(timeout));
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean await(long timeoutMillis) throws InterruptedException {
- return await0(timeoutMillis, true);
- }
-
- /**
- * {@inheritDoc}
- */
- public IoFuture awaitUninterruptibly() {
- try {
- await0(Long.MAX_VALUE, false);
- } catch ( InterruptedException ie) {
- // Do nothing : this catch is just mandatory by contract
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
- return awaitUninterruptibly(unit.toMillis(timeout));
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean awaitUninterruptibly(long timeoutMillis) {
- try {
- return await0(timeoutMillis, false);
- } catch (InterruptedException e) {
- throw new InternalError();
- }
- }
-
- /**
- * Wait for the Future to be ready. If the requested delay is 0 or
- * negative, this method immediately returns the value of the
- * 'ready' flag.
- * Every 5 second, the wait will be suspended to be able to check if
- * there is a deadlock or not.
- *
- * @param timeoutMillis The delay we will wait for the Future to be ready
- * @param interruptable Tells if the wait can be interrupted or not
- * @return <code>true</code> if the Future is ready
- * @throws InterruptedException If the thread has been interrupted
- * when it's not allowed.
- */
- private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException {
- long endTime = System.currentTimeMillis() + timeoutMillis;
-
- if (endTime < 0) {
- endTime = Long.MAX_VALUE;
- }
-
- synchronized (lock) {
- if (ready) {
- return ready;
- } else if (timeoutMillis <= 0) {
- return ready;
- }
-
- waiters++;
-
- try {
- for (;;) {
- try {
- long timeOut = Math.min(timeoutMillis, DEAD_LOCK_CHECK_INTERVAL);
- lock.wait(timeOut);
- } catch (InterruptedException e) {
- if (interruptable) {
- throw e;
- }
- }
-
- if (ready) {
- return true;
- }
-
- if (endTime < System.currentTimeMillis()) {
- return ready;
- }
- }
- } finally {
- waiters--;
- if (!ready) {
- checkDeadLock();
- }
- }
- }
- }
-
-
- /**
- *
- * TODO checkDeadLock.
- *
- */
- private void checkDeadLock() {
- // Only read / write / connect / write future can cause dead lock.
- if (!(this instanceof CloseFuture || this instanceof WriteFuture ||
- this instanceof ReadFuture || this instanceof ConnectFuture)) {
- return;
- }
-
- // Get the current thread stackTrace.
- // Using Thread.currentThread().getStackTrace() is the best solution,
- // even if slightly less efficient than doing a new Exception().getStackTrace(),
- // as internally, it does exactly the same thing. The advantage of using
- // this solution is that we may benefit some improvement with some
- // future versions of Java.
- StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
-
- // Simple and quick check.
- for (StackTraceElement s: stackTrace) {
- if (AbstractPollingIoProcessor.class.getName().equals(s.getClassName())) {
- IllegalStateException e = new IllegalStateException( "t" );
- e.getStackTrace();
- throw new IllegalStateException(
- "DEAD LOCK: " + IoFuture.class.getSimpleName() +
- ".await() was invoked from an I/O processor thread. " +
- "Please use " + IoFutureListener.class.getSimpleName() +
- " or configure a proper thread model alternatively.");
- }
- }
-
- // And then more precisely.
- for (StackTraceElement s: stackTrace) {
- try {
- Class<?> cls = DefaultIoFuture.class.getClassLoader().loadClass(s.getClassName());
- if (IoProcessor.class.isAssignableFrom(cls)) {
- throw new IllegalStateException(
- "DEAD LOCK: " + IoFuture.class.getSimpleName() +
- ".await() was invoked from an I/O processor thread. " +
- "Please use " + IoFutureListener.class.getSimpleName() +
- " or configure a proper thread model alternatively.");
- }
- } catch (Exception cnfe) {
- // Ignore
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isDone() {
- synchronized (lock) {
- return ready;
- }
- }
-
- /**
- * Sets the result of the asynchronous operation, and mark it as finished.
- */
- public void setValue(Object newValue) {
- synchronized (lock) {
- // Allow only once.
- if (ready) {
- return;
- }
-
- result = newValue;
- ready = true;
- if (waiters > 0) {
- lock.notifyAll();
- }
- }
-
- notifyListeners();
- }
-
- /**
- * Returns the result of the asynchronous operation.
- */
- protected Object getValue() {
- synchronized (lock) {
- return result;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public IoFuture addListener(IoFutureListener<?> listener) {
- if (listener == null) {
- throw new NullPointerException("listener");
- }
-
- boolean notifyNow = false;
- synchronized (lock) {
- if (ready) {
- notifyNow = true;
- } else {
- if (firstListener == null) {
- firstListener = listener;
- } else {
- if (otherListeners == null) {
- otherListeners = new ArrayList<IoFutureListener<?>>(1);
- }
- otherListeners.add(listener);
- }
- }
- }
-
- if (notifyNow) {
- notifyListener(listener);
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- public IoFuture removeListener(IoFutureListener<?> listener) {
- if (listener == null) {
- throw new NullPointerException("listener");
- }
-
- synchronized (lock) {
- if (!ready) {
- if (listener == firstListener) {
- if (otherListeners != null && !otherListeners.isEmpty()) {
- firstListener = otherListeners.remove(0);
- } else {
- firstListener = null;
- }
- } else if (otherListeners != null) {
- otherListeners.remove(listener);
- }
- }
- }
-
- return this;
- }
-
- private void notifyListeners() {
- // There won't be any visibility problem or concurrent modification
- // because 'ready' flag will be checked against both addListener and
- // removeListener calls.
- if (firstListener != null) {
- notifyListener(firstListener);
- firstListener = null;
-
- if (otherListeners != null) {
- for (IoFutureListener<?> l : otherListeners) {
- notifyListener(l);
- }
- otherListeners = null;
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- private void notifyListener(IoFutureListener l) {
- try {
- l.operationComplete(this);
- } catch (Throwable t) {
- ExceptionMonitor.getInstance().exceptionCaught(t);
- }
- }
-}
+/*
+ * 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.mina.core.future;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.mina.core.polling.AbstractPollingIoProcessor;
+import org.apache.mina.core.service.IoProcessor;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.util.ExceptionMonitor;
+
+
+/**
+ * A default implementation of {@link IoFuture} associated with
+ * an {@link IoSession}.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class DefaultIoFuture implements IoFuture {
+
+ /** A number of seconds to wait between two deadlock controls ( 5 seconds ) */
+ private static final long DEAD_LOCK_CHECK_INTERVAL = 5000L;
+
+ /** The associated session */
+ private final IoSession session;
+
+ /** A lock used by the wait() method */
+ private final Object lock;
+ private IoFutureListener<?> firstListener;
+ private List<IoFutureListener<?>> otherListeners;
+ private Object result;
+ private boolean ready;
+ private int waiters;
+
+ /**
+ * Creates a new instance associated with an {@link IoSession}.
+ *
+ * @param session an {@link IoSession} which is associated with this future
+ */
+ public DefaultIoFuture(IoSession session) {
+ this.session = session;
+ this.lock = this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IoSession getSession() {
+ return session;
+ }
+
+ /**
+ * @deprecated Replaced with {@link #awaitUninterruptibly()}.
+ */
+ @Deprecated
+ public void join() {
+ awaitUninterruptibly();
+ }
+
+ /**
+ * @deprecated Replaced with {@link #awaitUninterruptibly(long)}.
+ */
+ @Deprecated
+ public boolean join(long timeoutMillis) {
+ return awaitUninterruptibly(timeoutMillis);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IoFuture await() throws InterruptedException {
+ synchronized (lock) {
+ while (!ready) {
+ waiters++;
+ try {
+ // Wait for a notify, or if no notify is called,
+ // assume that we have a deadlock and exit the
+ // loop to check for a potential deadlock.
+ lock.wait(DEAD_LOCK_CHECK_INTERVAL);
+ } finally {
+ waiters--;
+ if (!ready) {
+ checkDeadLock();
+ }
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean await(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return await(unit.toMillis(timeout));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean await(long timeoutMillis) throws InterruptedException {
+ return await0(timeoutMillis, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IoFuture awaitUninterruptibly() {
+ try {
+ await0(Long.MAX_VALUE, false);
+ } catch ( InterruptedException ie) {
+ // Do nothing : this catch is just mandatory by contract
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
+ return awaitUninterruptibly(unit.toMillis(timeout));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean awaitUninterruptibly(long timeoutMillis) {
+ try {
+ return await0(timeoutMillis, false);
+ } catch (InterruptedException e) {
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * Wait for the Future to be ready. If the requested delay is 0 or
+ * negative, this method immediately returns the value of the
+ * 'ready' flag.
+ * Every 5 second, the wait will be suspended to be able to check if
+ * there is a deadlock or not.
+ *
+ * @param timeoutMillis The delay we will wait for the Future to be ready
+ * @param interruptable Tells if the wait can be interrupted or not
+ * @return <code>true</code> if the Future is ready
+ * @throws InterruptedException If the thread has been interrupted
+ * when it's not allowed.
+ */
+ private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException {
+ long endTime = System.currentTimeMillis() + timeoutMillis;
+
+ if (endTime < 0) {
+ endTime = Long.MAX_VALUE;
+ }
+
+ synchronized (lock) {
+ if (ready) {
+ return ready;
+ } else if (timeoutMillis <= 0) {
+ return ready;
+ }
+
+ waiters++;
+
+ try {
+ for (;;) {
+ try {
+ long timeOut = Math.min(timeoutMillis, DEAD_LOCK_CHECK_INTERVAL);
+ lock.wait(timeOut);
+ } catch (InterruptedException e) {
+ if (interruptable) {
+ throw e;
+ }
+ }
+
+ if (ready) {
+ return true;
+ }
+
+ if (endTime < System.currentTimeMillis()) {
+ return ready;
+ }
+ }
+ } finally {
+ waiters--;
+ if (!ready) {
+ checkDeadLock();
+ }
+ }
+ }
+ }
+
+
+ /**
+ *
+ * TODO checkDeadLock.
+ *
+ */
+ private void checkDeadLock() {
+ // Only read / write / connect / write future can cause dead lock.
+ if (!(this instanceof CloseFuture || this instanceof WriteFuture ||
+ this instanceof ReadFuture || this instanceof ConnectFuture)) {
+ return;
+ }
+
+ // Get the current thread stackTrace.
+ // Using Thread.currentThread().getStackTrace() is the best solution,
+ // even if slightly less efficient than doing a new Exception().getStackTrace(),
+ // as internally, it does exactly the same thing. The advantage of using
+ // this solution is that we may benefit some improvement with some
+ // future versions of Java.
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+
+ // Simple and quick check.
+ for (StackTraceElement s: stackTrace) {
+ if (AbstractPollingIoProcessor.class.getName().equals(s.getClassName())) {
+ IllegalStateException e = new IllegalStateException( "t" );
+ e.getStackTrace();
+ throw new IllegalStateException(
+ "DEAD LOCK: " + IoFuture.class.getSimpleName() +
+ ".await() was invoked from an I/O processor thread. " +
+ "Please use " + IoFutureListener.class.getSimpleName() +
+ " or configure a proper thread model alternatively.");
+ }
+ }
+
+ // And then more precisely.
+ for (StackTraceElement s: stackTrace) {
+ try {
+ Class<?> cls = DefaultIoFuture.class.getClassLoader().loadClass(s.getClassName());
+ if (IoProcessor.class.isAssignableFrom(cls)) {
+ throw new IllegalStateException(
+ "DEAD LOCK: " + IoFuture.class.getSimpleName() +
+ ".await() was invoked from an I/O processor thread. " +
+ "Please use " + IoFutureListener.class.getSimpleName() +
+ " or configure a proper thread model alternatively.");
+ }
+ } catch (Exception cnfe) {
+ // Ignore
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDone() {
+ synchronized (lock) {
+ return ready;
+ }
+ }
+
+ /**
+ * Sets the result of the asynchronous operation, and mark it as finished.
+ */
+ public void setValue(Object newValue) {
+ synchronized (lock) {
+ // Allow only once.
+ if (ready) {
+ return;
+ }
+
+ result = newValue;
+ ready = true;
+ if (waiters > 0) {
+ lock.notifyAll();
+ }
+ }
+
+ notifyListeners();
+ }
+
+ /**
+ * Returns the result of the asynchronous operation.
+ */
+ protected Object getValue() {
+ synchronized (lock) {
+ return result;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IoFuture addListener(IoFutureListener<?> listener) {
+ if (listener == null) {
+ throw new NullPointerException("listener");
+ }
+
+ boolean notifyNow = false;
+ synchronized (lock) {
+ if (ready) {
+ notifyNow = true;
+ } else {
+ if (firstListener == null) {
+ firstListener = listener;
+ } else {
+ if (otherListeners == null) {
+ otherListeners = new ArrayList<IoFutureListener<?>>(1);
+ }
+ otherListeners.add(listener);
+ }
+ }
+ }
+
+ if (notifyNow) {
+ notifyListener(listener);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IoFuture removeListener(IoFutureListener<?> listener) {
+ if (listener == null) {
+ throw new NullPointerException("listener");
+ }
+
+ synchronized (lock) {
+ if (!ready) {
+ if (listener == firstListener) {
+ if (otherListeners != null && !otherListeners.isEmpty()) {
+ firstListener = otherListeners.remove(0);
+ } else {
+ firstListener = null;
+ }
+ } else if (otherListeners != null) {
+ otherListeners.remove(listener);
+ }
+ }
+ }
+
+ return this;
+ }
+
+ private void notifyListeners() {
+ // There won't be any visibility problem or concurrent modification
+ // because 'ready' flag will be checked against both addListener and
+ // removeListener calls.
+ if (firstListener != null) {
+ notifyListener(firstListener);
+ firstListener = null;
+
+ if (otherListeners != null) {
+ for (IoFutureListener<?> l : otherListeners) {
+ notifyListener(l);
+ }
+ otherListeners = null;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void notifyListener(IoFutureListener l) {
+ try {
+ l.operationComplete(this);
+ } catch (Throwable t) {
+ ExceptionMonitor.getInstance().exceptionCaught(t);
+ }
+ }
+}
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java?rev=801159&r1=801158&r2=801159&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java Wed Aug 5 12:08:58 2009
@@ -1,253 +1,253 @@
-/*
- * 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.mina.filter.logging;
-
-import java.net.InetSocketAddress;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.Arrays;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.mina.core.filterchain.IoFilterEvent;
-import org.apache.mina.core.session.AttributeKey;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.util.CommonEventFilter;
-import org.slf4j.MDC;
-
-/**
- * This filter will inject some key IoSession properties into the Mapped Diagnostic Context (MDC)
- * <p/>
- * These properties will be set in the MDC for all logging events that are generated
- * down the call stack, even in code that is not aware of MINA.
- *
- * By default, the following properties will be set for all transports:
- * <ul>
- * <li>"handlerClass"</li>
- * <li>"remoteAddress"</li>
- * <li>"localAddress"</li>
- * </ul>
- *
- * When <code>session.getTransportMetadata().getAddressType() == InetSocketAddress.class</code>
- * the following properties will also be set:
- * <ul>
- * <li>"remoteIp"</li>
- * <li>"remotePort"</li>
- * <li>"localIp"</li>
- * <li>"localPort"</li>
- * </ul>
- *
- * User code can also add custom properties to the context, via {@link #setProperty(IoSession, String, String)}
- *
- * If you only want the MDC to be set for the IoHandler code, it's enough to add
- * one MdcInjectionFilter at the end of the filter chain.
- *
- * If you want the MDC to be set for ALL code, you should
- * add an MdcInjectionFilter to the start of the chain
- * and add that same MdcInjectionFilter instance after EVERY ExecutorFilter in the chain
- *
- * Thus it's ok to have one instance of the MdcInjectionFilter and add it multiple times to the chain
- * but you should avoid adding multiple instances to the chain.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-
-public class MdcInjectionFilter extends CommonEventFilter {
-
- public enum MdcKey {
- handlerClass, remoteAddress, localAddress, remoteIp, remotePort, localIp, localPort
- }
-
- /** key used for storing the context map in the IoSession */
- private static final AttributeKey CONTEXT_KEY = new AttributeKey(
- MdcInjectionFilter.class, "context");
-
- private ThreadLocal<Integer> callDepth = new ThreadLocal<Integer>() {
- @Override
- protected Integer initialValue() {
- return 0;
- }
- };
-
- private EnumSet<MdcKey> mdcKeys;
-
- /**
- * Use this constructor when you want to specify which keys to add to the MDC.
- * You could still add custom keys via {@link #setProperty(IoSession, String, String)}
- * @param keys set of keys that should be added to the MDC
- *
- * @see #setProperty(org.apache.mina.core.session.IoSession, String, String)
- */
- public MdcInjectionFilter(EnumSet<MdcKey> keys) {
- this.mdcKeys = keys.clone();
- }
-
- /**
- * Use this constructor when you want to specify which keys to add to the MDC
- * You could still add custom keys via {@link #setProperty(IoSession, String, String)}
- * @param keys list of keys that should be added to the MDC
- *
- * @see #setProperty(org.apache.mina.core.session.IoSession, String, String)
- */
- public MdcInjectionFilter(MdcKey... keys) {
- Set<MdcKey> keySet = new HashSet<MdcKey>(Arrays.asList(keys));
- this.mdcKeys = EnumSet.copyOf(keySet);
- }
-
- public MdcInjectionFilter() {
- this.mdcKeys = EnumSet.allOf(MdcKey.class);
- }
-
- @Override
- protected void filter(IoFilterEvent event) throws Exception {
- // since this method can potentially call into itself
- // we need to check the call depth before clearing the MDC
- int currentCallDepth = callDepth.get();
- callDepth.set(currentCallDepth + 1);
- Map<String, String> context = getAndFillContext(event.getSession());
-
- if (currentCallDepth == 0) {
- /* copy context to the MDC when necessary. */
- for (Map.Entry<String, String> e : context.entrySet()) {
- MDC.put(e.getKey(), e.getValue());
- }
- }
-
- try {
- /* propagate event down the filter chain */
- event.fire();
- } finally {
- if (currentCallDepth == 0) {
- /* remove context from the MDC */
- for (String key : context.keySet()) {
- MDC.remove(key);
- }
- callDepth.remove();
- } else {
- callDepth.set(currentCallDepth);
- }
- }
- }
-
- private Map<String, String> getAndFillContext(final IoSession session) {
- Map<String, String> context = getContext(session);
- if (context.isEmpty()) {
- fillContext(session, context);
- }
- return context;
- }
-
- @SuppressWarnings("unchecked")
- private static Map<String, String> getContext(final IoSession session) {
- Map<String, String> context = (Map<String, String>) session.getAttribute(CONTEXT_KEY);
- if (context == null) {
- context = new ConcurrentHashMap<String, String>();
- session.setAttribute(CONTEXT_KEY, context);
- }
- return context;
- }
-
- /**
- * write key properties of the session to the Mapped Diagnostic Context
- * sub-classes could override this method to map more/other attributes
- * @param session the session to map
- * @param context key properties will be added to this map
- */
- protected void fillContext(final IoSession session, final Map<String, String> context) {
- if (mdcKeys.contains(MdcKey.handlerClass)) {
- context.put(MdcKey.handlerClass.name(), session.getHandler()
- .getClass().getName());
- }
- if (mdcKeys.contains(MdcKey.remoteAddress)) {
- context.put(MdcKey.remoteAddress.name(), session.getRemoteAddress()
- .toString());
- }
- if (mdcKeys.contains(MdcKey.localAddress)) {
- context.put(MdcKey.localAddress.name(), session.getLocalAddress()
- .toString());
- }
- if (session.getTransportMetadata().getAddressType() == InetSocketAddress.class) {
- InetSocketAddress remoteAddress = (InetSocketAddress) session
- .getRemoteAddress();
- InetSocketAddress localAddress = (InetSocketAddress) session
- .getLocalAddress();
- if (mdcKeys.contains(MdcKey.remoteIp)) {
- context.put(MdcKey.remoteIp.name(), remoteAddress.getAddress()
- .getHostAddress());
- }
- if (mdcKeys.contains(MdcKey.remotePort)) {
- context.put(MdcKey.remotePort.name(), String
- .valueOf(remoteAddress.getPort()));
- }
- if (mdcKeys.contains(MdcKey.localIp)) {
- context.put(MdcKey.localIp.name(), localAddress.getAddress()
- .getHostAddress());
- }
- if (mdcKeys.contains(MdcKey.localPort)) {
- context.put(MdcKey.localPort.name(), String
- .valueOf(localAddress.getPort()));
- }
- }
- }
-
- public static String getProperty(IoSession session, String key) {
- if (key == null) {
- throw new NullPointerException("key should not be null");
- }
-
- Map<String, String> context = getContext(session);
- String answer = context.get(key);
- if (answer != null) {
- return answer;
- }
-
- return MDC.get(key);
- }
-
-
- /**
- * Add a property to the context for the given session
- * This property will be added to the MDC for all subsequent events
- * @param session The session for which you want to set a property
- * @param key The name of the property (should not be null)
- * @param value The value of the property
- */
- public static void setProperty(IoSession session, String key, String value) {
- if (key == null) {
- throw new NullPointerException("key should not be null");
- }
- if (value == null) {
- removeProperty(session, key);
- }
- Map<String, String> context = getContext(session);
- context.put(key, value);
- MDC.put(key, value);
- }
-
- public static void removeProperty(IoSession session, String key) {
- if (key == null) {
- throw new NullPointerException("key should not be null");
- }
- Map<String, String> context = getContext(session);
- context.remove(key);
- MDC.remove(key);
- }
-}
+/*
+ * 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.mina.filter.logging;
+
+import java.net.InetSocketAddress;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.mina.core.filterchain.IoFilterEvent;
+import org.apache.mina.core.session.AttributeKey;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.util.CommonEventFilter;
+import org.slf4j.MDC;
+
+/**
+ * This filter will inject some key IoSession properties into the Mapped Diagnostic Context (MDC)
+ * <p/>
+ * These properties will be set in the MDC for all logging events that are generated
+ * down the call stack, even in code that is not aware of MINA.
+ *
+ * By default, the following properties will be set for all transports:
+ * <ul>
+ * <li>"handlerClass"</li>
+ * <li>"remoteAddress"</li>
+ * <li>"localAddress"</li>
+ * </ul>
+ *
+ * When <code>session.getTransportMetadata().getAddressType() == InetSocketAddress.class</code>
+ * the following properties will also be set:
+ * <ul>
+ * <li>"remoteIp"</li>
+ * <li>"remotePort"</li>
+ * <li>"localIp"</li>
+ * <li>"localPort"</li>
+ * </ul>
+ *
+ * User code can also add custom properties to the context, via {@link #setProperty(IoSession, String, String)}
+ *
+ * If you only want the MDC to be set for the IoHandler code, it's enough to add
+ * one MdcInjectionFilter at the end of the filter chain.
+ *
+ * If you want the MDC to be set for ALL code, you should
+ * add an MdcInjectionFilter to the start of the chain
+ * and add that same MdcInjectionFilter instance after EVERY ExecutorFilter in the chain
+ *
+ * Thus it's ok to have one instance of the MdcInjectionFilter and add it multiple times to the chain
+ * but you should avoid adding multiple instances to the chain.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+
+public class MdcInjectionFilter extends CommonEventFilter {
+
+ public enum MdcKey {
+ handlerClass, remoteAddress, localAddress, remoteIp, remotePort, localIp, localPort
+ }
+
+ /** key used for storing the context map in the IoSession */
+ private static final AttributeKey CONTEXT_KEY = new AttributeKey(
+ MdcInjectionFilter.class, "context");
+
+ private ThreadLocal<Integer> callDepth = new ThreadLocal<Integer>() {
+ @Override
+ protected Integer initialValue() {
+ return 0;
+ }
+ };
+
+ private EnumSet<MdcKey> mdcKeys;
+
+ /**
+ * Use this constructor when you want to specify which keys to add to the MDC.
+ * You could still add custom keys via {@link #setProperty(IoSession, String, String)}
+ * @param keys set of keys that should be added to the MDC
+ *
+ * @see #setProperty(org.apache.mina.core.session.IoSession, String, String)
+ */
+ public MdcInjectionFilter(EnumSet<MdcKey> keys) {
+ this.mdcKeys = keys.clone();
+ }
+
+ /**
+ * Use this constructor when you want to specify which keys to add to the MDC
+ * You could still add custom keys via {@link #setProperty(IoSession, String, String)}
+ * @param keys list of keys that should be added to the MDC
+ *
+ * @see #setProperty(org.apache.mina.core.session.IoSession, String, String)
+ */
+ public MdcInjectionFilter(MdcKey... keys) {
+ Set<MdcKey> keySet = new HashSet<MdcKey>(Arrays.asList(keys));
+ this.mdcKeys = EnumSet.copyOf(keySet);
+ }
+
+ public MdcInjectionFilter() {
+ this.mdcKeys = EnumSet.allOf(MdcKey.class);
+ }
+
+ @Override
+ protected void filter(IoFilterEvent event) throws Exception {
+ // since this method can potentially call into itself
+ // we need to check the call depth before clearing the MDC
+ int currentCallDepth = callDepth.get();
+ callDepth.set(currentCallDepth + 1);
+ Map<String, String> context = getAndFillContext(event.getSession());
+
+ if (currentCallDepth == 0) {
+ /* copy context to the MDC when necessary. */
+ for (Map.Entry<String, String> e : context.entrySet()) {
+ MDC.put(e.getKey(), e.getValue());
+ }
+ }
+
+ try {
+ /* propagate event down the filter chain */
+ event.fire();
+ } finally {
+ if (currentCallDepth == 0) {
+ /* remove context from the MDC */
+ for (String key : context.keySet()) {
+ MDC.remove(key);
+ }
+ callDepth.remove();
+ } else {
+ callDepth.set(currentCallDepth);
+ }
+ }
+ }
+
+ private Map<String, String> getAndFillContext(final IoSession session) {
+ Map<String, String> context = getContext(session);
+ if (context.isEmpty()) {
+ fillContext(session, context);
+ }
+ return context;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Map<String, String> getContext(final IoSession session) {
+ Map<String, String> context = (Map<String, String>) session.getAttribute(CONTEXT_KEY);
+ if (context == null) {
+ context = new ConcurrentHashMap<String, String>();
+ session.setAttribute(CONTEXT_KEY, context);
+ }
+ return context;
+ }
+
+ /**
+ * write key properties of the session to the Mapped Diagnostic Context
+ * sub-classes could override this method to map more/other attributes
+ * @param session the session to map
+ * @param context key properties will be added to this map
+ */
+ protected void fillContext(final IoSession session, final Map<String, String> context) {
+ if (mdcKeys.contains(MdcKey.handlerClass)) {
+ context.put(MdcKey.handlerClass.name(), session.getHandler()
+ .getClass().getName());
+ }
+ if (mdcKeys.contains(MdcKey.remoteAddress)) {
+ context.put(MdcKey.remoteAddress.name(), session.getRemoteAddress()
+ .toString());
+ }
+ if (mdcKeys.contains(MdcKey.localAddress)) {
+ context.put(MdcKey.localAddress.name(), session.getLocalAddress()
+ .toString());
+ }
+ if (session.getTransportMetadata().getAddressType() == InetSocketAddress.class) {
+ InetSocketAddress remoteAddress = (InetSocketAddress) session
+ .getRemoteAddress();
+ InetSocketAddress localAddress = (InetSocketAddress) session
+ .getLocalAddress();
+ if (mdcKeys.contains(MdcKey.remoteIp)) {
+ context.put(MdcKey.remoteIp.name(), remoteAddress.getAddress()
+ .getHostAddress());
+ }
+ if (mdcKeys.contains(MdcKey.remotePort)) {
+ context.put(MdcKey.remotePort.name(), String
+ .valueOf(remoteAddress.getPort()));
+ }
+ if (mdcKeys.contains(MdcKey.localIp)) {
+ context.put(MdcKey.localIp.name(), localAddress.getAddress()
+ .getHostAddress());
+ }
+ if (mdcKeys.contains(MdcKey.localPort)) {
+ context.put(MdcKey.localPort.name(), String
+ .valueOf(localAddress.getPort()));
+ }
+ }
+ }
+
+ public static String getProperty(IoSession session, String key) {
+ if (key == null) {
+ throw new NullPointerException("key should not be null");
+ }
+
+ Map<String, String> context = getContext(session);
+ String answer = context.get(key);
+ if (answer != null) {
+ return answer;
+ }
+
+ return MDC.get(key);
+ }
+
+
+ /**
+ * Add a property to the context for the given session
+ * This property will be added to the MDC for all subsequent events
+ * @param session The session for which you want to set a property
+ * @param key The name of the property (should not be null)
+ * @param value The value of the property
+ */
+ public static void setProperty(IoSession session, String key, String value) {
+ if (key == null) {
+ throw new NullPointerException("key should not be null");
+ }
+ if (value == null) {
+ removeProperty(session, key);
+ }
+ Map<String, String> context = getContext(session);
+ context.put(key, value);
+ MDC.put(key, value);
+ }
+
+ public static void removeProperty(IoSession session, String key) {
+ if (key == null) {
+ throw new NullPointerException("key should not be null");
+ }
+ Map<String, String> context = getContext(session);
+ context.remove(key);
+ MDC.remove(key);
+ }
+}