1   package org.apache.commons.net.time;
2   
3   /* ====================================================================
4    *
5    * The Apache Software License, Version 1.1
6    *
7    * Copyright (c) 2003 The Apache Software Foundation.  All rights
8    * reserved.
9    *
10   * Redistribution and use in source and binary forms, with or without
11   * modification, are permitted provided that the following conditions
12   * are met:
13   *
14   * 1. Redistributions of source code must retain the above copyright
15   *    notice, this list of conditions and the following disclaimer.
16   *
17   * 2. Redistributions in binary form must reproduce the above copyright
18   *    notice, this list of conditions and the following disclaimer in
19   *    the documentation and/or other materials provided with the
20   *    distribution.
21   *
22   * 3. The end-user documentation included with the redistribution, if
23   *    any, must include the following acknowlegement:
24   *       "This product includes software developed by the
25   *        Apache Software Foundation (http://www.apache.org/)."
26   *    Alternately, this acknowlegement may appear in the software itself,
27   *    if and wherever such third-party acknowlegements normally appear.
28   *
29   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
30   *    Foundation" must not be used to endorse or promote products derived
31   *    from this software without prior written permission. For written
32   *    permission, please contact apache@apache.org.
33   *
34   * 5. Products derived from this software may not be called "Apache"
35   *    nor may "Apache" appear in their names without prior written
36   *    permission of the Apache Group.
37   *
38   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
39   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
42   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
45   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
46   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
47   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
48   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49   * SUCH DAMAGE.
50   * ====================================================================
51   *
52   * This software consists of voluntary contributions made by many
53   * individuals on behalf of the Apache Software Foundation.  For more
54   * information on the Apache Software Foundation, please see
55   * <http://www.apache.org/>.
56   */
57  
58  import java.io.DataOutputStream;
59  import java.io.IOException;
60  import java.net.ServerSocket;
61  import java.net.Socket;
62  
63  /**
64   * The TimetSimpleServer class is a simple TCP implementation of a server
65   * for the Time Protocol described in RFC 868.
66   * <p>
67   * Listens for TCP socket connections on the time protocol port and writes
68   * the local time to socket outputStream as 32-bit integer of seconds 
69   * since midnight on 1 January 1900 GMT.
70   * See <A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc868.txt"> the spec </A> for
71   * details.
72   * <p>
73   * Note this is for <B>debugging purposes only</B> and not meant to be run as a realiable time service.
74   *
75   * @author Jason Mathews, MITRE Corporation
76   *
77   * @version $Revision: 1.1 $ $Date: 2003/09/24 21:51:48 $
78   */
79  public class TimeTestSimpleServer implements Runnable
80  {
81  
82      /**
83       * baseline time 1900-01-01T00:00:00 UTC
84       */
85      public static final long SECONDS_1900_TO_1970 = 2208988800L;
86  
87      /*** The default time port.  It is set to 37 according to RFC 868. ***/
88      public static final int DEFAULT_PORT = 37;
89  
90      private ServerSocket server;
91      private int port;
92      private boolean running = false;
93  
94      /**
95       * Default constructor for TimetSimpleServer.
96       * Initializes port to defaul time port.
97       */
98      public TimeTestSimpleServer()
99      {
100         port = DEFAULT_PORT;
101     }
102 
103     /**
104      * Constructor for TimetSimpleServer given a specific port.
105      */
106     public TimeTestSimpleServer(int port)
107     {
108         this.port = port;
109     }
110 
111     public void connect() throws IOException
112     {
113         if (server == null)
114         {
115             server = new ServerSocket(port);
116         }
117     }
118 
119     public int getPort()
120     {
121         return server == null ? port : server.getLocalPort();
122     }
123 
124     public boolean isRunning()
125     {
126         return running;
127     }
128 
129     /**
130      * Start time service and provide time to client connections.
131      * @throws IOException
132      */
133     public void start() throws IOException
134     {
135         if (server == null)
136 	{
137             connect();
138 	}
139 	if (!running)
140 	{
141 	    running = true;
142 	    new Thread(this).start();
143 	}
144     }
145 
146     public void run()
147     {
148         Socket socket = null;
149         while (running)
150         {
151             try
152             {
153                 socket = server.accept();
154                 DataOutputStream os = new DataOutputStream(socket.getOutputStream());
155                 // add 500 ms to round off to nearest second
156                 int time = (int) ((System.currentTimeMillis() + 500) / 1000 + SECONDS_1900_TO_1970);
157                 os.writeInt(time);
158                 os.flush();
159             } catch (IOException e)
160             {
161             } finally
162             {
163                 if (socket != null)
164                     try
165                     {
166                         socket.close();  // force closing of the socket
167                     } catch (IOException e)
168                     {
169                         System.err.println("close socket error: " + e);
170                     }
171             }
172         }
173     }
174 
175     /**
176      * Close server socket.
177      */
178     public void stop()
179     {
180         running = false;
181         if (server != null)
182         {
183             try
184             {
185                 server.close();  // force closing of the socket
186             } catch (IOException e)
187             {
188                 System.err.println("close socket error: " + e);
189             }
190             server = null;
191         }
192     }
193 
194     public static void main(String[] args)
195     {
196         TimeTestSimpleServer server = new TimeTestSimpleServer();
197         try
198         {
199             server.start();
200         } catch (IOException e)
201         {
202         }
203     }
204 
205 }