org.apereo.portal.PortalInfoProviderImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apereo.portal.PortalInfoProviderImpl.java

Source

/**
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo 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 the following location:
 *
 *   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.apereo.portal;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.lang.StringUtils;
import org.apereo.portal.utils.RandomTokenGenerator;
import org.apereo.portal.utils.threading.ReadResult;
import org.apereo.portal.utils.threading.ReadWriteCallback;
import org.apereo.portal.utils.threading.ReadWriteLockTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author Eric Dalquist
 * @version $Revision$
 */
@Service("portalInfoProvider")
public class PortalInfoProviderImpl implements IPortalInfoProvider, ReadWriteCallback<String> {
    protected final Logger logger = LoggerFactory.getLogger(getClass());

    private String serverName;
    private String networkInterfaceName;

    private String resolvedServerName;
    private String resolvedUniqueServerName;

    /**
     * @param serverName A specific server name for {@link #getServerName()} to return
     */
    @Value("${org.apereo.portal.PortalInfoProvider.serverName:}")
    public void setServerName(String serverName) {
        this.serverName = StringUtils.trimToNull(serverName);
    }

    /**
     * @param networkInterfaceName The name to use to lookup a NetworkInterface via {@link NetworkInterface#getByName(String)}
     */
    @Value("${org.apereo.portal.PortalInfoProvider.networkInterfaceName:}")
    public void setNetworkInterfaceName(String networkInterfaceName) {
        this.networkInterfaceName = StringUtils.trimToNull(networkInterfaceName);
    }

    private final ReadWriteLock serverNameResolutionLock = new ReentrantReadWriteLock();

    @Override
    public final String getServerName() {
        return ReadWriteLockTemplate.doWithLock(serverNameResolutionLock, this);
    }

    @Override
    public String getUniqueServerName() {
        ReadWriteLockTemplate.doWithLock(serverNameResolutionLock, this);
        return this.resolvedUniqueServerName;
    }

    @Override
    public ReadResult<String> doInReadLock() {
        if (this.resolvedServerName != null) {
            return ReadResult.create(false, this.resolvedServerName);
        }

        return ReadResult.create(true);
    }

    @Override
    public String doInWriteLock(ReadResult<String> readResult) {
        this.resolvedServerName = resolveServerName();
        this.resolvedUniqueServerName = this.resolvedServerName + "_"
                + RandomTokenGenerator.INSTANCE.generateRandomToken(4);
        return this.resolvedServerName;
    }

    protected String resolveServerName() {
        if (this.serverName != null) {
            return this.serverName;
        }

        String name = getNetworkInterfaceName(this.networkInterfaceName);
        if (name != null) {
            return name;
        }

        name = getLocalHostName();
        if (name != null) {
            return name;
        }

        name = getDefaultNetworkInterfaceName();
        if (name != null) {
            return name;
        }

        this.logger.warn("Failed to get serverName for NetworkInterface (" + this.networkInterfaceName
                + "), for InetAddress.getLocalHost(), for any NetworkInterface. Reverting to JVM instance specific UUID string.");
        return UUID.randomUUID().toString();
    }

    protected String getDefaultNetworkInterfaceName() {
        this.logger
                .info("Attempting to resolve serverName by iterating over NetworkInterface.getNetworkInterfaces()");

        //Fail back to our best attempt at resolution
        final Enumeration<NetworkInterface> networkInterfaceEnum;
        try {
            networkInterfaceEnum = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            logger.warn("Failed to get list of available NetworkInterfaces.", e);
            return null;
        }

        //Use a local variable here to try and return the first hostName found that doesn't start with localhost
        String name = null;
        while (networkInterfaceEnum.hasMoreElements()) {
            final NetworkInterface networkInterface = networkInterfaceEnum.nextElement();

            for (Enumeration<InetAddress> inetAddressEnum = networkInterface.getInetAddresses(); inetAddressEnum
                    .hasMoreElements();) {
                final InetAddress inetAddress = inetAddressEnum.nextElement();
                name = inetAddress.getHostName();
                if (!name.startsWith("localhost")) {
                    return name;
                }
            }
        }

        return name;
    }

    protected String getLocalHostName() {
        this.logger.info("Attempting to resolve serverName using InetAddress.getLocalHost()");

        final InetAddress localhost;
        try {
            localhost = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            logger.warn("Failed to find InetAddress for InetAddress.getLocalHost()", e);
            return null;
        }

        return localhost.getHostName();
    }

    protected String getNetworkInterfaceName(String networkInterfaceName) {
        if (networkInterfaceName == null) {
            return null;
        }

        this.logger.info("Attempting to resolve serverName using NetworkInterface named ({})",
                networkInterfaceName);

        final NetworkInterface networkInterface;
        try {
            networkInterface = NetworkInterface.getByName(networkInterfaceName);
        } catch (SocketException e) {
            logger.warn("Failed to get NetworkInterface for name (" + networkInterfaceName + ").", e);
            return null;
        }

        if (networkInterface == null) {
            logger.warn("No NetworkInterface could be found for name (" + networkInterfaceName
                    + "). Available interface names: " + getNetworkInterfaceNames());
            return null;
        }

        final Enumeration<InetAddress> inetAddressesEnum = networkInterface.getInetAddresses();
        if (!inetAddressesEnum.hasMoreElements()) {
            logger.warn("NetworkInterface (" + networkInterface.getName()
                    + ") has no InetAddresses to get a name from.");
            return null;
        }

        final InetAddress inetAddress = inetAddressesEnum.nextElement();
        if (inetAddressesEnum.hasMoreElements()) {
            logger.warn("NetworkInterface (" + networkInterface.getName()
                    + ") has more than one InetAddress, the hostName of the first will be returned.");
        }

        return inetAddress.getHostName();
    }

    protected Set<String> getNetworkInterfaceNames() {
        final Enumeration<NetworkInterface> networkInterfacesEnum;
        try {
            networkInterfacesEnum = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            logger.warn("Failed to get list of available NetworkInterfaces.", e);
            return Collections.emptySet();
        }

        final Set<String> names = new LinkedHashSet<String>();
        while (networkInterfacesEnum.hasMoreElements()) {
            final NetworkInterface networkInterface = networkInterfacesEnum.nextElement();
            names.add(networkInterface.getName());
        }

        return names;
    }

}