Fix Javadoc errors
[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  * ================================================================================
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.core.infrastructure.messaging.util;
22
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;
31
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
37  * ports, translating 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
58     /**
59      * This method searches the availability of the port, if the requested port not available, this
60      * method will throw an exception.
61      *
62      * @param port the port to check
63      * @return the port verified as being free
64      * @throws RuntimeException on port allocation errors
65      */
66     public static int checkPort(final int port) {
67         LOGGER.entry("Checking availability of  port {}", port);
68
69         if (isPortAvailable(port)) {
70             LOGGER.debug("Port {} is available ", port);
71             return port;
72         }
73         LOGGER.debug("Port {} is not available", port);
74         throw new RuntimeException("could not allocate requested port: " + port);
75     }
76
77     /**
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}.
81      *
82      * @param port the first port to check
83      * @return the port that was found
84      * @throws RuntimeException on port allocation errors
85      */
86     public static int findPort(final int port) {
87         LOGGER.entry("Checking availability of  port {}", port);
88
89         int availablePort = port;
90
91         while (availablePort <= MAX_PORT_RANGE) {
92             if (isPortAvailable(availablePort)) {
93                 LOGGER.debug("Port {} is available ", availablePort);
94                 return availablePort;
95             }
96             LOGGER.debug("Port {} is not available", availablePort);
97             availablePort++;
98         }
99         throw new RuntimeException("could not find free available");
100     }
101
102     /**
103      * Check if port is available or not.
104      * 
105      * @param port the port to test
106      * @return true if port is available
107      */
108     public static boolean isPortAvailable(final int port) {
109         try (final Socket socket = new Socket("localhost", port)) {
110             return false;
111         } catch (final IOException ignoredException) {
112             LOGGER.trace("Port {} is available", port, ignoredException);
113             return true;
114         }
115     }
116
117     /**
118      * Returns the local host address.
119      *
120      * @return the local host address
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
132      * method will increment the port number and check the availability, this process will continue
133      * until it find port available.
134      *
135      * @param port the first port to check
136      * @return the port that was found
137      * @throws RuntimeException on port allocation errors
138      */
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");
142         }
143         return MessagingUtils.findPort(port);
144     }
145
146     /**
147      * Get an Internet Address for the local host.
148      *
149      * @return an Internet address
150      * @throws UnknownHostException if the address of the local host cannot be found
151      */
152     public static InetAddress getLocalHostLANAddress() throws UnknownHostException {
153         try {
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()) {
164
165                         if (inetAddr.isSiteLocalAddress()) {
166                             // Found non-loopback site-local address. Return it
167                             // immediately...
168                             return inetAddr;
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
174                             // found...
175                             candidateAddress = inetAddr;
176                             // Note that we don't repeatedly assign
177                             // non-loopback non-site-local addresses as
178                             // candidates,
179                             // only the first. For subsequent iterations,
180                             // candidate will be non-null.
181                         }
182                     }
183                 }
184             }
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;
193             }
194             // At this point, we did not find a non-loopback address.
195             // Fall back to returning whatever InetAddress.getLocalHost()
196             // returns...
197             final InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
198             if (jdkSuppliedAddress == null) {
199                 throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
200             }
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;
207         }
208     }
209
210     /**
211      * This method serializes the message holder objects.
212      *
213      * @param object the object
214      * @return byte[]
215      */
216     public static byte[] serializeObject(final Object object) {
217         LOGGER.entry(object.getClass().getName());
218         final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
219         ObjectOutputStream oos = null;
220         try {
221             oos = new ObjectOutputStream(bytesOut);
222             oos.writeObject(object);
223         } catch (final IOException e) {
224             LOGGER.warn("error on object serialization", e);
225         } finally {
226             flushAndClose(oos, bytesOut);
227         }
228         final byte[] bytes = bytesOut.toByteArray();
229         return bytes;
230     }
231
232     /**
233      * Flush and close an object stream and a byte array output stream.
234      *
235      * @param oos the object output stream
236      * @param bytesOut the byte array output stream
237      */
238     private static void flushAndClose(final ObjectOutputStream oos, final ByteArrayOutputStream bytesOut) {
239         try {
240             if (oos != null) {
241                 oos.flush();
242                 oos.close();
243             }
244             if (bytesOut != null) {
245                 bytesOut.close();
246             }
247
248         } catch (final IOException e) {
249             LOGGER.error("Failed to close the Srialization operation");
250             LOGGER.catching(e);
251         }
252     }
253 }