001    package org.apache.commons.net.time;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import java.io.DataOutputStream;
021    import java.io.IOException;
022    import java.net.ServerSocket;
023    import java.net.Socket;
024    
025    /**
026     * The TimetSimpleServer class is a simple TCP implementation of a server
027     * for the Time Protocol described in RFC 868.
028     * <p>
029     * Listens for TCP socket connections on the time protocol port and writes
030     * the local time to socket outputStream as 32-bit integer of seconds 
031     * since midnight on 1 January 1900 GMT.
032     * See <A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc868.txt"> the spec </A> for
033     * details.
034     * <p>
035     * Note this is for <B>debugging purposes only</B> and not meant to be run as a realiable time service.
036     *
037     * @author Jason Mathews, MITRE Corporation
038     *
039     * @version $Revision: 658518 $ $Date: 2008-05-21 02:04:30 +0100 (Wed, 21 May 2008) $
040     */
041    public class TimeTestSimpleServer implements Runnable
042    {
043    
044        /**
045         * baseline time 1900-01-01T00:00:00 UTC
046         */
047        public static final long SECONDS_1900_TO_1970 = 2208988800L;
048    
049        /*** The default time port.  It is set to 37 according to RFC 868. ***/
050        public static final int DEFAULT_PORT = 37;
051    
052        private ServerSocket server;
053        private int port;
054        private boolean running = false;
055    
056        /**
057         * Default constructor for TimetSimpleServer.
058         * Initializes port to defaul time port.
059         */
060        public TimeTestSimpleServer()
061        {
062            port = DEFAULT_PORT;
063        }
064    
065        /**
066         * Constructor for TimetSimpleServer given a specific port.
067         */
068        public TimeTestSimpleServer(int port)
069        {
070            this.port = port;
071        }
072    
073        public void connect() throws IOException
074        {
075            if (server == null)
076            {
077                server = new ServerSocket(port);
078            }
079        }
080    
081        public int getPort()
082        {
083            return server == null ? port : server.getLocalPort();
084        }
085    
086        public boolean isRunning()
087        {
088            return running;
089        }
090    
091        /**
092         * Start time service and provide time to client connections.
093         * @throws IOException
094         */
095        public void start() throws IOException
096        {
097            if (server == null)
098        {
099                connect();
100        }
101        if (!running)
102        {
103            running = true;
104            new Thread(this).start();
105        }
106        }
107    
108        public void run()
109        {
110            Socket socket = null;
111            while (running)
112            {
113                try
114                {
115                    socket = server.accept();
116                    DataOutputStream os = new DataOutputStream(socket.getOutputStream());
117                    // add 500 ms to round off to nearest second
118                    int time = (int) ((System.currentTimeMillis() + 500) / 1000 + SECONDS_1900_TO_1970);
119                    os.writeInt(time);
120                    os.flush();
121                } catch (IOException e)
122                {
123                } finally
124                {
125                    if (socket != null)
126                        try
127                        {
128                            socket.close();  // force closing of the socket
129                        } catch (IOException e)
130                        {
131                            System.err.println("close socket error: " + e);
132                        }
133                }
134            }
135        }
136    
137        /**
138         * Close server socket.
139         */
140        public void stop()
141        {
142            running = false;
143            if (server != null)
144            {
145                try
146                {
147                    server.close();  // force closing of the socket
148                } catch (IOException e)
149                {
150                    System.err.println("close socket error: " + e);
151                }
152                server = null;
153            }
154        }
155    
156        public static void main(String[] args)
157        {
158            TimeTestSimpleServer server = new TimeTestSimpleServer();
159            try
160            {
161                server.start();
162            } catch (IOException e)
163            {
164            }
165        }
166    
167    }