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;
018    
019    import java.io.OutputStream;
020    import java.io.Serializable;
021    import java.net.InetAddress;
022    import java.net.UnknownHostException;
023    import java.util.HashMap;
024    import java.util.Map;
025    
026    import org.apache.logging.log4j.core.Layout;
027    import org.apache.logging.log4j.core.appender.ManagerFactory;
028    import org.apache.logging.log4j.util.Strings;
029    
030    /**
031     * Socket Manager for UDP connections.
032     */
033    public class DatagramSocketManager extends AbstractSocketManager {
034    
035        private static final DatagramSocketManagerFactory FACTORY = new DatagramSocketManagerFactory();
036    
037        /**
038         * The Constructor.
039         * @param name The unique name of the connection.
040         * @param os The OutputStream.
041         * @param inetAddress
042         * @param host The host to connect to.
043         * @param port The port on the host.
044         * @param layout The layout
045         */
046        protected DatagramSocketManager(final String name, final OutputStream os, final InetAddress inetAddress, final String host,
047                    final int port, final Layout<? extends Serializable> layout) {
048            super(name, os, inetAddress, host, port, layout);
049        }
050    
051        /**
052         * Obtain a SocketManager.
053         * @param host The host to connect to.
054         * @param port The port on the host.
055         * @param layout The layout.
056         * @return A DatagramSocketManager.
057         */
058        public static DatagramSocketManager getSocketManager(final String host, final int port, final Layout<? extends Serializable> layout) {
059            if (Strings.isEmpty(host)) {
060                throw new IllegalArgumentException("A host name is required");
061            }
062            if (port <= 0) {
063                throw new IllegalArgumentException("A port value is required");
064            }
065            return (DatagramSocketManager) getManager("UDP:" + host + ':' + port, new FactoryData(host, port, layout),
066                FACTORY);
067        }
068    
069        /**
070         * Gets this DatagramSocketManager's content format. Specified by:
071         * <ul>
072         * <li>Key: "protocol" Value: "udp"</li>
073         * <li>Key: "direction" Value: "out"</li>
074         * </ul>
075         * 
076         * @return Map of content format keys supporting DatagramSocketManager
077         */
078        @Override
079        public Map<String, String> getContentFormat() {
080            final Map<String, String> result = new HashMap<String, String>(super.getContentFormat());
081            result.put("protocol", "udp");
082            result.put("direction", "out");
083            return result;
084        }
085    
086        /**
087         * Data for the factory.
088         */
089        private static class FactoryData {
090            private final String host;
091            private final int port;
092            private final Layout<? extends Serializable> layout;
093    
094            public FactoryData(final String host, final int port, final Layout<? extends Serializable> layout) {
095                this.host = host;
096                this.port = port;
097                this.layout = layout;
098            }
099        }
100    
101        /**
102         * Factory to create the DatagramSocketManager.
103         */
104        private static class DatagramSocketManagerFactory implements ManagerFactory<DatagramSocketManager, FactoryData> {
105    
106            @Override
107            public DatagramSocketManager createManager(final String name, final FactoryData data) {
108                InetAddress inetAddress;
109                try {
110                    inetAddress = InetAddress.getByName(data.host);
111                } catch (final UnknownHostException ex) {
112                    LOGGER.error("Could not find address of " + data.host, ex);
113                    return null;
114                }
115                final OutputStream os = new DatagramOutputStream(data.host, data.port, data.layout.getHeader(),
116                        data.layout.getFooter());
117                return new DatagramSocketManager(name, os, inetAddress, data.host, data.port, data.layout);
118            }
119        }
120    }