ba84ca069c0eaf0182ed37afa873f3b5768d5acf
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019 Nordix Foundation.
5  *  Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.apex.core.infrastructure.messaging.util;
24
25 import java.io.ByteArrayOutputStream;
26 import java.io.IOException;
27 import java.io.ObjectOutputStream;
28 import java.net.InetAddress;
29 import java.net.NetworkInterface;
30 import java.net.Socket;
31 import java.net.UnknownHostException;
32 import java.util.Enumeration;
33 import lombok.AccessLevel;
34 import lombok.NoArgsConstructor;
35 import org.slf4j.ext.XLogger;
36 import org.slf4j.ext.XLoggerFactory;
37
38 /**
39  * The Class MessagingUtils is a class with static methods used in IPC messaging for finding free ports, translating
40  * host names to addresses, serializing objects and flushing object streams.
41  *
42  * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
43  */
44 @NoArgsConstructor(access = AccessLevel.PRIVATE)
45 public final class MessagingUtils {
46     // The port number of the lowest user port, ports 0-1023 are system ports
47     private static final int LOWEST_USER_PORT = 1024;
48
49     /**
50      * Port number is an unsigned 16-bit integer, so maximum port is 65535.
51      */
52     private static final int MAX_PORT_RANGE = 65535;
53
54     // Logger for this class
55     private static final XLogger LOGGER = XLoggerFactory.getXLogger(MessagingUtils.class);
56
57     /**
58      * This method searches the availability of the port, if the requested port not available, this method will throw an
59      * exception.
60      *
61      * @param port the port to check
62      * @return the port verified as being free
63      * @throws RuntimeException on port allocation errors
64      */
65     public static int checkPort(final int port) {
66         LOGGER.entry("Checking availability of  port {}", port);
67
68         if (isPortAvailable(port)) {
69             LOGGER.debug("Port {} is available ", port);
70             return port;
71         }
72         LOGGER.debug("Port {} is not available", port);
73         throw new IllegalArgumentException("could not allocate requested port: " + port);
74     }
75
76     /**
77      * This method searches the availability of the port, if the requested port not available,this method will increment
78      * the port number and check the availability of that port, this process will continue until it reaches max port
79      * range which is MAX_PORT_RANGE.
80      *
81      * @param port the first port to check
82      * @return the port that was found
83      * @throws RuntimeException on port allocation errors
84      */
85     public static int findPort(final int port) {
86         LOGGER.entry("Checking availability of  port {}", port);
87
88         int availablePort = port;
89
90         while (availablePort <= MAX_PORT_RANGE) {
91             if (isPortAvailable(availablePort)) {
92                 LOGGER.debug("Port {} is available ", availablePort);
93                 return availablePort;
94             }
95             LOGGER.debug("Port {} is not available", availablePort);
96             availablePort++;
97         }
98         throw new IllegalArgumentException("could not find free available");
99     }
100
101     /**
102      * Check if port is available or not.
103      *
104      * @param port the port to test
105      * @return true if port is available
106      */
107     public static boolean isPortAvailable(final int port) {
108         try (final Socket socket = new Socket("localhost", port)) {
109             return false;
110         } catch (final IOException ignoredException) {
111             LOGGER.trace("Port {} is available", port, ignoredException);
112             return true;
113         }
114     }
115
116     /**
117      * Returns the local host address.
118      *
119      * @return the local host address
120      * @throws IllegalStateException if the local host's address cannot be found
121      */
122     public static InetAddress getHost() {
123         try {
124             return InetAddress.getLocalHost();
125         } catch (final UnknownHostException e) {
126             throw new IllegalStateException(e.getMessage(), e);
127         }
128     }
129
130     /**
131      * This method searches the availability of the port, if the requested port not available,this method will increment
132      * the port number and check the availability, this process will continue until it find port available.
133      *
134      * @param port the first port to check
135      * @return the port that was found
136      * @throws RuntimeException on port allocation errors
137      */
138     public static int allocateAddress(final int port) {
139         if (port < LOWEST_USER_PORT) {
140             throw new IllegalArgumentException("The port " + port + "  is already in use");
141         }
142         return MessagingUtils.findPort(port);
143     }
144
145     /**
146      * Get an Internet Address for the local host.
147      *
148      * @return an Internet address
149      * @throws UnknownHostException if the address of the local host cannot be found
150      */
151     public static InetAddress getLocalHostLanAddress() throws UnknownHostException {
152         try {
153             InetAddress candidateAddress = null;
154             // Iterate all NICs (network interface cards)...
155             for (final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces
156                     .hasMoreElements();) {
157                 final NetworkInterface iface = ifaces.nextElement();
158                 // Iterate all IP addresses assigned to each card...
159                 for (final Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs
160                         .hasMoreElements();) {
161                     final InetAddress inetAddr = inetAddrs.nextElement();
162                     if (!inetAddr.isLoopbackAddress()) {
163
164                         if (inetAddr.isSiteLocalAddress()) {
165                             // Found non-loopback site-local address. Return it
166                             // immediately...
167                             return inetAddr;
168                         } else if (candidateAddress == null) {
169                             // Found non-loopback address, but not
170                             // necessarily site-local.
171                             // Store it as a candidate to be returned if
172                             // site-local address is not subsequently
173                             // found...
174                             candidateAddress = inetAddr;
175                             // Note that we don't repeatedly assign
176                             // non-loopback non-site-local addresses as
177                             // candidates,
178                             // only the first. For subsequent iterations,
179                             // candidate will be non-null.
180                         }
181                     }
182                 }
183             }
184             if (candidateAddress != null) {
185                 // We did not find a site-local address, but we found some other
186                 // non-loopback address.
187                 // Server might have a non-site-local address assigned to its
188                 // NIC (or it might be running
189                 // IPv6 which deprecates the "site-local" concept).
190                 // Return this non-loopback candidate address...
191                 return candidateAddress;
192             }
193             // At this point, we did not find a non-loopback address.
194             // Fall back to returning whatever InetAddress.getLocalHost()
195             // returns...
196             final InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
197             if (jdkSuppliedAddress == null) {
198                 throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
199             }
200             return jdkSuppliedAddress;
201         } catch (final Exception e) {
202             final UnknownHostException unknownHostException =
203                     new UnknownHostException("Failed to determine LAN address: " + e);
204             unknownHostException.initCause(e);
205             throw unknownHostException;
206         }
207     }
208
209     /**
210      * This method serializes the message holder objects.
211      *
212      * @param object the object
213      * @return byte[]
214      */
215     public static byte[] serializeObject(final Object object) {
216         LOGGER.entry(object.getClass().getName());
217         final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
218         try (ObjectOutputStream oos = new ObjectOutputStream(bytesOut)) {
219             oos.writeObject(object);
220         } catch (final IOException e) {
221             LOGGER.warn("error on object serialization", e);
222         }
223         return bytesOut.toByteArray();
224     }
225 }