Source Code for Apache Log4j Core Implementation

Apache Log4j Core Implementation provides the functional components of the logging system. Users are free to create their own plugins and include them in the logging configuration. Apache Log4j Core is a required module to use Apache Log4j.

Bytecode (Java 8) for Apache Log4j Core Implementation is provided in a separate JAR file like log4j-core-2.14.1.jar.

Source Code files for Apache Log4j API are provided in both binary packge like apache-log4j-2.14.1-bin.zip and source package like apache-log4j-2.14.1-src.zip. You can download them at Apache Log4j Website.

You can also browse Source Code files for Apache Log4j Core Implementation 2.14.1 below.

✍: FYIcenter.com

org/apache/logging/log4j/core/net/MulticastDnsAdvertiser.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
package org.apache.logging.log4j.core.net;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.util.Integers;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.LoaderUtil;

/**
 * Advertise an entity via ZeroConf/MulticastDNS and the JmDNS library.
 *
 * The length of property names and values must be 255 bytes or less. Entries with names or values larger than 255 bytes
 * will be removed prior to advertisement.
 *
 */
@Plugin(name = "multicastdns", category = Core.CATEGORY_NAME, elementType = "advertiser", printObject = false)
public class MulticastDnsAdvertiser implements Advertiser {
    /**
     * Status logger.
     */
    protected static final Logger LOGGER = StatusLogger.getLogger();

    private static final int MAX_LENGTH = 255;
    private static final int DEFAULT_PORT = 4555;

    private static Object jmDNS = initializeJmDns();
    private static Class<?> jmDNSClass;
    private static Class<?> serviceInfoClass;

    public MulticastDnsAdvertiser() {
        // no arg constructor for reflection
    }

    /**
     * Advertise the provided entity.
     *
     * Properties map provided in advertise method must include a "name" entry but may also provide "protocol" (tcp/udp)
     * as well as a "port" entry
     *
     * The length of property names and values must be 255 bytes or less. Entries with names or values larger than 255
     * bytes will be removed prior to advertisement.
     *
     * @param properties the properties representing the entity to advertise
     * @return the object which can be used to unadvertise, or null if advertisement was unsuccessful
     */
    @Override
    public Object advertise(final Map<String, String> properties) {
        // default to tcp if "protocol" was not set
        final Map<String, String> truncatedProperties = new HashMap<>();
        for (final Map.Entry<String, String> entry : properties.entrySet()) {
            if (entry.getKey().length() <= MAX_LENGTH && entry.getValue().length() <= MAX_LENGTH) {
                truncatedProperties.put(entry.getKey(), entry.getValue());
            }
        }
        final String protocol = truncatedProperties.get("protocol");
        final String zone = "._log4j._" + (protocol != null ? protocol : "tcp") + ".local.";
        // default to 4555 if "port" was not set
        final String portString = truncatedProperties.get("port");
        final int port = Integers.parseInt(portString, DEFAULT_PORT);

        final String name = truncatedProperties.get("name");

        // if version 3 is available, use it to construct a serviceInfo instance, otherwise support the version1 API
        if (jmDNS != null) {
            boolean isVersion3 = false;
            try {
                // create method is in version 3, not version 1
                jmDNSClass.getMethod("create");
                isVersion3 = true;
            } catch (final NoSuchMethodException e) {
                // no-op
            }
            Object serviceInfo;
            if (isVersion3) {
                serviceInfo = buildServiceInfoVersion3(zone, port, name, truncatedProperties);
            } else {
                serviceInfo = buildServiceInfoVersion1(zone, port, name, truncatedProperties);
            }

            try {
                final Method method = jmDNSClass.getMethod("registerService", serviceInfoClass);
                method.invoke(jmDNS, serviceInfo);
            } catch (final IllegalAccessException | InvocationTargetException e) {
                LOGGER.warn("Unable to invoke registerService method", e);
            } catch (final NoSuchMethodException e) {
                LOGGER.warn("No registerService method", e);
            }
            return serviceInfo;
        }
        LOGGER.warn("JMDNS not available - will not advertise ZeroConf support");
        return null;
    }

    /**
     * Unadvertise the previously advertised entity.
     *
     * @param serviceInfo
     */
    @Override
    public void unadvertise(final Object serviceInfo) {
        if (jmDNS != null) {
            try {
                final Method method = jmDNSClass.getMethod("unregisterService", serviceInfoClass);
                method.invoke(jmDNS, serviceInfo);
            } catch (final IllegalAccessException | InvocationTargetException e) {
                LOGGER.warn("Unable to invoke unregisterService method", e);
            } catch (final NoSuchMethodException e) {
                LOGGER.warn("No unregisterService method", e);
            }
        }
    }

    private static Object createJmDnsVersion1() {
        try {
            return jmDNSClass.getConstructor().newInstance();
        } catch (final InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            LOGGER.warn("Unable to instantiate JMDNS", e);
        }
        return null;
    }

    private static Object createJmDnsVersion3() {
        try {
            final Method jmDNSCreateMethod = jmDNSClass.getMethod("create");
            return jmDNSCreateMethod.invoke(null, (Object[]) null);
        } catch (final IllegalAccessException | InvocationTargetException e) {
            LOGGER.warn("Unable to invoke create method", e);
        } catch (final NoSuchMethodException e) {
            LOGGER.warn("Unable to get create method", e);
        }
        return null;
    }

    private static Object buildServiceInfoVersion1(final String zone, final int port, final String name,
            final Map<String, String> properties) {
        // version 1 uses a hashtable
        @SuppressWarnings("UseOfObsoleteCollectionType")
        final Hashtable<String, String> hashtableProperties = new Hashtable<>(properties);
        try {
            return serviceInfoClass.getConstructor(String.class, String.class, int.class, int.class, int.class,
                    Hashtable.class).newInstance(zone, name, port, 0, 0, hashtableProperties);
        } catch (final IllegalAccessException | InstantiationException | InvocationTargetException e) {
            LOGGER.warn("Unable to construct ServiceInfo instance", e);
        } catch (final NoSuchMethodException e) {
            LOGGER.warn("Unable to get ServiceInfo constructor", e);
        }
        return null;
    }

    private static Object buildServiceInfoVersion3(final String zone, final int port, final String name,
            final Map<String, String> properties) {
        try {
            return serviceInfoClass
                    // zone/type display name port weight priority properties
                    .getMethod("create", String.class, String.class, int.class, int.class, int.class, Map.class)
                    .invoke(null, zone, name, port, 0, 0, properties);
        } catch (final IllegalAccessException | InvocationTargetException e) {
            LOGGER.warn("Unable to invoke create method", e);
        } catch (final NoSuchMethodException e) {
            LOGGER.warn("Unable to find create method", e);
        }
        return null;
    }

    private static Object initializeJmDns() {
        try {
            jmDNSClass = LoaderUtil.loadClass("javax.jmdns.JmDNS");
            serviceInfoClass = LoaderUtil.loadClass("javax.jmdns.ServiceInfo");
            // if version 3 is available, use it to construct a serviceInfo instance, otherwise support the version1 API
            boolean isVersion3 = false;
            try {
                // create method is in version 3, not version 1
                jmDNSClass.getMethod("create");
                isVersion3 = true;
            } catch (final NoSuchMethodException e) {
                // no-op
            }

            if (isVersion3) {
                return createJmDnsVersion3();
            }
            return createJmDnsVersion1();
        } catch (final ClassNotFoundException | ExceptionInInitializerError e) {
            LOGGER.warn("JmDNS or serviceInfo class not found", e);
        }
        return null;
    }
}

org/apache/logging/log4j/core/net/MulticastDnsAdvertiser.java

 

⇒ Source Code for Apache Log4j JDK Logging Adapter

⇐ Source Code for Apache Log4j API

⇑ Downloading and Reviewing Apache Log4j Packages

⇑⇑ FAQ for Apache Log4j

2015-11-03, 51215👍, 0💬