diff options
Diffstat (limited to 'utils')
6 files changed, 302 insertions, 61 deletions
diff --git a/utils/src/main/java/org/onap/policy/common/utils/resources/TextFileUtils.java b/utils/src/main/java/org/onap/policy/common/utils/resources/TextFileUtils.java new file mode 100644 index 00000000..5aeacf26 --- /dev/null +++ b/utils/src/main/java/org/onap/policy/common/utils/resources/TextFileUtils.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.resources; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.file.Files; + +/** + * The Class TextFileUtils is class that provides useful functions for handling text files. Functions to read and write + * text files to strings and strings are provided. + * + * @author Liam Fallon (liam.fallon@est.tech) + */ +public abstract class TextFileUtils { + private static final String UTF_8 = "UTF-8"; + private static final int READER_CHAR_BUFFER_SIZE_4096 = 4096; + + private TextFileUtils() { + // This class cannot be initialized + } + + /** + * Method to return the contents of a text file as a string. + * + * @param textFilePath The path to the file as a string + * @return A string containing the contents of the file + * @throws IOException on errors reading text from the file + */ + public static String getTextFileAsString(final String textFilePath) throws IOException { + final File textFile = new File(textFilePath); + return new String(Files.readAllBytes(textFile.toPath()), UTF_8); + } + + /** + * Method to write contents of a string to a text file. + * + * @param outString The string to write + * @param textFilePath The path to the file as a string + * @throws IOException on errors reading text from the file + */ + public static void putStringAsTextFile(final String outString, final String textFilePath) throws IOException { + final File textFile = new File(textFilePath); + putStringAsFile(outString, textFile); + } + + /** + * Method to write contents of a string to a text file. + * + * @param outString The string to write + * @param textFile The file to write the string to + * @throws IOException on errors reading text from the file + */ + public static void putStringAsFile(final String outString, final File textFile) throws IOException { + Files.write(textFile.toPath(), outString.getBytes(UTF_8)); + } + + /** + * Method to return the contents of a text steam as a string. + * + * @param textStream The stream + * @return A string containing the output of the stream as text + * @throws IOException on errors reading text from the file + */ + public static String getStreamAsString(final InputStream textStream) throws IOException { + return getReaderAsString(new InputStreamReader(textStream, UTF_8)); + } + + /** + * Method to return the contents of a reader steam as a string. This closes the reader after use + * + * @param textReader The reader + * @return A string containing the output of the reader as text + * @throws IOException on errors reading text from the file + */ + public static String getReaderAsString(final Reader textReader) throws IOException { + final StringBuilder builder = new StringBuilder(); + int charsRead = -1; + final char[] chars = new char[READER_CHAR_BUFFER_SIZE_4096]; + do { + charsRead = textReader.read(chars); + if (charsRead > 0) { + builder.append(chars, 0, charsRead); + } + } + while (charsRead > 0); + return builder.toString(); + } +} diff --git a/utils/src/main/java/org/onap/policy/common/utils/security/CryptoUtils.java b/utils/src/main/java/org/onap/policy/common/utils/security/CryptoUtils.java index ade8b467..ebe0483f 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/security/CryptoUtils.java +++ b/utils/src/main/java/org/onap/policy/common/utils/security/CryptoUtils.java @@ -64,36 +64,14 @@ public class CryptoUtils { private static final String RANDOM_NUMBER_GENERATOR = "SHA1PRNG"; /** - * This method is used as the main entry point when testing. - * + * CryptoUtils - encryption tool constructor. + * @param secretKey + * AES supports 128, 192 or 256-bit long key size, it can be plain text or generated with key generator */ - public static void main(String[] args) { - if (args.length == 3) { - if (args[0].equals("enc")) { - String encryptedValue = encrypt(args[1], args[2]); - logger.info("original value: " + args[1] + " encrypted value: " + encryptedValue); - } else if (args[0].equals("dec")) { - String decryptedValue = decrypt(args[1], args[2]); - logger.info("original value: " + args[1] + " decrypted value: " + decryptedValue); - } else { - logger.info("Unknown request: " + args[0]); - } - } else { - logger.info("Usage : CryptoUtils enc/dec password secretKey"); - logger.info("Example: CryptoUtils enc HelloWorld 1234"); - logger.info("Example: CryptoUtils dec enc:112233 1234"); - } - } - public CryptoUtils(SecretKeySpec secretKeySpec) { this.secretKeySpec = secretKeySpec; } - /** - * CryptoUtils - encryption tool constructor. - * @param secretKey - * AES supports 128, 192 or 256-bit long key size, it can be plain text or generated with key generator - */ public CryptoUtils(String secretKey) { this.secretKeySpec = readSecretKeySpec(secretKey); } @@ -256,4 +234,26 @@ public class CryptoUtils { public static Boolean isEncrypted(String value) { return (value != null && value.startsWith("enc:")); } + + /** + * This method is used as the main entry point when testing. + * + */ + public static void main(String[] args) { + if (args.length == 3) { + if ("enc".equals(args[0])) { + String encryptedValue = encrypt(args[1], args[2]); + logger.info("original value: " + args[1] + " encrypted value: " + encryptedValue); + } else if ("dec".equals(args[0])) { + String decryptedValue = decrypt(args[1], args[2]); + logger.info("original value: " + args[1] + " decrypted value: " + decryptedValue); + } else { + logger.info("Unknown request: " + args[0]); + } + } else { + logger.info("Usage : CryptoUtils enc/dec password secretKey"); + logger.info("Example: CryptoUtils enc HelloWorld 1234"); + logger.info("Example: CryptoUtils dec enc:112233 1234"); + } + } }
\ No newline at end of file diff --git a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java index 8bf89d56..13cd6de8 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java +++ b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java @@ -31,10 +31,15 @@ import org.slf4j.LoggerFactory; * Manages a series of services. The services are started in order, and stopped in reverse * order. */ -public class ServiceManager { +public class ServiceManager implements Startable { private static final Logger logger = LoggerFactory.getLogger(ServiceManager.class); /** + * Manager name. + */ + private final String name; + + /** * Services to be started/stopped. */ private final Deque<Service> items = new LinkedList<>(); @@ -45,6 +50,25 @@ public class ServiceManager { private boolean running; /** + * Constructs the object, with a default name. + */ + public ServiceManager() { + this("service manager"); + } + + /** + * Constructs the object. + * @param name the manager's name, used for logging purposes + */ + public ServiceManager(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + /** * Adds a pair of service actions to the manager. * * @param stepName name to be logged when the service is started/stopped @@ -54,7 +78,7 @@ public class ServiceManager { */ public synchronized ServiceManager addAction(String stepName, RunnableWithEx starter, RunnableWithEx stopper) { if (running) { - throw new IllegalStateException("services are already running; cannot add " + stepName); + throw new IllegalStateException(name + " is already running; cannot add " + stepName); } items.add(new Service(stepName, starter, stopper)); @@ -71,44 +95,47 @@ public class ServiceManager { */ public synchronized ServiceManager addService(String stepName, Startable service) { if (running) { - throw new IllegalStateException("services are already running; cannot add " + stepName); + throw new IllegalStateException(name + " is already running; cannot add " + stepName); } items.add(new Service(stepName, () -> service.start(), () -> service.stop())); return this; } - /** - * Starts each service, in order. If a service throws an exception, then the - * previously started services are stopped, in reverse order. - * - * @throws ServiceManagerException if a service fails to start - */ - public synchronized void start() throws ServiceManagerException { + @Override + public synchronized boolean isAlive() { + return running; + } + + @Override + public synchronized boolean start() { if (running) { - throw new IllegalStateException("services are already running"); + throw new IllegalStateException(name + " is already running"); } + logger.info("{} starting", name); + // tracks the services that have been started so far Deque<Service> started = new LinkedList<>(); Exception ex = null; for (Service item : items) { try { - logger.info("starting {}", item.stepName); + logger.info("{} starting {}", name, item.stepName); item.starter.run(); started.add(item); } catch (Exception e) { - logger.error("failed to start {}; rewinding steps", item.stepName); + logger.error("{} failed to start {}; rewinding steps", name, item.stepName); ex = e; break; } } if (ex == null) { + logger.info("{} started", name); running = true; - return; + return true; } // one of the services failed to start - rewind those we've previously started @@ -116,26 +143,27 @@ public class ServiceManager { rewind(started); } catch (ServiceManagerException e) { - logger.error("rewind failed", e); + logger.error("{} rewind failed", name, e); } throw new ServiceManagerException(ex); } - /** - * Stops the services, in reverse order from which they were started. Stops all of the - * services, even if one of the "stop" functions throws an exception. Assumes that - * {@link #start()} has completed successfully. - * - * @throws ServiceManagerException if a service fails to stop - */ - public synchronized void stop() throws ServiceManagerException { + @Override + public synchronized boolean stop() { if (!running) { - throw new IllegalStateException("services are not running"); + throw new IllegalStateException(name + " is not running"); } running = false; rewind(items); + + return true; + } + + @Override + public void shutdown() { + stop(); } /** @@ -148,21 +176,25 @@ public class ServiceManager { private void rewind(Deque<Service> running) throws ServiceManagerException { Exception ex = null; + logger.info("{} stopping", name); + // stop everything, in reverse order Iterator<Service> it = running.descendingIterator(); while (it.hasNext()) { Service item = it.next(); try { - logger.info("stopping {}", item.stepName); + logger.info("{} stopping {}", name, item.stepName); item.stopper.run(); } catch (Exception e) { - logger.error("failed to stop {}", item.stepName); + logger.error("{} failed to stop {}", name, item.stepName); ex = e; // do NOT break or re-throw, as we must stop ALL remaining items } } + logger.info("{} stopped", name); + if (ex != null) { throw new ServiceManagerException(ex); } @@ -185,6 +217,6 @@ public class ServiceManager { @FunctionalInterface public static interface RunnableWithEx { - public void run() throws Exception; + void run() throws Exception; } } diff --git a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java index 3daa441a..ac37b6b4 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java +++ b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java @@ -23,7 +23,7 @@ package org.onap.policy.common.utils.services; /** * Exceptions thrown by the ServiceManager. */ -public class ServiceManagerException extends Exception { +public class ServiceManagerException extends RuntimeException { private static final long serialVersionUID = 1L; public ServiceManagerException() { diff --git a/utils/src/test/java/org/onap/policy/common/utils/resources/TextFileUtilsTest.java b/utils/src/test/java/org/onap/policy/common/utils/resources/TextFileUtilsTest.java new file mode 100644 index 00000000..7f246ab2 --- /dev/null +++ b/utils/src/test/java/org/onap/policy/common/utils/resources/TextFileUtilsTest.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.resources; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.junit.Test; + +/** + * Test text file utilities. + * @author Liam Fallon (liam.fallon@est.tech) + */ +public class TextFileUtilsTest { + + private static final String FILE_CONTENT = "This is the contents of a text file"; + + @Test + public void test() throws IOException { + final File tempTextFile = File.createTempFile("Test", "txt"); + + TextFileUtils.putStringAsTextFile(FILE_CONTENT, tempTextFile.getAbsolutePath()); + + final String textFileString0 = TextFileUtils.getTextFileAsString(tempTextFile.getAbsolutePath()); + assertEquals(FILE_CONTENT, textFileString0); + + final FileInputStream fis = new FileInputStream(tempTextFile); + final String textFileString1 = TextFileUtils.getStreamAsString(fis); + assertEquals(textFileString0, textFileString1); + + } +} diff --git a/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java b/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java index 49c0599b..b7774a5e 100644 --- a/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java +++ b/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java @@ -23,6 +23,8 @@ package org.onap.policy.common.utils.services; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -36,7 +38,8 @@ import org.onap.policy.common.capabilities.Startable; import org.onap.policy.common.utils.services.ServiceManager.RunnableWithEx; public class ServiceManagerTest { - private static final String ALREADY_RUNNING = "services are already running"; + private static final String MY_NAME = "my-name"; + private static final String ALREADY_RUNNING = MY_NAME + " is already running"; private static final String EXPECTED_EXCEPTION = "expected exception"; private ServiceManager svcmgr; @@ -46,7 +49,17 @@ public class ServiceManagerTest { */ @Before public void setUp() { - svcmgr = new ServiceManager(); + svcmgr = new ServiceManager(MY_NAME); + } + + @Test + public void testServiceName() { + assertEquals("service manager", new ServiceManager().getName()); + } + + @Test + public void testGetName() { + assertEquals(MY_NAME, svcmgr.getName()); } @Test @@ -106,16 +119,20 @@ public class ServiceManagerTest { Startable start1 = mock(Startable.class); svcmgr.addService("test start", start1); - svcmgr.start(); + assertTrue(svcmgr.start()); + + assertTrue(svcmgr.isAlive()); verify(start1).start(); verify(start1, never()).stop(); // cannot re-start - assertThatIllegalStateException().isThrownBy(() -> svcmgr.start()) - .withMessage(ALREADY_RUNNING); + assertThatIllegalStateException().isThrownBy(() -> svcmgr.start()).withMessage(ALREADY_RUNNING); // verify that it didn't try to start the service again verify(start1).start(); + + // still running + assertTrue(svcmgr.isAlive()); } @Test @@ -140,6 +157,8 @@ public class ServiceManagerTest { assertThatThrownBy(() -> svcmgr.start()).isInstanceOf(ServiceManagerException.class).hasCause(exception); + assertFalse(svcmgr.isAlive()); + verify(start1).start(); verify(start2).start(); verify(start3).start(); @@ -177,6 +196,8 @@ public class ServiceManagerTest { svcmgr.addService("fifth test start rewind", start5); assertThatThrownBy(() -> svcmgr.start()).isInstanceOf(ServiceManagerException.class).hasCause(exception); + + assertFalse(svcmgr.isAlive()); } @Test @@ -185,8 +206,7 @@ public class ServiceManagerTest { svcmgr.addService("first stop", start1); // cannot stop until started - assertThatIllegalStateException().isThrownBy(() -> svcmgr.stop()) - .withMessage("services are not running"); + assertThatIllegalStateException().isThrownBy(() -> svcmgr.stop()).withMessage(MY_NAME + " is not running"); // verify that it didn't try to stop the service verify(start1, never()).stop(); @@ -194,7 +214,9 @@ public class ServiceManagerTest { // start it svcmgr.start(); - svcmgr.stop(); + assertTrue(svcmgr.stop()); + + assertFalse(svcmgr.isAlive()); verify(start1).stop(); } @@ -218,6 +240,28 @@ public class ServiceManagerTest { verify(stop1).run(); verify(start2).start(); verify(start2).stop(); + + assertFalse(svcmgr.isAlive()); + } + + @Test + public void testShutdown() throws Exception { + Startable start1 = mock(Startable.class); + svcmgr.addService("first stop", start1); + + // cannot stop until started + assertThatIllegalStateException().isThrownBy(() -> svcmgr.shutdown()).withMessage(MY_NAME + " is not running"); + + // verify that it didn't try to stop the service + verify(start1, never()).stop(); + + // start it + svcmgr.start(); + + svcmgr.shutdown(); + + assertFalse(svcmgr.isAlive()); + verify(start1).stop(); } @Test @@ -242,6 +286,8 @@ public class ServiceManagerTest { assertThatThrownBy(() -> svcmgr.stop()).isInstanceOf(ServiceManagerException.class).hasCause(exception); + assertFalse(svcmgr.isAlive()); + // all of them should have been stopped, in reverse order assertEquals(Arrays.asList("rewind5", "rewind4", "rewind3", "rewind2", "rewind1").toString(), lst.toString()); } |