2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.apex.core.infrastructure.messaging.util;
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.ObjectOutputStream;
26 import java.net.InetAddress;
27 import java.net.NetworkInterface;
28 import java.net.Socket;
29 import java.net.UnknownHostException;
30 import java.util.Enumeration;
32 import org.slf4j.ext.XLogger;
33 import org.slf4j.ext.XLoggerFactory;
36 * The Class MessagingUtils is a class with static methods used in IPC messaging for finding free
37 * ports, translating host names to addresses, serializing objects and flushing object streams.
39 * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
41 public final class MessagingUtils {
42 // The port number of the lowest user port, ports 0-1023 are system ports
43 private static final int LOWEST_USER_PORT = 1024;
46 * Port number is an unsigned 16-bit integer, so maximum port is 65535
48 private static final int MAX_PORT_RANGE = 65535;
50 // Logger for this class
51 private static final XLogger LOGGER = XLoggerFactory.getXLogger(MessagingUtils.class);
54 * Private constructor used to prevent sub class instantiation.
56 private MessagingUtils() {}
59 * This method searches the availability of the port, if the requested port not available, this
60 * method will throw an exception.
62 * @param port the port to check
63 * @return the port verified as being free
64 * @throws RuntimeException on port allocation errors
66 public static int checkPort(final int port) {
67 LOGGER.entry("Checking availability of port {}", port);
69 if (isPortAvailable(port)) {
70 LOGGER.debug("Port {} is available ", port);
73 LOGGER.debug("Port {} is not available", port);
74 throw new RuntimeException("could not allocate requested port: " + port);
78 * This method searches the availability of the port, if the requested port not available,this
79 * method will increment the port number and check the availability of that port, this process
80 * will continue until it reaches max port range which is {@link MAX_PORT_RANGE}.
82 * @param port the first port to check
83 * @return the port that was found
84 * @throws RuntimeException on port allocation errors
86 public static int findPort(final int port) {
87 LOGGER.entry("Checking availability of port {}", port);
89 int availablePort = port;
91 while (availablePort <= MAX_PORT_RANGE) {
92 if (isPortAvailable(availablePort)) {
93 LOGGER.debug("Port {} is available ", availablePort);
96 LOGGER.debug("Port {} is not available", availablePort);
99 throw new RuntimeException("could not find free available");
103 * Check if port is available or not.
105 * @param port the port to test
106 * @return true if port is available
108 public static boolean isPortAvailable(final int port) {
109 try (final Socket socket = new Socket("localhost", port)) {
111 } catch (final IOException ignoredException) {
112 LOGGER.trace("Port {} is available", port, ignoredException);
118 * Returns the local host address.
120 * @return the local host address
122 public static InetAddress getHost() {
124 return InetAddress.getLocalHost();
125 } catch (final UnknownHostException e) {
126 throw new IllegalStateException(e.getMessage(), e);
131 * This method searches the availability of the port, if the requested port not available,this
132 * method will increment the port number and check the availability, this process will continue
133 * until it find port available.
135 * @param port the first port to check
136 * @return the port that was found
137 * @throws RuntimeException on port allocation errors
139 public static int allocateAddress(final int port) {
140 if (port < LOWEST_USER_PORT) {
141 throw new IllegalArgumentException("The port " + port + " is already in use");
143 return MessagingUtils.findPort(port);
147 * Get an Internet Address for the local host.
149 * @return an Internet address
150 * @throws UnknownHostException if the address of the local host cannot be found
152 public static InetAddress getLocalHostLANAddress() throws UnknownHostException {
154 InetAddress candidateAddress = null;
155 // Iterate all NICs (network interface cards)...
156 for (final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces
157 .hasMoreElements();) {
158 final NetworkInterface iface = ifaces.nextElement();
159 // Iterate all IP addresses assigned to each card...
160 for (final Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs
161 .hasMoreElements();) {
162 final InetAddress inetAddr = inetAddrs.nextElement();
163 if (!inetAddr.isLoopbackAddress()) {
165 if (inetAddr.isSiteLocalAddress()) {
166 // Found non-loopback site-local address. Return it
169 } else if (candidateAddress == null) {
170 // Found non-loopback address, but not
171 // necessarily site-local.
172 // Store it as a candidate to be returned if
173 // site-local address is not subsequently
175 candidateAddress = inetAddr;
176 // Note that we don't repeatedly assign
177 // non-loopback non-site-local addresses as
179 // only the first. For subsequent iterations,
180 // candidate will be non-null.
185 if (candidateAddress != null) {
186 // We did not find a site-local address, but we found some other
187 // non-loopback address.
188 // Server might have a non-site-local address assigned to its
189 // NIC (or it might be running
190 // IPv6 which deprecates the "site-local" concept).
191 // Return this non-loopback candidate address...
192 return candidateAddress;
194 // At this point, we did not find a non-loopback address.
195 // Fall back to returning whatever InetAddress.getLocalHost()
197 final InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
198 if (jdkSuppliedAddress == null) {
199 throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
201 return jdkSuppliedAddress;
202 } catch (final Exception e) {
203 final UnknownHostException unknownHostException =
204 new UnknownHostException("Failed to determine LAN address: " + e);
205 unknownHostException.initCause(e);
206 throw unknownHostException;
211 * This method serializes the message holder objects.
213 * @param object the object
216 public static byte[] serializeObject(final Object object) {
217 LOGGER.entry(object.getClass().getName());
218 final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
219 ObjectOutputStream oos = null;
221 oos = new ObjectOutputStream(bytesOut);
222 oos.writeObject(object);
223 } catch (final IOException e) {
224 LOGGER.warn("error on object serialization", e);
226 flushAndClose(oos, bytesOut);
228 final byte[] bytes = bytesOut.toByteArray();
233 * Flush and close an object stream and a byte array output stream.
235 * @param oos the object output stream
236 * @param bytesOut the byte array output stream
238 private static void flushAndClose(final ObjectOutputStream oos, final ByteArrayOutputStream bytesOut) {
244 if (bytesOut != null) {
248 } catch (final IOException e) {
249 LOGGER.error("Failed to close the Srialization operation");