diff options
author | Bogumil Zebek <bogumil.zebek@nokia.com> | 2021-03-09 12:54:38 +0100 |
---|---|---|
committer | Zebek Bogumil <bogumil.zebek@nokia.com> | 2021-03-10 09:31:58 +0100 |
commit | 4af5241ab25b0103d8ea680789aaf9a8696dfc75 (patch) | |
tree | 36ccae11ebf094aa1ddd65df309b7531ce0db1ff /src/main/java/org/onap/pnfsimulator/simulator | |
parent | c9975cb96ba4e0208e72399ed80f909beb95d9d9 (diff) |
Move pnf simulator to the new repo
In the first phase we renamed project from pnf simulator to vesclient.
Next steps: package rename, update Readme.md, upgrade project dependencies.
Issue-ID: INT-1869
Signed-off-by: Bogumil Zebek<bogumil.zebek@nokia.com>
Change-Id: I7714792f9739eb746c9c533e8ef41b9618a3a1d9
Diffstat (limited to 'src/main/java/org/onap/pnfsimulator/simulator')
32 files changed, 2067 insertions, 0 deletions
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java new file mode 100644 index 0000000..878591b --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.io.IOException; + +import org.onap.pnfsimulator.template.Template; +import org.onap.pnfsimulator.template.TemplateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DbTemplateReader implements TemplateReader { + private final TemplateService service; + private final Gson gson; + + @Autowired + public DbTemplateReader(TemplateService service, Gson gson) { + this.service = service; + this.gson = gson; + } + + @Override + public JsonObject readTemplate(String templateName) throws IOException { + Template template = service.get(templateName).orElseThrow(() -> new IOException("Template does not exist")); + JsonElement jsonElement = gson.toJsonTree(template.getContent()); + return jsonElement.getAsJsonObject(); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java b/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java new file mode 100644 index 0000000..01f6508 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +public class EventNotFoundException extends RuntimeException { + private static final String NOT_FOUND = "Not found an event with id: "; + + public EventNotFoundException(String eventId) { + super(NOT_FOUND + eventId); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java new file mode 100644 index 0000000..a405a2e --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class FilesystemTemplateReader implements TemplateReader { + + private final Path templatesDir; + private final Gson gson; + + @Autowired + FilesystemTemplateReader(@Value("${templates.dir}") String templatesDir, Gson gson) { + this.templatesDir = Paths.get(templatesDir); + this.gson = gson; + } + + public JsonObject readTemplate(String templateFileName) throws IOException { + Path absTemplateFilePath = templatesDir.resolve(templateFileName); + try (Stream<String> lines = Files.lines(absTemplateFilePath)) { + String content = lines.collect(Collectors.joining("\n")); + return gson.fromJson(content, JsonObject.class); + } + } +} + diff --git a/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java new file mode 100644 index 0000000..4a7cf02 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java @@ -0,0 +1,26 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +@FunctionalInterface +public interface IncrementProvider { + int getAndIncrement(String id); +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java new file mode 100644 index 0000000..9d4d3ec --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class IncrementProviderImpl implements IncrementProvider { + private final EventDataRepository repository; + + @Autowired + public IncrementProviderImpl(EventDataRepository repository) { + this.repository = repository; + } + + @Override + public int getAndIncrement(String id) { + EventData eventData = repository.findById(id) + .orElseThrow(() -> new EventNotFoundException(id)); + int value = eventData.getIncrementValue() + 1; + eventData.setIncrementValue(value); + repository.save(eventData); + return value; + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java b/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java new file mode 100644 index 0000000..da0026a --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java @@ -0,0 +1,134 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator; + +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.stream.Collectors; + +public enum JsonTokenProcessor { + STRING(JsonToken.STRING) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + String originalString = reader.nextString(); + if (keywordsExtractor.isPrimitive(originalString)) { + writer.value(keywordsExtractor.substitutePrimitiveKeyword(originalString)); + } else { + String possibleSubstitution = Arrays.stream(originalString.split(" ")) + .map(singleWord -> keywordsExtractor.substituteStringKeyword(singleWord, incrementValue)).collect( + Collectors.joining(" ")); + writer.value(originalString.equals(possibleSubstitution) ? originalString : possibleSubstitution); + } + } + }, + BEGIN_ARRAY(JsonToken.BEGIN_ARRAY) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.beginArray(); + writer.beginArray(); + } + }, + END_ARRAY(JsonToken.END_ARRAY) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.endArray(); + writer.endArray(); + } + }, + BEGIN_OBJECT(JsonToken.BEGIN_OBJECT) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.beginObject(); + writer.beginObject(); + } + }, + END_OBJECT(JsonToken.END_OBJECT) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.endObject(); + writer.endObject(); + } + }, + NAME(JsonToken.NAME) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + writer.name(reader.nextName()); + } + }, + NUMBER(JsonToken.NUMBER) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + writer.value(new BigDecimal(reader.nextString())); + } + }, + BOOLEAN(JsonToken.BOOLEAN) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + writer.value(reader.nextBoolean()); + } + }, + NULL(JsonToken.NULL) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.nextNull(); + writer.nullValue(); + } + }, + END_DOCUMENT(JsonToken.END_DOCUMENT) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + // do nothing + } + }; + + private JsonToken jsonToken; + + JsonTokenProcessor(JsonToken jsonToken) { + this.jsonToken = jsonToken; + } + + boolean isProcessorFor(JsonToken jsonToken) { + return this.jsonToken == jsonToken; + } + + abstract void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) throws IOException; + + private static final String INVALID_JSON_BODY_UNSUPPORTED_JSON_TOKEN = "Invalid json body. Unsupported JsonToken."; + + static JsonTokenProcessor getProcessorFor(JsonToken jsonToken) throws IOException { + return Arrays.stream(JsonTokenProcessor.values()).filter(processor -> processor.isProcessorFor(jsonToken)).findFirst() + .orElseThrow(() -> new IOException(INVALID_JSON_BODY_UNSUPPORTED_JSON_TOKEN)); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java new file mode 100644 index 0000000..2dc52a1 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java @@ -0,0 +1,129 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator; + +import static io.vavr.API.$; +import static io.vavr.API.Case; +import static io.vavr.API.Match; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getEpochSecond; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomLimitedInteger; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomInteger; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomLimitedString; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomString; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomPrimitiveInteger; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getTimestampPrimitive; +import static org.onap.pnfsimulator.simulator.keywords.NonParameterKeywordPatterns.$nonParameterKeyword; +import static org.onap.pnfsimulator.simulator.keywords.SingleParameterKeywordPatterns.$singleParameterKeyword; +import static org.onap.pnfsimulator.simulator.keywords.TwoParameterKeywordPatterns.$twoParameterKeyword; + +import io.vavr.API.Match.Pattern1; +import org.onap.pnfsimulator.simulator.keywords.Keyword; +import org.onap.pnfsimulator.simulator.keywords.NonParameterKeyword; +import org.onap.pnfsimulator.simulator.keywords.SingleParameterKeyword; +import org.onap.pnfsimulator.simulator.keywords.TwoParameterKeyword; +import org.springframework.stereotype.Component; + +@Component +public class KeywordsExtractor { + + String substituteStringKeyword(String text, int increment) { + return Match(text).of( + Case(isRandomStringParamKeyword(), + spk -> spk.substituteKeyword(getRandomString().apply(spk.getAdditionalParameter())) + ), + Case(isRandomStringNonParamKeyword(), + npk -> npk.substituteKeyword(getRandomLimitedString().apply()) + ), + Case(isRandomIntegerParamKeyword(), + tpk -> tpk.substituteKeyword(getRandomInteger().apply( + tpk.getAdditionalParameter1(), + tpk.getAdditionalParameter2() + ) + ) + ), + Case(isRandomIntegerNonParamKeyword(), + npk -> npk.substituteKeyword(getRandomLimitedInteger().apply()) + ), + Case(isIncrementKeyword(), + ik -> ik.substituteKeyword(String.valueOf(increment)) + ), + Case(isTimestampNonParamKeyword(), + npk -> npk.substituteKeyword(getEpochSecond().apply()) + ), + Case( + $(), + () -> text + )); + } + + Long substitutePrimitiveKeyword(String text) { + return Match(text).of( + Case(isRandomPrimitiveIntegerParamKeyword(), + tpk -> + getRandomPrimitiveInteger().apply(tpk.getAdditionalParameter1(), tpk.getAdditionalParameter2())), + Case(isTimestampPrimitiveNonParamKeyword(), + tpk -> + getTimestampPrimitive().apply()), + Case( + $(), + () -> 0L + )); + } + + boolean isPrimitive(String text) { + return Match(text).of( + Case(isRandomPrimitiveIntegerParamKeyword(), () -> true), + Case(isTimestampPrimitiveNonParamKeyword(), () -> true), + Case($(), () -> false)); + } + + private Pattern1<String, SingleParameterKeyword> isRandomStringParamKeyword() { + return $singleParameterKeyword($(spk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(spk, "RandomString"))); + } + + private Pattern1<String, NonParameterKeyword> isRandomStringNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "RandomString"))); + } + + private Pattern1<String, NonParameterKeyword> isIncrementKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "Increment"))); + } + + private Pattern1<String, TwoParameterKeyword> isRandomIntegerParamKeyword() { + return $twoParameterKeyword($(tpk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(tpk, "RandomInteger"))); + } + + private Pattern1<String, TwoParameterKeyword> isRandomPrimitiveIntegerParamKeyword() { + return $twoParameterKeyword($(tpk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(tpk, "RandomPrimitiveInteger"))); + } + + private Pattern1<String, NonParameterKeyword> isTimestampPrimitiveNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "TimestampPrimitive"))); + } + + private Pattern1<String, NonParameterKeyword> isRandomIntegerNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "RandomInteger"))); + } + + private Pattern1<String, NonParameterKeyword> isTimestampNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "Timestamp"))); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java new file mode 100644 index 0000000..ac80647 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +import org.springframework.stereotype.Component; + +@Component +public class KeywordsHandler { + + private KeywordsExtractor keywordsExtractor; + private IncrementProvider incrementProvider; + + public KeywordsHandler(KeywordsExtractor keywordsExtractor, IncrementProvider incrementProvider) { + this.keywordsExtractor = keywordsExtractor; + this.incrementProvider = incrementProvider; + } + + public JsonElement substituteKeywords(JsonElement jsonBody, String jobId) { + int counter = incrementProvider.getAndIncrement(jobId); + try ( + JsonReader reader = new JsonReader(new StringReader(jsonBody.toString())); + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + ) { + modify(reader, jsonWriter, counter); + return new Gson().fromJson(stringWriter.getBuffer().toString(), JsonElement.class); + } catch (IOException e) { + throw new KeywordsHandlerException(e); + } + } + + private void modify(JsonReader reader, JsonWriter writer, int incrementValue) throws IOException { + JsonTokenProcessor jsonTokenProcessor; + do { + JsonToken token = reader.peek(); + jsonTokenProcessor = JsonTokenProcessor.getProcessorFor(token); + jsonTokenProcessor.process(reader, writer, incrementValue, keywordsExtractor); + } while (isJsonProcessingFinished(jsonTokenProcessor)); + } + + private boolean isJsonProcessingFinished(JsonTokenProcessor jsonTokenProcessor) { + return !jsonTokenProcessor.isProcessorFor(JsonToken.END_DOCUMENT); + } + +} + + diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java new file mode 100644 index 0000000..9685bc3 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +public class KeywordsHandlerException extends RuntimeException { + + public KeywordsHandlerException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java new file mode 100644 index 0000000..3bcfa5b --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator; + +import io.vavr.Function0; +import io.vavr.Function1; +import io.vavr.Function2; + +import java.time.Instant; +import java.util.Random; + +import org.apache.commons.lang3.RandomStringUtils; + +class KeywordsValueProvider { + + private KeywordsValueProvider() { + } + + static final int DEFAULT_STRING_LENGTH = 20; + public static final int RANDOM_INTEGER_MAX_LIMITATION = 9; + public static final int RANDOM_INTEGER_MIN_LIMITATION = 0; + + private static Function2<Integer, Integer, Integer> bigger = (left, right) -> left >= right ? left : right; + private static Function2<Integer, Integer, Integer> smaller = (left, right) -> left < right ? left : right; + private static Function2<Integer, Integer, Integer> randomPrimitiveIntegerFromSortedRange = (min, max) -> new Random().nextInt(max - min + 1) + min; + private static Function2<Integer, Integer, String> randomIntegerFromSortedRange = (min, max) -> Integer.toString(new Random().nextInt(max - min + 1) + min); + + private static Function1<Integer, String> randomString = RandomStringUtils::randomAscii; + private static Function2<Integer, Integer, String> randomInteger = (left, right) -> randomIntegerFromSortedRange.apply(smaller.apply(left, right), bigger.apply(left, right)); + private static Function0<String> randomLimitedInteger = () -> randomInteger.apply(RANDOM_INTEGER_MIN_LIMITATION, RANDOM_INTEGER_MAX_LIMITATION); + private static Function0<String> randomLimitedString = () -> RandomStringUtils.randomAscii(DEFAULT_STRING_LENGTH); + private static Function0<String> epochSecond = () -> Long.toString(Instant.now().getEpochSecond()); + private static Function2<Integer, Integer, Long> randomPrimitiveInteger = (left, right) -> randomPrimitiveIntegerFromSortedRange.apply(smaller.apply(left, right), bigger.apply(left, right)).longValue(); + private static Function0<Long> timestampPrimitive = () -> Instant.now().getEpochSecond(); + + public static Function1<Integer, String> getRandomString() { + return randomString; + } + + public static Function2<Integer, Integer, String> getRandomInteger() { + return randomInteger; + } + + public static Function0<String> getRandomLimitedInteger() { + return randomLimitedInteger; + } + + public static Function0<String> getRandomLimitedString() { + return randomLimitedString; + } + + public static Function0<String> getEpochSecond() { + return epochSecond; + } + + public static Function2<Integer, Integer, Long> getRandomPrimitiveInteger() { + return randomPrimitiveInteger; + } + + public static Function0<Long> getTimestampPrimitive() { + return timestampPrimitive; + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java b/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java new file mode 100644 index 0000000..218dbc8 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java @@ -0,0 +1,132 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +import com.google.common.base.Strings; +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataService; +import org.onap.pnfsimulator.rest.model.FullEvent; +import org.onap.pnfsimulator.rest.model.SimulatorParams; +import org.onap.pnfsimulator.rest.model.SimulatorRequest; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapter; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl; +import org.onap.pnfsimulator.simulator.client.HttpResponseAdapter; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper; +import org.onap.pnfsimulator.simulator.scheduler.EventScheduler; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfigService; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Optional; + +@Service +public class SimulatorService { + + private final TemplatePatcher templatePatcher; + private final TemplateVariablesReplacer templateVariablesReplacer; + private final TemplateReader templateReader; + private final EventDataService eventDataService; + private final EventScheduler eventScheduler; + private final SslAuthenticationHelper sslAuthenticationHelper; + private SimulatorConfigService simulatorConfigService; + private static final JsonObject EMPTY_JSON_OBJECT = new JsonObject(); + + @Autowired + public SimulatorService( + TemplatePatcher templatePatcher, + TemplateReader templateReader, + EventScheduler eventScheduler, + EventDataService eventDataService, + SimulatorConfigService simulatorConfigService, + TemplateVariablesReplacer templateVariablesReplacer, + SslAuthenticationHelper sslAuthenticationHelper) { + this.templatePatcher = templatePatcher; + this.templateReader = templateReader; + this.eventDataService = eventDataService; + this.eventScheduler = eventScheduler; + this.simulatorConfigService = simulatorConfigService; + this.templateVariablesReplacer = templateVariablesReplacer; + this.sslAuthenticationHelper = sslAuthenticationHelper; + } + + public String triggerEvent(SimulatorRequest simulatorRequest) throws IOException, SchedulerException, GeneralSecurityException { + String templateName = simulatorRequest.getTemplateName(); + SimulatorParams simulatorParams = simulatorRequest.getSimulatorParams(); + JsonObject template = templateReader.readTemplate(templateName); + JsonObject input = Optional.ofNullable(simulatorRequest.getPatch()).orElse(new JsonObject()); + JsonObject patchedJson = templatePatcher + .mergeTemplateWithPatch(template, input); + JsonObject variables = Optional.ofNullable(simulatorRequest.getVariables()).orElse(new JsonObject()); + JsonObject patchedJsonWithVariablesSubstituted = templateVariablesReplacer.substituteVariables(patchedJson, variables); + + JsonObject keywords = new JsonObject(); + + EventData eventData = eventDataService.persistEventData(template, patchedJsonWithVariablesSubstituted, input, keywords); + + String targetVesUrl = getDefaultUrlIfNotProvided(simulatorParams.getVesServerUrl()); + return eventScheduler + .scheduleEvent(targetVesUrl, Optional.ofNullable(simulatorParams.getRepeatInterval()).orElse(1), + Optional.ofNullable(simulatorParams.getRepeatCount()).orElse(1), simulatorRequest.getTemplateName(), + eventData.getId(), + patchedJsonWithVariablesSubstituted); + } + + public HttpResponseAdapter triggerOneTimeEvent(FullEvent event) throws IOException, GeneralSecurityException { + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), id -> 1); + JsonObject withKeywordsSubstituted = keywordsHandler.substituteKeywords(event.getEvent(), "").getAsJsonObject(); + + HttpClientAdapter client = createHttpClientAdapter(event.getVesServerUrl()); + eventDataService.persistEventData(EMPTY_JSON_OBJECT, withKeywordsSubstituted, event.getEvent(), EMPTY_JSON_OBJECT); + + return client.send(withKeywordsSubstituted.toString()); + } + + public SimulatorConfig getConfiguration() { + return simulatorConfigService.getConfiguration(); + } + + public SimulatorConfig updateConfiguration(SimulatorConfig newConfig) { + return simulatorConfigService.updateConfiguration(newConfig); + } + + public boolean cancelAllEvents() throws SchedulerException { + return eventScheduler.cancelAllEvents(); + } + + public boolean cancelEvent(String jobName) throws SchedulerException { + return eventScheduler.cancelEvent(jobName); + } + + HttpClientAdapter createHttpClientAdapter(String vesServerUrl) throws IOException, GeneralSecurityException { + String targetVesUrl = getDefaultUrlIfNotProvided(vesServerUrl); + return new HttpClientAdapterImpl(targetVesUrl, sslAuthenticationHelper); + } + + private String getDefaultUrlIfNotProvided(String vesUrlSimulatorParam) { + return Strings.isNullOrEmpty(vesUrlSimulatorParam) + ? simulatorConfigService.getConfiguration().getVesServerUrl().toString() : vesUrlSimulatorParam; + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java b/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java new file mode 100644 index 0000000..1114d3c --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Component +class TemplatePatcher { + + JsonObject mergeTemplateWithPatch(JsonObject templateJson, JsonObject patchJson) { + JsonObject template = templateJson.deepCopy(); + patchTemplateNode(template, patchJson); + return template; + } + + private void patchTemplateNode(JsonObject templateJson, JsonObject patchJson) { + for (Map.Entry<String, JsonElement> stringJsonElementEntry : patchJson.entrySet()) { + String patchKey = stringJsonElementEntry.getKey(); + JsonElement patchValue = stringJsonElementEntry.getValue(); + JsonElement templateElement = templateJson.get(patchKey); + + if (!patchValue.isJsonObject() || templateElement == null || !templateElement.isJsonObject()) { + templateJson.remove(patchKey); + templateJson.add(patchKey, patchValue); + } else { + patchTemplateNode(templateElement.getAsJsonObject(), patchValue.getAsJsonObject()); + } + + } + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java new file mode 100644 index 0000000..2471c08 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator; + +import com.google.gson.JsonObject; + +import java.io.IOException; + +public interface TemplateReader { + JsonObject readTemplate(String templateName) throws IOException; +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java b/src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java new file mode 100644 index 0000000..eb0b141 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.Map.Entry; + +import lombok.val; +import org.springframework.stereotype.Component; + +@Component +public class TemplateVariablesReplacer { + private static final Gson GSON = new Gson(); + private static final String OBJECT_KEYWORD_MARK = "#"; + private static final String ESCAPED_QUOTE = "\""; + private static final String STRING_KEYWORD_MARK = ESCAPED_QUOTE + OBJECT_KEYWORD_MARK + "%s" + ESCAPED_QUOTE; + + JsonObject substituteVariables(JsonObject source, JsonObject variables) { + var result = source.toString(); + for (val variable : variables.entrySet()) { + result = substituteVariable(result, variable); + } + return GSON.fromJson(result, JsonObject.class); + } + + private String substituteVariable(String sourceAsString, Entry<String, JsonElement> variable) { + return sourceAsString.replaceAll(String.format(STRING_KEYWORD_MARK, variable.getKey()), variable.getValue().toString()); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java new file mode 100644 index 0000000..36ba922 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2021 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client; + +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class HttpApacheResponseAdapterFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpApacheResponseAdapterFactory.class); + + public HttpResponseAdapter create(HttpResponse response) { + String message; + try { + message = EntityUtils.toString(response.getEntity()); + } catch (IllegalArgumentException | IOException e) { + LOGGER.warn("Response from VES was empty"); + message = ""; + } + return new HttpResponseAdapter(response.getStatusLine().getStatusCode(), message); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java new file mode 100644 index 0000000..8cb6aa2 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client; + +public interface HttpClientAdapter { + + HttpResponseAdapter send(String content); + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java new file mode 100644 index 0000000..ba668fc --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java @@ -0,0 +1,119 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client; + +import org.apache.commons.codec.binary.Base64; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.onap.pnfsimulator.simulator.client.utils.ssl.HttpClientFactoryFacade; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.util.UUID; + +import static org.onap.pnfsimulator.logging.MdcVariables.REQUEST_ID; +import static org.onap.pnfsimulator.logging.MdcVariables.X_INVOCATION_ID; +import static org.onap.pnfsimulator.logging.MdcVariables.X_ONAP_REQUEST_ID; + +public class HttpClientAdapterImpl implements HttpClientAdapter { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientAdapterImpl.class); + private static final String CONTENT_TYPE = "Content-Type"; + private static final String APPLICATION_JSON = "application/json"; + private static final Marker INVOKE = MarkerFactory.getMarker("INVOKE"); + private static final HttpApacheResponseAdapterFactory responseFactory = new HttpApacheResponseAdapterFactory(); + private final HttpClient client; + private final String targetUrl; + + public HttpClientAdapterImpl(String targetUrl, SslAuthenticationHelper sslAuthenticationHelper) + throws IOException, GeneralSecurityException { + this.client = HttpClientFactoryFacade.create(targetUrl, sslAuthenticationHelper); + this.targetUrl = targetUrl; + } + + HttpClientAdapterImpl(HttpClient client, String targetUrl) { + this.client = client; + this.targetUrl = targetUrl; + } + + @Override + public HttpResponseAdapter send(String content) { + HttpResponseAdapter vesResponse; + try { + HttpResponse response = sendAndRetrieve(content); + LOGGER.info(INVOKE, "Message sent, ves response code: {}", response.getStatusLine()); + vesResponse = responseFactory.create(response); + EntityUtils.consumeQuietly(response.getEntity()); //response has to be fully consumed otherwise apache won't release connection + } catch (IOException | URISyntaxException e) { + LOGGER.warn("Error sending message to ves: {}", e.getMessage(), e.getCause()); + vesResponse = new HttpResponseAdapter(421, String.format("Fail to connect with ves: %s", e.getMessage())); + } + return vesResponse; + } + + private HttpResponse sendAndRetrieve(String content) throws IOException, URISyntaxException { + HttpPost request = createRequest(content); + HttpResponse httpResponse = client.execute(request); + request.releaseConnection(); + return httpResponse; + } + + private HttpPost createRequest(String content) throws UnsupportedEncodingException, URISyntaxException { + LOGGER.info("sending request using address: {}", this.targetUrl); + URI targetAddress = new URI(this.targetUrl); + HttpPost request = new HttpPost(targetAddress); + if(urlContainsUserInfo(targetAddress)) { + request.addHeader(HttpHeaders.AUTHORIZATION, getAuthenticationHeaderForUser(targetAddress.getUserInfo())); + } + StringEntity stringEntity = new StringEntity(content); + request.addHeader(CONTENT_TYPE, APPLICATION_JSON); + request.addHeader(X_ONAP_REQUEST_ID, MDC.get(REQUEST_ID)); + request.addHeader(X_INVOCATION_ID, UUID.randomUUID().toString()); + request.setEntity(stringEntity); + return request; + } + + private boolean urlContainsUserInfo(URI targetAddress) { + return targetAddress.getUserInfo() != null && !targetAddress.getUserInfo().isEmpty(); + } + + private String getAuthenticationHeaderForUser(String userInfo) { + final byte[] encodedUserInfo = Base64.encodeBase64( + userInfo.getBytes(StandardCharsets.ISO_8859_1) + ); + return String.format("Basic %s", new String(encodedUserInfo)); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java new file mode 100644 index 0000000..e78b8a3 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2021 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client; + +public class HttpResponseAdapter { + + private final int code; + private final String message; + + public HttpResponseAdapter(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java new file mode 100644 index 0000000..72af9e5 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import javax.net.ssl.SSLContext; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.ssl.SSLContexts; + +class CertAuthSslContextFactory { + + private final CertificateReader certificateReader; + + CertAuthSslContextFactory(CertificateReader certificateReader) { + this.certificateReader = certificateReader; + } + + SSLContext createSslContext(SslAuthenticationHelper sslAuthenticationHelper) + throws GeneralSecurityException, IOException { + final String keystorePasswordPath = sslAuthenticationHelper.getClientCertificatePasswordPath(); + + final KeyStore keystore = certificateReader.read(sslAuthenticationHelper.getClientCertificatePath(), + keystorePasswordPath, "PKCS12"); + final KeyStore truststore = certificateReader.read(sslAuthenticationHelper.getTrustStorePath(), + sslAuthenticationHelper.getTrustStorePasswordPath(), "JKS"); + + return SSLContexts.custom() + .loadKeyMaterial(keystore, certificateReader.readPassword(keystorePasswordPath)) + .loadTrustMaterial(truststore, new TrustSelfSignedStrategy()) + .build(); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java new file mode 100644 index 0000000..a42114b --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyStore; + +class CertificateReader { + + KeyStore read(String certificatePath, String passwordPath, String type) throws GeneralSecurityException, IOException { + try (InputStream keyStoreStream = new FileInputStream(certificatePath)) { + KeyStore keyStore = KeyStore.getInstance(type); + keyStore.load(keyStoreStream, readPassword(passwordPath)); + return keyStore; + } + } + + char[] readPassword(String passwordPath) throws IOException { + final String password = Files.readString(Path.of(passwordPath)); + return PasswordConverter.convert(password); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java new file mode 100644 index 0000000..ca57a64 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java @@ -0,0 +1,104 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import io.vavr.control.Try; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +class HttpClientFactory { + private static final int CONNECTION_TIMEOUT = 1000; + private static final RequestConfig CONFIG = RequestConfig.custom() + .setConnectTimeout(CONNECTION_TIMEOUT) + .setConnectionRequestTimeout(CONNECTION_TIMEOUT) + .setSocketTimeout(CONNECTION_TIMEOUT) + .build(); + private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientFactory.class); + private final SSLContextFactory sslContextFactory; + + HttpClientFactory(SSLContextFactory sslContextFactory) { + this.sslContextFactory = sslContextFactory; + } + + HttpClient create(String url, SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException { + HttpClient client; + if (!sslAuthenticationHelper.isClientCertificateEnabled()) { + client = "https".equals(new URL(url).getProtocol()) ? createForHttps() : createBasic(); + } else if (sslAuthenticationHelper.isStrictHostnameVerification()) { + client = createSecured(sslContextFactory.create(sslAuthenticationHelper), new DefaultHostnameVerifier()); + } else { + client = createSecured(sslContextFactory.create(sslAuthenticationHelper), new NoopHostnameVerifier()); + } + return client; + } + + private HttpClient createForHttps() { + return Try.of(this::createSecuredTrustAlways) + .onFailure(this::logErrorMessage) + .getOrElse(createBasic()); + } + + private void logErrorMessage(Throwable e) { + String message = String.format( + "Could not initialize client due to SSL exception: %s. " + + "Default client without SSL support will be used instead." + + "\nCause: %s", + e.getMessage(), + e.getCause() + ); + LOGGER.error(message, e); + } + + + private HttpClient createBasic() { + return HttpClientBuilder + .create() + .setDefaultRequestConfig(CONFIG) + .build(); + } + + private HttpClient createSecuredTrustAlways() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { + return createSecured(sslContextFactory.createTrustAlways(), new NoopHostnameVerifier()); + } + + private HttpClient createSecured(SSLContext trustAlways, HostnameVerifier hostnameVerifier) { + return HttpClients.custom() + .setSSLContext(trustAlways) + .setDefaultRequestConfig(CONFIG) + .setSSLHostnameVerifier(hostnameVerifier) + .build(); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java new file mode 100644 index 0000000..dffd635 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import org.apache.http.client.HttpClient; + +public class HttpClientFactoryFacade { + + private HttpClientFactoryFacade() { + } + + private static final CertificateReader CERTIFICATE_READER = new CertificateReader(); + private static final CertAuthSslContextFactory CERT_AUTH_SSL_CONTEXT_FACTORY = new CertAuthSslContextFactory(CERTIFICATE_READER); + private static final SSLContextFactory SSL_CONTEXT_FACTORY = new SSLContextFactory(CERT_AUTH_SSL_CONTEXT_FACTORY); + private static final HttpClientFactory HTTP_CLIENT_FACTORY = new HttpClientFactory(SSL_CONTEXT_FACTORY); + + public static HttpClient create(String url, SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException { + return HTTP_CLIENT_FACTORY.create(url, sslAuthenticationHelper); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java new file mode 100644 index 0000000..7a645ae --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.util.Optional; + +class PasswordConverter { + private PasswordConverter() { + } + + static char[] convert(String password) { + return Optional.ofNullable(password).map(String::toCharArray).orElse(null); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java new file mode 100644 index 0000000..b8dfe6f --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import javax.net.ssl.SSLContext; +import org.apache.http.conn.ssl.TrustAllStrategy; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.ssl.SSLContextBuilder; + +class SSLContextFactory { + private static final TrustStrategy TRUST_STRATEGY_ALWAYS = new TrustAllStrategy(); + + private final CertAuthSslContextFactory certAuthSslContextFactory; + + SSLContextFactory(CertAuthSslContextFactory certAuthSslContextFactory) { + this.certAuthSslContextFactory = certAuthSslContextFactory; + } + SSLContext create(SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException { + return certAuthSslContextFactory.createSslContext(sslAuthenticationHelper); + } + + SSLContext createTrustAlways() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { + return SSLContextBuilder.create().loadTrustMaterial(TRUST_STRATEGY_ALWAYS).build(); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java new file mode 100644 index 0000000..271ad93 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.io.Serializable; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "ssl") +@RefreshScope +@Primary +@Getter +@Setter +public class SslAuthenticationHelper implements Serializable { + + private boolean clientCertificateEnabled; + private boolean strictHostnameVerification; + private String clientCertificatePath; + private String clientCertificatePasswordPath; + private String trustStorePath; + private String trustStorePasswordPath; +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java new file mode 100644 index 0000000..1bb1332 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.keywords; + +import io.vavr.Function1; +import io.vavr.Function2; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.stream.Collectors; + +import lombok.Getter; + +@Getter +public class Keyword { + + protected static final String LETTERS_REGEX = "([a-zA-Z]+)"; + protected static final String NONLETTERS_REGEX = "([^a-zA-Z]+)"; + + protected static final Function1<String, String> OPTIONAL = + regex -> regex + "?"; + + private final String name; + private final List<String> meaningfulParts; + + public static final Function2<Keyword, String, Boolean> IS_MATCHING_KEYWORD_NAME = (keyword, key) -> + keyword != null && keyword.getName() != null && keyword.getName().equals(key); + + /** + * Returns list of independent parts inside the keyword. Current implementation assumes that customer can join keywords with integer values, so + * keyword is decomposed to parts then some parts of the keyword is skipped because of replacement process. + * + * @param matcher - Matcher to check find independent groups inside the keyword + * @param skipGroups Informs this method about which groups should be consider as part of the replacement process + * @return list of independent parts inside the keywords + */ + static List<String> extractPartsFrom(Matcher matcher, List<Integer> skipGroups) { + List<String> parts = new ArrayList<>(); + for (int i = 1; i <= matcher.groupCount(); i++) { + if (matcher.group(i) != null && !skipGroups.contains(i)) { + parts.add(matcher.group(i)); + } + } + return parts; + } + + Keyword(String name, List<String> meaningfulParts) { + this.name = name; + this.meaningfulParts = meaningfulParts; + } + + public String substituteKeyword(String substitution) { + return meaningfulParts.stream() + .map(part -> part.equals(name) ? substitution : part) + .collect(Collectors.joining()); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java new file mode 100644 index 0000000..5e44550 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.keywords; + +import io.vavr.Tuple; +import io.vavr.Tuple1; +import io.vavr.match.annotation.Patterns; +import io.vavr.match.annotation.Unapply; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +@Patterns +@Getter +@Setter +public class NonParameterKeyword extends Keyword { + + public static final int KEYWORD_NAME_GROUP = 2; + + private static final String KEYWORD_REGEX = new StringBuilder() + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .append("#") + .append(LETTERS_REGEX) + .append("(?!\\()") + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .toString(); + + private NonParameterKeyword(String name, List<String> meaningfulParts) { + super(name, meaningfulParts); + } + + @Unapply + static Tuple1<NonParameterKeyword> nonParameterKeyword(String keyword) { + val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword); + NonParameterKeyword npk = null; + if (matcher.find()) { + npk = new NonParameterKeyword( + matcher.group(KEYWORD_NAME_GROUP), + extractPartsFrom(matcher, Collections.emptyList()) + ); + } + return Tuple.of(npk); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java new file mode 100644 index 0000000..b1c38c8 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.keywords; + +import io.vavr.Tuple; +import io.vavr.Tuple1; +import io.vavr.match.annotation.Patterns; +import io.vavr.match.annotation.Unapply; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +@Patterns +@Getter +@Setter +public class SingleParameterKeyword extends Keyword { + + public static final int KEYWORD_NAME_GROUP = 2; + public static final int ADDITIONAL_PARAMETER_GROUP = 3; + + private static final String KEYWORD_REGEX = new StringBuilder() + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .append("#") + .append(LETTERS_REGEX) + .append("\\((\\d+)\\)") + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .toString(); + public static final int SKIPPED_GROUP_NUMBER = 3; + + private Integer additionalParameter; + + private SingleParameterKeyword(String name, List<String> meaningfulParts, + Integer additionalParameter) { + super(name, meaningfulParts); + this.additionalParameter = additionalParameter; + } + + @Unapply + static Tuple1<SingleParameterKeyword> singleParameterKeyword(String keyword) { + val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword); + SingleParameterKeyword spk = null; + if (matcher.find()) { + spk = new SingleParameterKeyword( + matcher.group(KEYWORD_NAME_GROUP), + extractPartsFrom(matcher, Collections.singletonList(SKIPPED_GROUP_NUMBER)), + Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_GROUP)) + ); + } + return Tuple.of(spk); + } +} + + diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java new file mode 100644 index 0000000..6fecfa6 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.keywords; + +import io.vavr.Tuple; +import io.vavr.Tuple1; +import io.vavr.match.annotation.Patterns; +import io.vavr.match.annotation.Unapply; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +@Patterns +@Getter +@Setter +public class TwoParameterKeyword extends Keyword { + + public static final int ADDITIONAL_PARAMETER_1_GROUP = 3; + public static final int ADDITIONAL_PARAMETER_2_GROUP = 4; + public static final int KEYWORD_NAME_GROUP = 2; + protected static final List<Integer> ADDITIONAL_PARAMETERS_GROUPS = Arrays.asList(ADDITIONAL_PARAMETER_1_GROUP, ADDITIONAL_PARAMETER_2_GROUP); + + private static final String NON_LIMITED_NUMBER_REGEX = "\\((\\d+)"; + private static final String COLON_REGEX = "\\s?,\\s?"; + private static final String OPTIONAL_NUMBER_PARAM_REGEX = "(\\d+)\\)"; + + private static final String KEYWORD_REGEX = OPTIONAL.apply(NONLETTERS_REGEX) + + "#" + + LETTERS_REGEX + + NON_LIMITED_NUMBER_REGEX + + COLON_REGEX + + OPTIONAL_NUMBER_PARAM_REGEX + + OPTIONAL.apply(NONLETTERS_REGEX); + + private Integer additionalParameter1; + private Integer additionalParameter2; + + private TwoParameterKeyword(String name, List<String> meaningfulParts, Integer additionalParameter1, + Integer additionalParameter2) { + super(name, meaningfulParts); + this.additionalParameter1 = additionalParameter1; + this.additionalParameter2 = additionalParameter2; + } + + @Unapply + static Tuple1<TwoParameterKeyword> twoParameterKeyword(String keyword) { + val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword); + TwoParameterKeyword tpk = null; + if (matcher.find()) { + tpk = new TwoParameterKeyword( + matcher.group(KEYWORD_NAME_GROUP), + extractPartsFrom(matcher, ADDITIONAL_PARAMETERS_GROUPS), + Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_1_GROUP)), + Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_2_GROUP)) + ); + } + return Tuple.of(tpk); + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java new file mode 100644 index 0000000..a467370 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.scheduler; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.simulator.KeywordsHandler; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapter; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.Optional; + +public class EventJob implements Job { + + private static final Logger LOGGER = LoggerFactory.getLogger(EventJob.class); + + static final String TEMPLATE_NAME = "TEMPLATE_NAME"; + static final String VES_URL = "VES_URL"; + static final String BODY = "BODY"; + static final String CLIENT_ADAPTER = "CLIENT_ADAPTER"; + static final String KEYWORDS_HANDLER = "KEYWORDS_HANDLER"; + static final String EVENT_ID = "EVENT_ID"; + + @Override + public void execute(JobExecutionContext jobExecutionContext) { + JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); + String templateName = jobDataMap.getString(TEMPLATE_NAME); + String vesUrl = jobDataMap.getString(VES_URL); + JsonObject body = (JsonObject) jobDataMap.get(BODY); + String id = jobDataMap.getString(EVENT_ID); + Optional<HttpClientAdapter> httpClientAdapter = getHttpClientAdapter(jobDataMap, vesUrl); + + if (httpClientAdapter.isPresent()) { + KeywordsHandler keywordsHandler = (KeywordsHandler) jobDataMap.get(KEYWORDS_HANDLER); + JsonElement processedBody = keywordsHandler.substituteKeywords(body, id); + String processedBodyString = processedBody.toString(); + String jobKey = jobExecutionContext.getJobDetail().getKey().toString(); + + logEventDetails(templateName, vesUrl, body.toString(), jobKey); + httpClientAdapter.get().send(processedBodyString); + } else { + LOGGER.error("Could not send event as client is not available"); + } + } + + private Optional<HttpClientAdapter> getHttpClientAdapter(JobDataMap jobDataMap, String vesUrl) { + HttpClientAdapter adapter = null; + try { + adapter = (HttpClientAdapter) (jobDataMap.containsKey(CLIENT_ADAPTER) ? jobDataMap.get(CLIENT_ADAPTER) + : new HttpClientAdapterImpl(vesUrl, new SslAuthenticationHelper())); + adapter = (HttpClientAdapter) ( + jobDataMap.containsKey(CLIENT_ADAPTER) + ? jobDataMap.get(CLIENT_ADAPTER) + : new HttpClientAdapterImpl(vesUrl, new SslAuthenticationHelper()) + ); + } catch (MalformedURLException e) { + LOGGER.error("Invalid format of vesServerUr: {}", vesUrl); + } catch (IOException | GeneralSecurityException e) { + LOGGER.error("Invalid configuration of client certificate"); + } + return Optional.ofNullable(adapter); + } + + private void logEventDetails(String templateName, String vesUrl, String body, String jobKey) { + LOGGER.info("Job {}:Sending event to {} from template {}", + jobKey, vesUrl, templateName); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Job {}: Request body {}", jobKey, body); + } + } + +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java new file mode 100644 index 0000000..5584cb1 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.scheduler; + + +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.simulator.KeywordsHandler; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; +import org.quartz.TriggerBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.BODY; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.CLIENT_ADAPTER; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.EVENT_ID; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.KEYWORDS_HANDLER; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.TEMPLATE_NAME; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.VES_URL; +import static org.quartz.SimpleScheduleBuilder.simpleSchedule; + +@Component +public class EventScheduler { + + + private final Scheduler scheduler; + private final KeywordsHandler keywordsHandler; + private final SslAuthenticationHelper sslAuthenticationHelper; + + @Autowired + public EventScheduler(Scheduler scheduler, KeywordsHandler keywordsHandler, SslAuthenticationHelper sslAuthenticationHelper) { + this.scheduler = scheduler; + this.keywordsHandler = keywordsHandler; + this.sslAuthenticationHelper = sslAuthenticationHelper; + } + + public String scheduleEvent(String vesUrl, Integer repeatInterval, Integer repeatCount, + String templateName, String eventId, JsonObject body) + throws SchedulerException, IOException, GeneralSecurityException { + + JobDetail jobDetail = createJobDetail(vesUrl, templateName, eventId, body); + SimpleTrigger trigger = createTrigger(repeatInterval, repeatCount); + + scheduler.scheduleJob(jobDetail, trigger); + return jobDetail.getKey().getName(); + } + + public boolean cancelAllEvents() throws SchedulerException { + List<JobKey> jobKeys = getActiveJobsKeys(); + return scheduler.deleteJobs(jobKeys); + } + + public boolean cancelEvent(String jobName) throws SchedulerException { + Optional<JobKey> activeJobKey = getActiveJobsKeys().stream().filter(e -> e.getName().equals(jobName)).findFirst(); + return activeJobKey.isPresent() && scheduler.deleteJob(activeJobKey.get()); + } + + private SimpleTrigger createTrigger(int interval, int repeatCount) { + return TriggerBuilder.newTrigger() + .withSchedule(simpleSchedule() + .withIntervalInSeconds(interval) + .withRepeatCount(repeatCount - 1)) + .build(); + } + + private JobDetail createJobDetail(String vesUrl, String templateName, String eventId, JsonObject body) throws IOException, GeneralSecurityException { + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put(TEMPLATE_NAME, templateName); + jobDataMap.put(VES_URL, vesUrl); + jobDataMap.put(EVENT_ID, eventId); + jobDataMap.put(KEYWORDS_HANDLER, keywordsHandler); + jobDataMap.put(BODY, body); + jobDataMap.put(CLIENT_ADAPTER, new HttpClientAdapterImpl(vesUrl, sslAuthenticationHelper)); + + return JobBuilder + .newJob(EventJob.class) + .withDescription(templateName) + .usingJobData(jobDataMap) + .build(); + } + + private List<JobKey> getActiveJobsKeys() throws SchedulerException { + return scheduler.getCurrentlyExecutingJobs() + .stream() + .map(JobExecutionContext::getJobDetail) + .map(JobDetail::getKey) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java new file mode 100644 index 0000000..2beb9dc --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.scheduler; + +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.impl.StdSchedulerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class QuartzConfiguration { + + @Bean + Scheduler provideScheduler() throws SchedulerException { + StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(); + Scheduler scheduler = stdSchedulerFactory.getScheduler(); + scheduler.start(); + return scheduler; + } +} |