Changes for checkstyle 8.32
[policy/apex-pdp.git] / core / core-infrastructure / src / main / java / org / onap / policy / apex / core / infrastructure / messaging / util / MessagingUtils.java
1 /*-
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.core.infrastructure.messaging.util;
23
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;
32 import org.slf4j.ext.XLogger;
33 import org.slf4j.ext.XLoggerFactory;
34
35 /**
36  * The Class MessagingUtils is a class with static methods used in IPC messaging for finding free ports, translating
37  * host names to addresses, serializing objects and flushing object streams.
38  *
39  * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
40  */
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;
44
45     /**
46      * Port number is an unsigned 16-bit integer, so maximum port is 65535.
47      */
48     private static final int MAX_PORT_RANGE = 65535;
49
50     // Logger for this class
51     private static final XLogger LOGGER = XLoggerFactory.getXLogger(MessagingUtils.class);
52
53     /**
54      * Private constructor used to prevent sub class instantiation.
55      */
56     private MessagingUtils() {
57         // Private constructor to block subclassing
58     }
59
60     /**
61      * This method searches the availability of the port, if the requested port not available, this method will throw an
62      * exception.
63      *
64      * @param port the port to check
65      * @return the port verified as being free
66      * @throws RuntimeException on port allocation errors
67      */
68     public static int checkPort(final int port) {
69         LOGGER.entry("Checking availability of  port {}", port);
70
71         if (isPortAvailable(port)) {
72             LOGGER.debug("Port {} is available ", port);
73             return port;
74         }
75         LOGGER.debug("Port {} is not available", port);
76         throw new IllegalArgumentException("could not allocate requested port: " + port);
77     }
78
79     /**
80      * This method searches the availability of the port, if the requested port not available,this method will increment
81      * the port number and check the availability of that port, this process will continue until it reaches max port
82      * range which is MAX_PORT_RANGE.
83      *
84      * @param port the first port to check
85      * @return the port that was found
86      * @throws RuntimeException on port allocation errors
87      */
88     public static int findPort(final int port) {
89         LOGGER.entry("Checking availability of  port {}", port);
90
91         int availablePort = port;
92
93         while (availablePort <= MAX_PORT_RANGE) {
94             if (isPortAvailable(availablePort)) {
95                 LOGGER.debug("Port {} is available ", availablePort);
96                 return availablePort;
97             }
98             LOGGER.debug("Port {} is not available", availablePort);
99             availablePort++;
100         }
101         throw new IllegalArgumentException("could not find free available");
102     }
103
104     /**
105      * Check if port is available or not.
106      *
107      * @param port the port to test
108      * @return true if port is available
109      */
110     public static boolean isPortAvailable(final int port) {
111         try (final Socket socket = new Socket("localhost", port)) {
112             return false;
113         } catch (final IOException ignoredException) {
114             LOGGER.trace("Port {} is available", port, ignoredException);
115             return true;
116         }
117     }
118
119     /**
120      * Returns the local host address.
121      *
122      * @return the local host address
123      * @throws IllegalStateException if the local host's address cannot be found
124      */
125     public static InetAddress getHost() {
126         try {
127             return InetAddress.getLocalHost();
128         } catch (final UnknownHostException e) {
129             throw new IllegalStateException(e.getMessage(), e);
130         }
131     }
132
133     /**
134      * This method searches the availability of the port, if the requested port not available,this method will increment
135      * the port number and check the availability, this process will continue until it find port available.
136      *
137      * @param port the first port to check
138      * @return the port that was found
139      * @throws RuntimeException on port allocation errors
140      */
141     public static int allocateAddress(final int port) {
142         if (port < LOWEST_USER_PORT) {
143             throw new IllegalArgumentException("The port " + port + "  is already in use");
144         }
145         return MessagingUtils.findPort(port);
146     }
147
148     /**
149      * Get an Internet Address for the local host.
150      *
151      * @return an Internet address
152      * @throws UnknownHostException if the address of the local host cannot be found
153      */
154     public static InetAddress getLocalHostLanAddress() throws UnknownHostException {
155         try {
156             InetAddress candidateAddress = null;
157             // Iterate all NICs (network interface cards)...
158             for (final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces
159                     .hasMoreElements();) {
160                 final NetworkInterface iface = ifaces.nextElement();
161                 // Iterate all IP addresses assigned to each card...
162                 for (final Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs
163                         .hasMoreElements();) {
164                     final InetAddress inetAddr = inetAddrs.nextElement();
165                     if (!inetAddr.isLoopbackAddress()) {
166
167                         if (inetAddr.isSiteLocalAddress()) {
168                             // Found non-loopback site-local address. Return it
169                             // immediately...
170                             return inetAddr;
171                         } else if (candidateAddress == null) {
172                             // Found non-loopback address, but not
173                             // necessarily site-local.
174                             // Store it as a candidate to be returned if
175                             // site-local address is not subsequently
176                             // found...
177                             candidateAddress = inetAddr;
178                             // Note that we don't repeatedly assign
179                             // non-loopback non-site-local addresses as
180                             // candidates,
181                             // only the first. For subsequent iterations,
182                             // candidate will be non-null.
183                         }
184                     }
185                 }
186             }
187             if (candidateAddress != null) {
188                 // We did not find a site-local address, but we found some other
189                 // non-loopback address.
190                 // Server might have a non-site-local address assigned to its
191                 // NIC (or it might be running
192                 // IPv6 which deprecates the "site-local" concept).
193                 // Return this non-loopback candidate address...
194                 return candidateAddress;
195             }
196             // At this point, we did not find a non-loopback address.
197             // Fall back to returning whatever InetAddress.getLocalHost()
198             // returns...
199             final InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
200             if (jdkSuppliedAddress == null) {
201                 throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
202             }
203             return jdkSuppliedAddress;
204         } catch (final Exception e) {
205             final UnknownHostException unknownHostException =
206                     new UnknownHostException("Failed to determine LAN address: " + e);
207             unknownHostException.initCause(e);
208             throw unknownHostException;
209         }
210     }
211
212     /**
213      * This method serializes the message holder objects.
214      *
215      * @param object the object
216      * @return byte[]
217      */
218     public static byte[] serializeObject(final Object object) {
219         LOGGER.entry(object.getClass().getName());
220         final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
221         ObjectOutputStream oos = null;
222         try {
223             oos = new ObjectOutputStream(bytesOut);
224             oos.writeObject(object);
225         } catch (final IOException e) {
226             LOGGER.warn("error on object serialization", e);
227         } finally {
228             flushAndClose(oos, bytesOut);
229         }
230         return bytesOut.toByteArray();
231     }
232
233     /**
234      * Flush and close an object stream and a byte array output stream.
235      *
236      * @param oos the object output stream
237      * @param bytesOut the byte array output stream
238      */
239     private static void flushAndClose(final ObjectOutputStream oos, final ByteArrayOutputStream bytesOut) {
240         try {
241             if (oos != null) {
242                 oos.flush();
243                 oos.close();
244             }
245             if (bytesOut != null) {
246                 bytesOut.close();
247             }
248
249         } catch (final IOException e) {
250             LOGGER.error("Failed to close the Srialization operation");
251             LOGGER.catching(e);
252         }
253     }
254 }