2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.core.infrastructure.messaging.util;
24 import java.io.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.ObjectOutputStream;
27 import java.net.InetAddress;
28 import java.net.NetworkInterface;
29 import java.net.Socket;
30 import java.net.UnknownHostException;
31 import java.util.Enumeration;
33 import org.slf4j.ext.XLogger;
34 import org.slf4j.ext.XLoggerFactory;
37 * The Class MessagingUtils is a class with static methods used in IPC messaging for finding free ports, translating
38 * host names to addresses, serializing objects and flushing object streams.
40 * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
42 public final class MessagingUtils {
43 // The port number of the lowest user port, ports 0-1023 are system ports
44 private static final int LOWEST_USER_PORT = 1024;
47 * Port number is an unsigned 16-bit integer, so maximum port is 65535.
49 private static final int MAX_PORT_RANGE = 65535;
51 // Logger for this class
52 private static final XLogger LOGGER = XLoggerFactory.getXLogger(MessagingUtils.class);
55 * Private constructor used to prevent sub class instantiation.
57 private MessagingUtils() {
58 // Private constructor to block subclassing
62 * This method searches the availability of the port, if the requested port not available, this method will throw an
65 * @param port the port to check
66 * @return the port verified as being free
67 * @throws RuntimeException on port allocation errors
69 public static int checkPort(final int port) {
70 LOGGER.entry("Checking availability of port {}", port);
72 if (isPortAvailable(port)) {
73 LOGGER.debug("Port {} is available ", port);
76 LOGGER.debug("Port {} is not available", port);
77 throw new IllegalArgumentException("could not allocate requested port: " + port);
81 * This method searches the availability of the port, if the requested port not available,this method will increment
82 * the port number and check the availability of that port, this process will continue until it reaches max port
83 * range which is MAX_PORT_RANGE.
85 * @param port the first port to check
86 * @return the port that was found
87 * @throws RuntimeException on port allocation errors
89 public static int findPort(final int port) {
90 LOGGER.entry("Checking availability of port {}", port);
92 int availablePort = port;
94 while (availablePort <= MAX_PORT_RANGE) {
95 if (isPortAvailable(availablePort)) {
96 LOGGER.debug("Port {} is available ", availablePort);
99 LOGGER.debug("Port {} is not available", availablePort);
102 throw new IllegalArgumentException("could not find free available");
106 * Check if port is available or not.
108 * @param port the port to test
109 * @return true if port is available
111 public static boolean isPortAvailable(final int port) {
112 try (final Socket socket = new Socket("localhost", port)) {
114 } catch (final IOException ignoredException) {
115 LOGGER.trace("Port {} is available", port, ignoredException);
121 * Returns the local host address.
123 * @return the local host address
124 * @throws IllegalStateException if the local host's address cannot be found
126 public static InetAddress getHost() {
128 return InetAddress.getLocalHost();
129 } catch (final UnknownHostException e) {
130 throw new IllegalStateException(e.getMessage(), e);
135 * This method searches the availability of the port, if the requested port not available,this method will increment
136 * the port number and check the availability, this process will continue until it find port available.
138 * @param port the first port to check
139 * @return the port that was found
140 * @throws RuntimeException on port allocation errors
142 public static int allocateAddress(final int port) {
143 if (port < LOWEST_USER_PORT) {
144 throw new IllegalArgumentException("The port " + port + " is already in use");
146 return MessagingUtils.findPort(port);
150 * Get an Internet Address for the local host.
152 * @return an Internet address
153 * @throws UnknownHostException if the address of the local host cannot be found
155 public static InetAddress getLocalHostLanAddress() throws UnknownHostException {
157 InetAddress candidateAddress = null;
158 // Iterate all NICs (network interface cards)...
159 for (final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces
160 .hasMoreElements();) {
161 final NetworkInterface iface = ifaces.nextElement();
162 // Iterate all IP addresses assigned to each card...
163 for (final Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs
164 .hasMoreElements();) {
165 final InetAddress inetAddr = inetAddrs.nextElement();
166 if (!inetAddr.isLoopbackAddress()) {
168 if (inetAddr.isSiteLocalAddress()) {
169 // Found non-loopback site-local address. Return it
172 } else if (candidateAddress == null) {
173 // Found non-loopback address, but not
174 // necessarily site-local.
175 // Store it as a candidate to be returned if
176 // site-local address is not subsequently
178 candidateAddress = inetAddr;
179 // Note that we don't repeatedly assign
180 // non-loopback non-site-local addresses as
182 // only the first. For subsequent iterations,
183 // candidate will be non-null.
188 if (candidateAddress != null) {
189 // We did not find a site-local address, but we found some other
190 // non-loopback address.
191 // Server might have a non-site-local address assigned to its
192 // NIC (or it might be running
193 // IPv6 which deprecates the "site-local" concept).
194 // Return this non-loopback candidate address...
195 return candidateAddress;
197 // At this point, we did not find a non-loopback address.
198 // Fall back to returning whatever InetAddress.getLocalHost()
200 final InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
201 if (jdkSuppliedAddress == null) {
202 throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
204 return jdkSuppliedAddress;
205 } catch (final Exception e) {
206 final UnknownHostException unknownHostException =
207 new UnknownHostException("Failed to determine LAN address: " + e);
208 unknownHostException.initCause(e);
209 throw unknownHostException;
214 * This method serializes the message holder objects.
216 * @param object the object
219 public static byte[] serializeObject(final Object object) {
220 LOGGER.entry(object.getClass().getName());
221 final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
222 ObjectOutputStream oos = null;
224 oos = new ObjectOutputStream(bytesOut);
225 oos.writeObject(object);
226 } catch (final IOException e) {
227 LOGGER.warn("error on object serialization", e);
229 flushAndClose(oos, bytesOut);
231 return bytesOut.toByteArray();
235 * Flush and close an object stream and a byte array output stream.
237 * @param oos the object output stream
238 * @param bytesOut the byte array output stream
240 private static void flushAndClose(final ObjectOutputStream oos, final ByteArrayOutputStream bytesOut) {
246 if (bytesOut != null) {
250 } catch (final IOException e) {
251 LOGGER.error("Failed to close the Srialization operation");