001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.core;
028    import org.opends.messages.Message;
029    
030    
031    
032    import org.opends.server.admin.std.server.ConnectionHandlerCfg;
033    import org.opends.server.api.ClientConnection;
034    import org.opends.server.api.ConnectionHandler;
035    import org.opends.server.api.DirectoryThread;
036    import org.opends.server.api.ServerShutdownListener;
037    import org.opends.server.loggers.debug.DebugTracer;
038    import org.opends.server.types.DebugLogLevel;
039    import org.opends.server.types.DisconnectReason;
040    
041    import static org.opends.server.loggers.debug.DebugLogger.*;
042    import org.opends.server.loggers.ErrorLogger;
043    import static org.opends.messages.CoreMessages.*;
044    
045    import static org.opends.server.util.StaticUtils.*;
046    
047    
048    
049    /**
050     * This class defines a thread that will be used to terminate client
051     * connections if they have been idle for too long.
052     */
053    public class IdleTimeLimitThread
054           extends DirectoryThread
055           implements ServerShutdownListener
056    {
057      /**
058       * The debug log tracer for this object.
059       */
060      private static final DebugTracer TRACER = getTracer();
061    
062    
063    
064      // Indicates whether a shutdown request has been received.
065      private boolean shutdownRequested;
066    
067    
068    
069      /**
070       * Creates a new instance of this idle time limit thread.
071       */
072      public IdleTimeLimitThread()
073      {
074        super("Idle Time Limit Thread");
075        setDaemon(true);
076    
077        shutdownRequested = false;
078        DirectoryServer.registerShutdownListener(this);
079      }
080    
081    
082    
083      /**
084       * Operates in a loop, teriminating any client connections that have been idle
085       * for too long.
086       */
087      public void run()
088      {
089        Message disconnectMessage = INFO_IDLETIME_LIMIT_EXCEEDED.get();
090    
091        long sleepTime = 5000L;
092    
093        while (! shutdownRequested)
094        {
095          try
096          {
097            try
098            {
099              sleep(sleepTime);
100            } catch (InterruptedException ie) {}
101    
102            sleepTime = 5000L;
103            for (ConnectionHandler ch : DirectoryServer.getConnectionHandlers())
104            {
105              ConnectionHandler<? extends ConnectionHandlerCfg> connHandler =
106                   (ConnectionHandler<? extends ConnectionHandlerCfg>) ch;
107              for (ClientConnection c : connHandler.getClientConnections())
108              {
109                long idleTime = c.getIdleTime();
110                if (idleTime > 0)
111                {
112                  long idleTimeLimit = c.getIdleTimeLimit();
113                  if (idleTimeLimit > 0)
114                  {
115                    if (idleTime > idleTimeLimit)
116                    {
117                      if (debugEnabled())
118                      {
119                        TRACER.debugInfo("Terminating client connection " +
120                                         c.getConnectionID() +
121                                         " due to the idle time limit");
122                      }
123    
124                      try
125                      {
126                        c.disconnect(DisconnectReason.IDLE_TIME_LIMIT_EXCEEDED,
127                                     true, disconnectMessage);
128                      }
129                      catch (Exception e)
130                      {
131                        if (debugEnabled())
132                        {
133                          TRACER.debugCaught(DebugLogLevel.ERROR, e);
134                        }
135    
136                        Message message = ERR_IDLETIME_DISCONNECT_ERROR.get(
137                                c.getConnectionID(),
138                                stackTraceToSingleLineString(e)
139                        );
140                        ErrorLogger.logError(message);
141                      }
142                    }
143                    else
144                    {
145                      long shouldSleepTime = idleTimeLimit - idleTime;
146                      if (shouldSleepTime < sleepTime)
147                      {
148                        sleepTime = shouldSleepTime;
149                      }
150                    }
151                  }
152                }
153              }
154            }
155          }
156          catch (Exception e)
157          {
158            if (debugEnabled())
159            {
160              TRACER.debugCaught(DebugLogLevel.ERROR, e);
161            }
162    
163            Message message =
164                ERR_IDLETIME_UNEXPECTED_ERROR.get(stackTraceToSingleLineString(e));
165            ErrorLogger.logError(message);
166          }
167        }
168      }
169    
170    
171    
172      /**
173       * {@inheritDoc}
174       */
175      public String getShutdownListenerName()
176      {
177        return "Idle Time Limit Thread";
178      }
179    
180    
181    
182      /**
183       * {@inheritDoc}
184       */
185      public void processServerShutdown(Message reason)
186      {
187        shutdownRequested = true;
188      }
189    }
190