001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    package org.apache.logging.log4j.core.net.server;
018    
019    import java.io.File;
020    import java.io.FileInputStream;
021    import java.io.FileNotFoundException;
022    import java.io.IOException;
023    import java.io.InputStream;
024    import java.net.MalformedURLException;
025    import java.net.URI;
026    import java.net.URL;
027    
028    import org.apache.logging.log4j.LogManager;
029    import org.apache.logging.log4j.Logger;
030    import org.apache.logging.log4j.core.LogEventListener;
031    import org.apache.logging.log4j.core.config.Configuration;
032    import org.apache.logging.log4j.core.config.ConfigurationSource;
033    import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
034    import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
035    import org.apache.logging.log4j.core.util.Assert;
036    
037    /**
038     * Abstract socket server for TCP and UDP implementations.
039     * 
040     * @param <T> The kind of input stream read
041     * 
042     * TODO Make a LifeCycle
043     */
044    public abstract class AbstractSocketServer<T extends InputStream> extends LogEventListener implements Runnable {
045    
046        /**
047         * Factory that creates a Configuration for the server.
048         */
049        protected static class ServerConfigurationFactory extends XmlConfigurationFactory {
050    
051            private final String path;
052    
053            public ServerConfigurationFactory(final String path) {
054                this.path = path;
055            }
056    
057            @Override
058            public Configuration getConfiguration(final String name, final URI configLocation) {
059                if (path != null && path.length() > 0) {
060                    File file = null;
061                    ConfigurationSource source = null;
062                    try {
063                        file = new File(path);
064                        final FileInputStream is = new FileInputStream(file);
065                        source = new ConfigurationSource(is, file);
066                    } catch (final FileNotFoundException ex) {
067                        // Ignore this error
068                    }
069                    if (source == null) {
070                        try {
071                            final URL url = new URL(path);
072                            source = new ConfigurationSource(url.openStream(), url);
073                        } catch (final MalformedURLException mue) {
074                            // Ignore this error
075                        } catch (final IOException ioe) {
076                            // Ignore this error
077                        }
078                    }
079    
080                    try {
081                        if (source != null) {
082                            return new XmlConfiguration(source);
083                        }
084                    } catch (final Exception ex) {
085                        // Ignore this error.
086                    }
087                    System.err.println("Unable to process configuration at " + path + ", using default.");
088                }
089                return super.getConfiguration(name, configLocation);
090            }
091        }
092    
093        protected static final int MAX_PORT = 65534;
094    
095        private volatile boolean active = true;
096    
097        protected final LogEventBridge<T> logEventInput;
098    
099        protected final Logger logger;
100    
101        /**
102         * Creates a new socket server.
103         * 
104         * @param port listen to this port
105         * @param logEventInput Use this input to read log events.
106         */
107        public AbstractSocketServer(final int port, final LogEventBridge<T> logEventInput) {
108            this.logger = LogManager.getLogger(this.getClass().getName() + '.' + port);
109            this.logEventInput = Assert.requireNonNull(logEventInput, "LogEventInput");
110        }
111    
112        protected boolean isActive() {
113            return this.active;
114        }
115    
116        protected void setActive(final boolean isActive) {
117            this.active = isActive;
118        }
119    
120        /**
121         * Start this server in a new thread.
122         * 
123         * @return the new thread that running this server.
124         */
125        public Thread startNewThread() {
126            final Thread thread = new Thread(this);
127            thread.start();
128            return thread;
129        }
130    
131    }