    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    }