001    /* 
002     * Copyright 2005-2006 Stephen McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at 
007     * 
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     * 
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.station.server;
020    
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.ObjectInputStream;
024    import java.io.BufferedInputStream;
025    import java.net.Socket;
026    import java.net.ServerSocket;
027    import java.net.SocketException;
028    import java.util.logging.Logger;
029    import java.util.logging.LogRecord;
030    
031    import net.dpml.depot.LogStatement;
032    
033    import net.dpml.lang.PID;
034    
035    /**
036     * The LoggingServer is a remote service that handles the aggregation of 
037     * log records from multiple jvm processes.
038     *
039     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
040     * @version 1.2.0
041     */
042    public class LoggingServer implements Runnable
043    {
044        private static final PID PROCESS = new PID();
045    
046        private final ServerSocket m_server;
047        
048        private int m_count = 0;
049        
050       /**
051        * Creation of a new logging service instance.
052        * @param port the log server port
053        * @exception IOException if an IO exception occurs
054        */
055        public LoggingServer( int port ) throws IOException
056        {
057            m_server = new ServerSocket( port );
058        }
059        
060       /**
061        * Runnable implementation.
062        */ 
063        public void run()
064        {
065            while( true )
066            {
067                try
068                {
069                    Socket socket = m_server.accept();
070                    RequestHandler handler = new RequestHandler( socket );
071                    Thread thread = new Thread( handler );
072                    thread.start();
073                }
074                catch( Throwable e )
075                {
076                    e.printStackTrace();
077                    m_count++;
078                }
079            }
080        }
081        
082        int getErrorCount()
083        {
084            return m_count;
085        }
086        
087       /**
088        * Internal utility class to handle a client connection.
089        */
090        final class RequestHandler implements Runnable
091        {
092            private final Socket m_socket;
093            
094           /**
095            * Creation of a new request handler.
096            * @param socket the socket
097            */
098            private RequestHandler( Socket socket )
099            {
100                m_socket = socket;
101            }
102            
103           /**
104            * Run the process.
105            */
106            public void run()
107            {
108                try
109                {
110                    InputStream input = m_socket.getInputStream();
111                    BufferedInputStream buffer = new BufferedInputStream( input );
112                    ObjectInputStream ois = new ObjectInputStream( buffer );
113                    while( true )
114                    {
115                        Object object = ois.readObject();
116                        if( object instanceof LogStatement )
117                        {
118                            LogStatement statement = (LogStatement) object;
119                            PID pid = statement.getPID();
120                            if( !PROCESS.equals( pid ) )
121                            {
122                                int id = pid.getValue();
123                                LogRecord record = statement.getLogRecord();
124                                String raw = record.getMessage();
125                                String message = "$[" + id + "] " + raw;
126                                record.setMessage( message );
127                                Logger logger = getNamedLogger( record );
128                                logger.log( record );
129                            }
130                        }
131                    }
132                    //System.out.println( "## DONE" );
133                    //input.close();
134                    //m_socket.close();
135                }
136                catch( ClassNotFoundException e )
137                {
138                    e.printStackTrace();
139                }
140                catch( SocketException ioe )
141                {
142                    // ignore
143                }
144                catch( IOException ioe )
145                {
146                    ioe.printStackTrace();
147                }
148            }
149    
150            private Logger getNamedLogger( LogRecord record )
151            {
152                String name = record.getLoggerName();
153                if( null != name )
154                {
155                    return Logger.getLogger( name );
156                }
157                else
158                {
159                    return Logger.getAnonymousLogger();
160                }
161            }
162        }
163    
164    }
165