ENTAXY-374 release 1.8.2 #10

Merged
skryuchkov merged 1 commits from ENTAXY-374 into master 2022-08-25 18:36:58 +03:00
618 changed files with 61269 additions and 3202 deletions
Showing only changes of commit f495628c75 - Show all commits

View File

@ -1897,7 +1897,7 @@
"system-management" "system-management"
] ]
}, },
"description": "Создать сразу несколько доступов, которым разрешено отправлять сообщения от данной системы, можно с помощью метода сreatePermissionForObjectRequest, где “objectUuid” это uuid системы, от которой буду исходить сообщения, “subjectUuid1”, “subjectUuid2” и т д, это uuid систем, которым будут отправлять сообщения\n" "description": "Создать сразу несколько доступов, которым разрешено отправлять сообщения от данной системы, можно с помощью метода createPermissionForObjectRequest, где “objectUuid” это uuid системы, от которой буду исходить сообщения, “subjectUuid1”, “subjectUuid2” и т д, это uuid систем, которым будут отправлять сообщения\n"
}, },
"response": [] "response": []
}, },
@ -1979,7 +1979,7 @@
"system-management" "system-management"
] ]
}, },
"description": "Создать сразу несколько доступов, которым разрешено отправлять сообщения в данную систему, можно с помощью метода сreatePermissionForSubjectRequest, где “objectUuid1”, “objectUuid2” и т д - это uuid систем, от которых буду исходить сообщения, “subjectUuid” - это uuid системы, которой будут отправлять сообщения\n" "description": "Создать сразу несколько доступов, которым разрешено отправлять сообщения в данную систему, можно с помощью метода createPermissionForSubjectRequest, где “objectUuid1”, “objectUuid2” и т д - это uuid систем, от которых буду исходить сообщения, “subjectUuid” - это uuid системы, которой будут отправлять сообщения\n"
}, },
"response": [] "response": []
} }
@ -2973,7 +2973,7 @@
"schema" "schema"
] ]
}, },
"description": "Для корректирования мета информации ресурса в шине есть метод еditResourceInfo.\n\n\n\n\n" "description": "Для корректирования мета информации ресурса в шине есть метод editResourceInfo.\n\n\n\n\n"
}, },
"response": [] "response": []
}, },

View File

@ -64,7 +64,7 @@ redelivery.redeliveryDelay=5000
#cron - по умолчанию запускается каждые 00:00:00, #cron - по умолчанию запускается каждые 00:00:00,
#cron выражение использует знак "+" как разделитель для модуля quartz2l #cron выражение использует знак "+" как разделитель для модуля quartz2l
quirtz.job.clean.cron=0+0+0+*+*+?+* quartz.job.clean.cron=0+0+0+*+*+?+*
---- ----
- _ru.entaxy.esb.system.event.rest.cfg_ - _ru.entaxy.esb.system.event.rest.cfg_
@ -550,6 +550,6 @@ _POST server:9090/topic-subscription/publish_
Т.к. удаление топиков происходит в 2 этапа, с помощью планировщика _Quartz2_, работающего в кластере, запускается задача по очистке. Запуск происходит в конкурентном режиме, узел первый запустивший задачу получает приоритет, на остальных узлах задача останавливается до следующего запуска. Т.к. удаление топиков происходит в 2 этапа, с помощью планировщика _Quartz2_, работающего в кластере, запускается задача по очистке. Запуск происходит в конкурентном режиме, узел первый запустивший задачу получает приоритет, на остальных узлах задача останавливается до следующего запуска.
Частота запуска задачи настраивается в конфигурационном файле _ru.entaxy.esb.system.event.handler.cfg_ в свойстве quirtz.job.clean.cron=0+0+0+*+*+?+* Частота запуска задачи настраивается в конфигурационном файле _ru.entaxy.esb.system.event.handler.cfg_ в свойстве quartz.job.clean.cron=0+0+0+*+*+?+*
с помощью cron выражения. Особенность cron выражения для quartz в том что “++” используется, как разделитель. с помощью cron выражения. Особенность cron выражения для quartz в том что “++” используется, как разделитель.

View File

@ -0,0 +1,171 @@
= Хранилище данных EAV
== Описание модуля EXTRAS :: ENTAXY :: EAV (Entity, Attribute, Value)
Хранилище данных EAV реализует модель _Сущность-Атрибут-Значение_ - это модель данных, предназначенная для описания сущностей, в которых количество атрибутов (свойств, параметров) не ограничено или не известно заранее.
== Объекты модуля ЕАV
image::eav_objects.png[]
*Внешняя сущность*(External Entity) - любая внешняя сущность относительно модуля EAV.
*Сущность EAV*(Entity EAV) - именованная сущность, связывающая аттрибуты с внешней сущностью.
Модуль предоставляет возможность объединять сущности EAV в одноуровневую иерархию.
*Атрибут*(Attribute) - именованный атрибут сущности EAV, содержит значение и его тип.
*Типы значений:*
* DOUBLE
* LONG
* TEXT
* JSON
== Использование хранилища EAV
В BLUEPRINT подключаем OSGI-сервис EAVProcessor
[source]
----
<reference id="eavProcessor" interface="ru.entaxy.eav.service.EAVProcessor"/>
----
в маршрутах или java коде осуществляем необходимые вызовы для создания/получения/изменения значений.
*Примеры вызовов из маршрута Apache Camel XMLDSL*
Создание атрибута для внешней сущности
[source]
----
<bean ref="eavProcessor" method="createPrimitive('externalIdTest', 'externalTypeTest', 'entityNameTest', 'attributeNameTest', 'textValue', 'testLogin')"/>
----
Получить все значения сохранённой сущности
[source]
----
<bean ref="eavProcessor" method="getEntityWithValues('externalIdTest', 'externalTypeTest', 'entityNameTest')"/>
----
Удалить сохранённые значения
[source]
----
<bean ref="eavProcessor" method="deleteExternalEntity('externalIdTest', 'externalTypeTest')"/>
----
== OSGI-сервис EAVProcessor.
Сервис, выставляющий api для работы с EAV хранилищем.
*Методы:*
* _createPrimitive_ - простой метод сохранения примитивного значения(числового, строкового)
* _createComplex_ - простой метод сохранения комплексного значения(JSON)
* _getEntityWithValues_ - получение значений сущности EAV по имени
* _fetchEntityWithValues_ - получение значений сущности EAV по имени либо null, без исключений
* _getEntityNamedAttributes_ - получение значений с определённым именем для сущности EAV
* _getEntityByNameAndAttributeValue_ - получение сущности EAV по атрибуту
* _getParentEntity_ - получение родительской сущности EAV для внешней связанной сущности
* _getChildEntities_ - получение дочерних сущностей EAV для внешней связанной сущности с именем сущности EAV по умолчанию(PARENT)
* _getChildEntitiesByName_ - получение дочерних сущностей EAV для внешней связанной сущности с указанным именем сущности EAV
* _getByExternalEntity_ - получение всех сущностей EAV для внешней связанной сущности
* _getByAttributeSet_ - получение сущностей EAV по множественным наборов параметров, каждый набор составляется из значений элементов с одним порядковым номером всех списков
* _updateAttribute_ - метод для изменения значения аттрибута
* _deleteExternalEntity_ - удаление всех записей связанных с внешней сущностью
* _deleteEntity_ - удаление именованной сущности EAV
* _deleteAllEntityAttributes_ - удаление атрибутов именованной сущности EAV
* _deleteAllEntityAttributesByName_ - удаление аттрибута сущности EAV с определённым наименованием
* _combineEntities_ - метод для объединения внешних сущностей под 1 родителем
== Схема базы данных(БД).
Схема БД при таком подходе остаётся неизменной независимо от состава и структуры хранимых данных.
Бандл eav-storage разворачивает структуру из 2 таблиц:
*Таблица eav_entity*
|===
|Слолбец |Параметры |Описание
//----------------------
|id
|bigint, not null
|идентификатор сущности модуля EAV
|external_id
|text, not null
|внешний идентификатор связываемой сущности
|external_type
|text, not null
|тип связываемой сущности
|name
|text
|наименование сущности модуля EAV
|parent_id
|bigint, not null, default 0
|идентификатор(поле id) родительской сущности модуля EAV
|create_date
|timestamp, not null
|служебное поле, дата создания
|edit_date
|timestamp
|служебное поле, дата изменения
|created_by
|text, not null
|служебное поле, логин автора записи
|external_type
|text
|служебное поле, логин последнего изменившего сущность
|===
*Таблица eav_attribute*
|===
|Слолбец |Параметры |Описание
//----------------------
|id
|bigint, not null
|идентификатор атрибута
|entity_id
|text, not null
|идентификатор сущности eav_entity
|name
|text, not null
|наименование аттрибута
|type
|text
|тип аттрибута
|double
|double
|служебное поле для хранения значения
|long
|bigint
|служебное поле для хранения значения
|text
|text
|служебное поле для хранения значения
|text2
|text
|служебное поле для хранения значения
|===

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -18,8 +18,8 @@ _Для разработчиков:
-имеет Api, который занимается Crud операциями, -имеет Api, который занимается Crud операциями,
-хранит учетные записи в базе данных, -хранит учетные записи в базе данных,
-предоставляет файл с актуальной информацией для nginx, -предоставляет файл с актуальной информацией для nginx,
-выставляет interсeptor для аутентификации в других сервисах, -выставляет interceptor для аутентификации в других сервисах,
-выставляет interсeptor для определения принадлежности аккаунта определённой системе._ -выставляет interceptor для определения принадлежности аккаунта определённой системе._
=== permission === permission
@ -32,7 +32,7 @@ _Для разработчиков:
-имеет Api, который занимается Crud операциями -имеет Api, который занимается Crud операциями
- хранит права в базе данных, - хранит права в базе данных,
-(camel)компонент, который используется в маршрутах, для проверки возможности отправки из системы a в систему b. -(camel)компонент, который используется в маршрутах, для проверки возможности отправки из системы a в систему b.
-выставляет interсeptor для авторизации в служебных сервисах._ -выставляет interceptor для авторизации в служебных сервисах._
=== system-management-api === system-management-api

View File

@ -21,7 +21,7 @@ __Alternative languages:__
== Дистрибутивы Entaxy == Дистрибутивы Entaxy
Сущетсвет несколько вариантов сборок Entaxy, которые доступны по адресу https://entaxy.ru/download Существует несколько вариантов сборок Entaxy, которые доступны по адресу https://entaxy.ru/download
. `entaxy-assembly-compact*` - все-в-одном, брокер, бд и графический веб-интерфейс в одной сборке. См. xref:#_установка_all_in_one [Установка all-in-one] . `entaxy-assembly-compact*` - все-в-одном, брокер, бд и графический веб-интерфейс в одной сборке. См. xref:#_установка_all_in_one [Установка all-in-one]

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>root</artifactId> <artifactId>root</artifactId>
<groupId>ru.entaxy.esb</groupId> <groupId>ru.entaxy.esb</groupId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime</groupId> <groupId>ru.entaxy.esb.platform.runtime</groupId>
<artifactId>base</artifactId> <artifactId>base</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId> <groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>base-support</artifactId> <artifactId>base-support</artifactId>
@ -17,6 +17,7 @@
ru.entaxy.platform.base.support.xml, ru.entaxy.platform.base.support.xml,
ru.entaxy.platform.base.support.osgi, ru.entaxy.platform.base.support.osgi,
ru.entaxy.platform.base.support.osgi.tracker, ru.entaxy.platform.base.support.osgi.tracker,
ru.entaxy.platform.base.support.osgi.tracker.filter,
ru.entaxy.platform.base.support.osgi.filter ru.entaxy.platform.base.support.osgi.filter
</bundle.osgi.export.pkg> </bundle.osgi.export.pkg>
</properties> </properties>

View File

@ -0,0 +1,54 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.support;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
public class DependencySorter {
public static interface DependencyProvider<T> {
List<T> getDependencies(T inspectedObject);
}
public static <T> List<T> getSortedList(List<T> origin, DependencyProvider<T> provider) throws Exception {
List<T> result = new LinkedList<>();
// add independent objects
result.addAll(
origin.stream().filter(obj -> provider.getDependencies(obj).isEmpty())
.collect(Collectors.toList())
);
while (result.size() < origin.size()) {
List<T> nextObjects = origin.stream().filter(obj->!result.contains(obj))
.filter(obj->result.containsAll(provider.getDependencies(obj)))
.collect(Collectors.toList());
if (nextObjects.isEmpty())
// TODO create more informative exception
throw new Exception("Contains unsatisfied dependencies");
result.addAll(nextObjects);
}
return result;
}
}

View File

@ -39,7 +39,7 @@ public class FileUtils {
protected String md5FilePath = ""; protected String md5FilePath = "";
protected String currentMd5 = null; protected String currentMd5 = null;
protected String timmestampFilePath = ""; protected String timestampFilePath = "";
protected String currentTimestamp = null; protected String currentTimestamp = null;
public FileHelper(String filePath) { public FileHelper(String filePath) {
@ -49,7 +49,7 @@ public class FileUtils {
public FileHelper(File file) { public FileHelper(File file) {
this.file = file; this.file = file;
this.md5FilePath = file.getAbsolutePath().concat(".md5"); this.md5FilePath = file.getAbsolutePath().concat(".md5");
this.timmestampFilePath = file.getAbsolutePath().concat(".timestamp"); this.timestampFilePath = file.getAbsolutePath().concat(".timestamp");
} }
public boolean isReadable() { public boolean isReadable() {
@ -59,7 +59,7 @@ public class FileUtils {
protected String calcMd5() { protected String calcMd5() {
if (!CommonUtils.isValid(this.fileMd5Hash)) if (!CommonUtils.isValid(this.fileMd5Hash))
try { try {
this.fileMd5Hash = DigestUtils.md2Hex(this.file.toURI().toURL().openStream()); this.fileMd5Hash = DigestUtils.md5Hex(this.file.toURI().toURL().openStream());
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
@ -85,7 +85,7 @@ public class FileUtils {
public String getTimestamp() { public String getTimestamp() {
if (this.currentTimestamp == null) if (this.currentTimestamp == null)
try { try {
this.currentTimestamp = Files.readString((new File(this.timmestampFilePath)).toPath()); this.currentTimestamp = Files.readString((new File(this.timestampFilePath)).toPath());
} catch (IOException e) { } catch (IOException e) {
this.currentTimestamp = ""; this.currentTimestamp = "";
} }
@ -121,7 +121,7 @@ public class FileUtils {
String timestamp = Calendar.getInstance().getTimeInMillis() + ""; String timestamp = Calendar.getInstance().getTimeInMillis() + "";
String result = ""; String result = "";
try { try {
FileUtils.string2file(timestamp, timmestampFilePath); FileUtils.string2file(timestamp, timestampFilePath);
this.currentTimestamp = null; this.currentTimestamp = null;
result = getTimestamp(); result = getTimestamp();
} catch (IOException e) { } catch (IOException e) {

View File

@ -1,5 +1,4 @@
/*- /* ~~~~~~licensing~~~~~~
* ~~~~~~licensing~~~~~~
* base-support * base-support
* ========== * ==========
* Copyright (C) 2020 - 2021 EmDev LLC * Copyright (C) 2020 - 2021 EmDev LLC
@ -25,10 +24,12 @@ import java.io.InputStreamReader;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
@ -108,10 +109,283 @@ public class JSONUtils {
url.openStream(), StandardCharsets.UTF_8)) url.openStream(), StandardCharsets.UTF_8))
.lines() .lines()
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
return JSONUtils.getJsonRootObject(metadata);
}
JsonElement je = (new JsonParser()).parse(metadata); public static JsonObject getJsonRootObject(String jsonData) {
try {
JsonElement je = (new JsonParser()).parse(jsonData);
JsonObject root = je.getAsJsonObject(); JsonObject root = je.getAsJsonObject();
return root; return root;
} catch (Exception e) {
return new JsonObject();
}
}
public static void mergeObjects(JsonObject source, JsonObject target) {
if (source == null)
return;
if (target == null)
return;
for (Entry<String, JsonElement> entry: source.entrySet()) {
if (target.has(entry.getKey())) {
if (entry.getValue().isJsonObject())
if (target.get(entry.getKey()).isJsonObject()) {
mergeObjects(entry.getValue().getAsJsonObject(), target.get(entry.getKey()).getAsJsonObject());
continue;
}
target.remove(entry.getKey());
}
target.add(entry.getKey(), entry.getValue().deepCopy());
}
}
public static boolean replaceValue(JsonObject origin, String path, JsonElement replacement) {
return setValue(origin, path, replacement, false);
}
public static boolean setValue(JsonObject origin, String path, JsonElement replacement, boolean ifMissing) {
String preparedPath = path.replaceAll("(\\[\\d+\\])", ".$1");
String[] pathSplitted = preparedPath.split("\\.");
JsonElement currentElement = origin;
for (int i=0; i<pathSplitted.length-1; i++) {
String fragment = pathSplitted[i];
if (fragment.startsWith("[") && fragment.endsWith("]")) {
// array index
if (currentElement.isJsonArray()) {
int index = Integer.parseInt(fragment.substring(1, fragment.length()-1));
JsonArray arr = currentElement.getAsJsonArray();
if (arr.size()>index)
currentElement = arr.get(index);
else {
// TODO process
// System.out.println("ERROR: index out of bounds");
}
} else {
// TODO process
// System.out.println("ERROR: found indexed property on non-array value");
}
} else if (currentElement.isJsonObject()) {
currentElement = currentElement.getAsJsonObject().get(fragment);
} else {
// TODO process
// System.out.println("ERROR: currentElement can't be traversed");
}
}
if (currentElement == null) {
// System.out.println("ERROR: currentElement is null");
return false;
}
String finalFragment = pathSplitted[pathSplitted.length-1];
if (finalFragment.startsWith("[") && finalFragment.endsWith("]")) {
// array index
if (currentElement.isJsonArray()) {
// System.out.println("INDEX: [" + finalFragment.substring(1, finalFragment.length()-1) + "]");
int index = Integer.parseInt(finalFragment.substring(1, finalFragment.length()-1));
JsonArray arr = currentElement.getAsJsonArray();
if (arr.size()>index) {
// arr.remove(index);
arr.set(index, replacement);
} else {
// TODO process
// System.out.println("ERROR: index out of bounds");
}
} else {
// TODO process
// System.out.println("ERROR: found indexed property on non-array value");
}
} else if (currentElement.isJsonObject()) {
if (ifMissing && currentElement.getAsJsonObject().has(finalFragment))
return false;
currentElement.getAsJsonObject().remove(finalFragment);
currentElement.getAsJsonObject().add(finalFragment, replacement);
} else {
// System.out.println("ERROR: currentElement can't be traversed");
return false;
}
// System.out.println("\n -- found --\n" + currentElement.toString() + "\n");
return true;
}
public static class JsonTraverse {
List<ObjectChecker> checkers = new ArrayList<>();
public JsonTraverse checker(ObjectChecker checker) {
this.checkers.add(checker);
return this;
}
public Object traverse(JsonObject rootObject) {
Object result = null;
Map<String, Object> context = new HashMap<>();
result = element2object(rootObject, context, "$");
return result;
}
protected Object element2object(JsonElement element, Map<String, Object> context, String path) {
if (element.isJsonNull() || element.isJsonPrimitive())
return element2value(element, context, path);
if (element.isJsonArray())
return element2list(element, context, path);
if (element.isJsonObject()) {
JsonObject jsonObject = element.getAsJsonObject();
ObjectWrapper ow = null;
for (ObjectChecker oc: checkers) {
ow = oc.checkObject(jsonObject);
if (ow != null)
break;
}
if (ow != null) {
ow.wrap(jsonObject, context, path);
if (ow.continueTraverse())
ow.setTraverseMap(element2map(element, context, path), context);
return ow;
}
return element2map(element, context, path);
}
return null;
}
protected Map<String, Object> element2map(JsonElement element, Map<String, Object> context, String path){
Map<String, Object> result = new HashMap<>();
if (element.isJsonObject()) {
JsonObject jsonObject = element.getAsJsonObject();
for (Entry<String, JsonElement> entry: jsonObject.entrySet()) {
result.put(entry.getKey(), element2object(entry.getValue(), context, path + "." + entry.getKey()));
}
} else
if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
result.put(PROP_VALUE, element2list(element, context, path));
} else
if (element.isJsonNull()) {
result.put(PROP_VALUE, null);
} else
if (element.isJsonPrimitive()) {
result.put(PROP_VALUE, element2value(element, context, path));
}
return result;
}
protected Object element2value(JsonElement element, Map<String, Object> context, String path) {
Object result = null;
if (element.isJsonNull() || !element.isJsonPrimitive())
return result;
try {
JsonPrimitive primitive = element.getAsJsonPrimitive();
if (primitive.isNumber())
result = primitive.getAsNumber();
else if (primitive.isBoolean())
result = primitive.getAsBoolean();
else result = primitive.getAsString();
} catch (Exception e1) {
try {
result = element.getAsBoolean();
} catch (Exception e2) {
result = element.getAsString();
}
}
return result;
}
protected List<Object> element2list(JsonElement element, Map<String, Object> context, String path) {
List<Object> result = new ArrayList<>();
JsonArray array = element.getAsJsonArray();
for (int i=0; i<array.size(); i++)
result.add(element2object(array.get(i), context, path + "[" + i + "]"));
return result;
}
}
public static abstract class ObjectChecker {
public abstract ObjectWrapper checkObject(JsonObject object);
}
public static abstract class ObjectWrapper implements Map<String, Object> {
protected Map<String, Object> data = new HashMap<>();
public abstract void wrap(JsonObject object, Map<String, Object> context, String path);
public boolean continueTraverse() {
return true;
}
public void setTraverseMap(Map<String, Object> traverseMap, Map<String, Object> context) {
this.data = traverseMap;
}
@Override
public int size() {
return this.data.size();
}
@Override
public boolean isEmpty() {
return this.data.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return this.data.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return this.data.containsValue(value);
}
@Override
public Object get(Object key) {
return this.data.get(key);
}
@Override
public Object put(String key, Object value) {
return this.data.put(key, value);
}
@Override
public Object remove(Object key) {
return this.data.remove(key);
}
@Override
public void putAll(Map<? extends String, ? extends Object> m) {
this.data.putAll(m);
}
@Override
public void clear() {
this.data.clear();
}
@Override
public Set<String> keySet() {
return this.data.keySet();
}
@Override
public Collection<Object> values() {
return this.data.values();
}
@Override
public Set<Entry<String, Object>> entrySet() {
return this.data.entrySet();
};
} }
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime</groupId> <groupId>ru.entaxy.esb.platform.runtime</groupId>
<artifactId>base</artifactId> <artifactId>base</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,37 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime</groupId>
<artifactId>base</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>config-extensions</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: BASE :: CONFIG EXTENSIONS</name>
<description>ENTAXY :: PLATFORM :: BASE :: CONFIG EXTENSIONS</description>
<properties>
<bundle.osgi.export.pkg>ru.entaxy.platform.base.config</bundle.osgi.export.pkg>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.karaf.config</groupId>
<artifactId>org.apache.karaf.config.core</artifactId>
<version>${karaf.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>base-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.configadmin</artifactId>
<version>${felix.configadmin.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,105 @@
/*-
* ~~~~~~licensing~~~~~~
* config-plugin
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationPlugin;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* Configuration plugin providing resolving references from one config to others
* in a form $PID_OF_OTHER_CONFIG{PROPERTY_NAME}
* e.g. $org.ops4j.pax.url.mvn{org.ops4j.pax.url.mvn.localRepository}
*
* If pid or property not found no changes are made
*
* @author sstarovoytenkov
*
*/
@Component(service = {ConfigurationPlugin.class}, immediate = true,
property = {ConfigurationPlugin.CM_TARGET + "=*"
, ConfigurationPlugin.CM_RANKING + "=100"
, "config.plugin.id=ConfigLookupConfigurationPlugin"})
public class ConfigLookupConfigurationPlugin implements ConfigurationPlugin {
private static final Logger log = LoggerFactory.getLogger(ConfigLookupConfigurationPlugin.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected ConfigurationAdmin configurationAdmin;
@Override
public void modifyConfiguration(ServiceReference<?> arg0, Dictionary<String, Object> properties) {
for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements(); ) {
String key = keys.nextElement();
Object val = properties.get(key);
if (val instanceof String) {
String text = (String)val;
String newValue = (String)val;
Pattern pattern = Pattern.compile("\\$([^\\{\\}])+\\{.+?\\}");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
log.debug("FOUND :: " + text.substring(matcher.start(), matcher.end()));
String placeholder = text.substring(matcher.start(), matcher.end());
String pid = placeholder.substring(1, placeholder.indexOf("{"));
String propName = placeholder.substring(placeholder.indexOf("{")+1
, placeholder.indexOf("}"));
log.debug("PARSED :: " + pid + ":" + propName);
Configuration conf;
try {
conf = configurationAdmin.getConfiguration(pid);
if (conf != null) {
Dictionary<String, Object> props = conf.getProperties();
Object value = props.get(propName);
log.debug("VALUE :: " + placeholder + " = " + value);
if (value != null) {
newValue = newValue.replace(placeholder, (String)value);
log.debug("NEW VALUE :: " + placeholder + " = " + newValue);
}
}
} catch (IOException e) {
log.error("Error with pid: " + pid, e);
}
}
properties.put(key, newValue);
}
}
}
}

View File

@ -0,0 +1,232 @@
/*-
* ~~~~~~licensing~~~~~~
* configuration-test-1
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.apache.felix.utils.properties.TypedProperties;
import org.apache.karaf.config.core.ConfigRepository;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.CommonUtils;
public class DefaultPropertiesProvider implements Map<String, Object> {
private static final Logger log = LoggerFactory.getLogger(DefaultPropertiesProvider.class);
protected String objectId;
protected String objectType;
protected String configurationPid;
protected BundleContext bundleContext;
protected Map<String, Object> properties;
public DefaultPropertiesProvider(String configurationPid
, BundleContext bundleContext
, Map<String, Object> properties) {
this.configurationPid = configurationPid;
this.bundleContext = bundleContext;
this.properties = properties;
register();
}
public DefaultPropertiesProvider(String objectId
, String objectType
, String configurationPid
, BundleContext bundleContext
, Map<String, Object> properties) {
this.objectId = objectId;
this.objectType = objectType;
this.configurationPid = configurationPid;
this.bundleContext = bundleContext;
this.properties = properties;
register();
}
protected void register() {
if (!CommonUtils.isValid(objectId) || !CommonUtils.isValid(objectType))
return;
try {
String fileName = System.getProperty("karaf.etc");
Path path = Paths.get(fileName).resolve(objectType).resolve(configurationPid + ".cfg");
File f = new File(path.toUri());
/*
if ((this.configurationPid != null) && (this.bundleContext != null)) {
ServiceReference<CustomConfigLocationCollector> collectorRef =
this.bundleContext.getServiceReference(CustomConfigLocationCollector.class);
if (collectorRef != null) {
CustomConfigLocationCollector collector = this.bundleContext.getService(collectorRef);
if (collector != null)
collector.addCustomLocation(configurationPid, "file:/" + f.getAbsolutePath().replace("\\", "/"));
else
log.error("registerImmutables :: COLLECTOR IS NULL");
this.bundleContext.ungetService(collectorRef);
} else {
log.error("registerImmutables :: REF IS NULL");
}
}
*/
if (!f.exists()) {
f.getParentFile().mkdirs();
f.createNewFile();
} else {
// we're not updating existing files
return;
}
ServiceReference<ConfigRepository> refCR = bundleContext.getServiceReference(ConfigRepository.class);
if (refCR == null)
return;
ConfigRepository repo = bundleContext.getService(refCR);
TypedProperties typedProperties;
/* ServiceReference<ConfigurationAdmin> refCA = bundleContext.getServiceReference(ConfigurationAdmin.class);
if (refCA == null)
return;
ConfigurationAdmin configAdmin = bundleContext.getService(refCA);
Configuration config = configAdmin.getConfiguration(configurationPid);
Dictionary<String, Object> props = config.getProperties();
Iterator<String> iter = props.keys().asIterator();
System.out.println("PROPS :: ");
while(iter.hasNext()) {
String key = iter.next();
System.out.println(key + "-->" + props.get(key) + ":" + props.get(key).getClass().getName());
}
props.put("felix.fileinstall.filename", "file:/" + f.getAbsolutePath().replace("\\", "/"));
config.update(props);
TypedProperties typedProperties = repo.getConfig(configurationPid);
System.out.println("TYPED PROPS 0:: ");
for (Entry<String, Object> entry: typedProperties.entrySet())
System.out.println(entry.getKey() + "-->" + entry.getValue() + ":" + entry.getValue().getClass().getName());
*/
typedProperties = repo.getConfig(configurationPid);
typedProperties.putAll(properties);
typedProperties.remove( Constants.SERVICE_PID );
typedProperties.remove( ConfigurationAdmin.SERVICE_FACTORYPID );
typedProperties.remove( "felix.fileinstall.filename" );
typedProperties.save(f);
// typedProperties = repo.getConfig(configurationPid);
// typedProperties.put("felix.fileinstall.filename", "file:/" + f.getAbsolutePath().replace("\\", "/"));
/* repo.update(configurationPid, typedProperties);
typedProperties = repo.getConfig(configurationPid);
System.out.println("TYPED PROPS 2:: ");
for (Entry<String, Object> entry: typedProperties.entrySet())
System.out.println(entry.getKey() + "-->" + entry.getValue() + ":" + entry.getValue().getClass().getName());
*/
bundleContext.ungetService(refCR);
} catch (IOException | InvalidSyntaxException e) {
log.error("Error registering default properties for " + configurationPid + "\n", e);
}
}
@Override
public int size() {
return properties.size();
}
@Override
public boolean isEmpty() {
return properties.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return properties.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return properties.containsValue(value);
}
@Override
public Object get(Object key) {
return properties.get(key);
}
@Override
public Object put(String key, Object value) {
return properties.put(key, value);
}
@Override
public Object remove(Object key) {
return properties.remove(key);
}
@Override
public void putAll(Map<? extends String, ? extends Object> m) {
properties.putAll(m);
}
@Override
public void clear() {
properties.clear();
}
@Override
public Set<String> keySet() {
return properties.keySet();
}
@Override
public Collection<Object> values() {
return properties.values();
}
@Override
public Set<Entry<String, Object>> entrySet() {
return properties.entrySet();
}
}

View File

@ -0,0 +1,97 @@
/*-
* ~~~~~~licensing~~~~~~
* configuration-test-1
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
import java.util.Map;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DefaultPropertiesProviderWithImmutables extends DefaultPropertiesProvider implements Immutables {
private static final Logger log = LoggerFactory.getLogger(DefaultPropertiesProviderWithImmutables.class);
protected Map<String, Object> immutables;
public DefaultPropertiesProviderWithImmutables(String objectId
, String objectType
, String configurationPid
, BundleContext bundleContext
, Map<String, Object> configurables) {
super(objectId, objectType, configurationPid, bundleContext, configurables);
}
public DefaultPropertiesProviderWithImmutables(String configurationPid
, BundleContext bundleContext
, Map<String, Object> configurables) {
super(configurationPid, bundleContext, configurables);
}
public DefaultPropertiesProviderWithImmutables(String configurationPid
, BundleContext bundleContext
, Map<String, Object> configurables
, Map<String, Object> immutables) {
super(configurationPid, bundleContext, configurables);
this.immutables = immutables;
registerImmutables();
}
public DefaultPropertiesProviderWithImmutables(String objectId
, String objectType
, String configurationPid
, BundleContext bundleContext
, Map<String, Object> configurables
, Map<String, Object> immutables) {
super(objectId, objectType, configurationPid, bundleContext, configurables);
this.immutables = immutables;
registerImmutables();
}
protected void registerImmutables() {
if ((this.configurationPid != null) && (this.bundleContext != null)) {
ServiceReference<ImmutablesCollector> collectorRef = this.bundleContext.getServiceReference(ImmutablesCollector.class);
if (collectorRef != null) {
ImmutablesCollector collector = this.bundleContext.getService(collectorRef);
if (collector != null)
collector.add(this);
else
log.error("registerImmutables :: COLLECTOR IS NULL");
this.bundleContext.ungetService(collectorRef);
} else {
log.error("registerImmutables :: REF IS NULL");
}
}
}
@Override
public String getPid() {
return this.configurationPid;
}
@Override
public Map<String, Object> getProperties() {
return this.immutables;
};
}

View File

@ -0,0 +1,29 @@
/*-
* ~~~~~~licensing~~~~~~
* configuration-test-1
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
import java.util.Map;
public interface Immutables {
String getPid();
Map<String, Object> getProperties();
}

View File

@ -0,0 +1,26 @@
/*-
* ~~~~~~licensing~~~~~~
* configuration-test-1
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
public interface ImmutablesCollector {
void add(Immutables immutables);
}

View File

@ -0,0 +1,117 @@
/*-
* ~~~~~~licensing~~~~~~
* configuration-test-1
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
import java.io.IOException;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationPlugin;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = {ConfigurationPlugin.class, ImmutablesCollector.class}, immediate = true,
property = {ConfigurationPlugin.CM_TARGET + "=*"
, ConfigurationPlugin.CM_RANKING + "=100"
, "config.plugin.id=ImmutablesConfigurationPlugin"})
public class ImmutablesConfigurationPlugin implements ConfigurationPlugin, ImmutablesCollector {
private static final Logger log = LoggerFactory.getLogger(ImmutablesConfigurationPlugin.class);
protected BundleContext bundleContext;
protected Map<String, Immutables> immutablesMap = new HashMap<>();
protected Map<String, Dictionary<String, Object>> immutablesDataMap = new HashMap<>();
@Reference(cardinality = ReferenceCardinality.MANDATORY)
ConfigurationAdmin configurationAdmin;
public void activate(ComponentContext componentContext) {
this.bundleContext = componentContext.getBundleContext();
log.debug("ImmutablesConfigurationPlugin activated");
}
@Override
public void modifyConfiguration(ServiceReference<?> reference, Dictionary<String, Object> properties) {
String pid = properties.get(Constants.SERVICE_PID).toString();
if (immutablesDataMap.containsKey(pid)) {
Dictionary<String, Object> ims = immutablesDataMap.get(pid);
Iterator<String> iter = ims.keys().asIterator();
while (iter.hasNext()) {
String key = iter.next();
properties.put(key, ims.get(key));
}
log.debug("DATA: " + pid + " FOUND");
} else {
log.debug("DATA: " + pid + " NOT FOUND");
}
}
@Override
public void add(Immutables immutables) {
synchronized (immutablesDataMap) {
boolean reload = true;
if (immutablesDataMap.containsKey(immutables.getPid())) {
Dictionary<String, Object> current = immutablesDataMap.get(immutables.getPid());
reload = !immutables.getProperties().entrySet().stream()
.allMatch(e -> e.getValue().equals(current.get(e.getKey())));
}
if (!reload) {
log.debug("Immutables for " + immutables.getPid() + " already loaded");
return;
}
immutablesDataMap.remove(immutables.getPid());
log.debug("Adding direct Immutables for " + immutables.getPid());
Dictionary<String, Object> ims = new Hashtable<>();
Map<String, Object> properties = immutables.getProperties();
if (properties != null)
for (Entry<String, Object> entry: properties.entrySet())
ims.put(entry.getKey(), entry.getValue());
immutablesDataMap.put(immutables.getPid(), ims);
try {
Dictionary<String, Object> props = configurationAdmin.getConfiguration(immutables.getPid()).getProperties();
if (props == null)
props = new Hashtable<>();
Iterator<String> keys = ims.keys().asIterator();
while (keys.hasNext()) {
String key = keys.next();
props.put(key, ims.get(key));
}
configurationAdmin.getConfiguration(immutables.getPid()).setBundleLocation("?");
configurationAdmin.getConfiguration(immutables.getPid()).update(props);
} catch (IOException e) {
log.error("Failed updateing configuration", e);
}
}
}
}

View File

@ -0,0 +1,99 @@
/*-
* ~~~~~~licensing~~~~~~
* configuration-test-1
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.config;
import java.util.Map;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ImmutablesImpl implements Immutables {
private static final Logger log = LoggerFactory.getLogger(ImmutablesImpl.class);
protected BundleContext bundleContext;
protected String pid;
protected Map<String, Object> properties;
public ImmutablesImpl() {
super();
}
public ImmutablesImpl(String pid, BundleContext bundleContext) {
super();
setPid(pid);
setBundleContext(bundleContext);
}
public ImmutablesImpl(String pid, BundleContext bundleContext, Map<String, Object> properties) {
super();
setProperties(properties);
setPid(pid);
setBundleContext(bundleContext);
}
public void setPid(String pid) {
this.pid = pid;
checkAndRegister();
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
checkAndRegister();
}
protected void checkAndRegister() {
if ((this.pid != null) && (this.bundleContext != null)) {
log.debug("\n\tcheckAndRegister :: START");
ServiceReference<ImmutablesCollector> collectorRef = this.bundleContext.getServiceReference(ImmutablesCollector.class);
if (collectorRef != null) {
log.debug("\n\tcheckAndRegister :: GET COLLECTOR");
ImmutablesCollector collector = this.bundleContext.getService(collectorRef);
if (collector != null)
collector.add(this);
else
log.debug("\n\tcheckAndRegister :: COLLECTOR IS NULL");
this.bundleContext.ungetService(collectorRef);
} else {
log.debug("\n\tcheckAndRegister :: REF IS NULL");
}
}
}
@Override
public String getPid() {
return this.pid;
}
@Override
public Map<String, Object> getProperties() {
return this.properties;
}
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -19,7 +19,9 @@
*/ */
package ru.entaxy.esb.platform.runtime.base.connecting.adapter.core.management; package ru.entaxy.esb.platform.runtime.base.connecting.adapter.core.management;
public interface AdapterMBean { import ru.entaxy.esb.platform.base.management.core.api.RuntimeTypedMBean;
public interface AdapterMBean extends RuntimeTypedMBean {
public boolean isInited(); public boolean isInited();

View File

@ -22,8 +22,11 @@ package ru.entaxy.esb.platform.runtime.base.connecting.adapter.core.management;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
import javax.management.StandardMBean; import javax.management.StandardMBean;
import ru.entaxy.esb.platform.base.management.core.api.EntaxyRuntimeTyped;
import ru.entaxy.esb.platform.runtime.base.connecting.adapter.core.api.Adapter; import ru.entaxy.esb.platform.runtime.base.connecting.adapter.core.api.Adapter;
//@TODO move string to constant
@EntaxyRuntimeTyped(name = "entaxy.runtime.adapter")
public class AdapterMBeanImpl extends StandardMBean implements AdapterMBean { public class AdapterMBeanImpl extends StandardMBean implements AdapterMBean {
protected Adapter adapter; protected Adapter adapter;

View File

@ -24,9 +24,9 @@ import ru.entaxy.esb.platform.base.management.core.Qualifier;
public interface AdaptersMBean { public interface AdaptersMBean {
public static final String ADAPTERS_KEY = "categrory"; public static final String ADAPTERS_KEY = "category";
public static final String ADAPTERS_VALUE = "adapters"; public static final String ADAPTERS_VALUE = "adapter";
public static final Qualifier Q_ADAPTERS = ManagementCore.Q_PLATFORM.qualifier(ADAPTERS_KEY, ADAPTERS_VALUE); public static final Qualifier Q_ADAPTERS = ManagementCore.Q_PLATFORM.qualifier(ADAPTERS_KEY, ADAPTERS_VALUE);

View File

@ -67,7 +67,7 @@ public class AdaptersMBeanImpl extends StandardMBean implements AdaptersMBean {
@Activate @Activate
public void activate(ComponentContext componentContext) { public void activate(ComponentContext componentContext) {
log.info(" >> ACTIVATE <<"); log.debug(" >> ACTIVATE <<");
this.bundleContext = componentContext.getBundleContext(); this.bundleContext = componentContext.getBundleContext();
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -55,7 +55,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${destinationType}:${destinationName}" "expression": "${destinationType}:${destinationName}"
} }
}, },
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -665,7 +665,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${destinationType}:${destinationName}" "expression": "${destinationType}:${destinationName}"
} }
}, },
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -55,7 +55,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${destinationType}:${destinationName}" "expression": "${destinationType}:${destinationName}"
} }
}, },
{ {

View File

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -19,6 +18,9 @@
<properties> <properties>
<bundle.osgi.dynamicimport.pkg>*</bundle.osgi.dynamicimport.pkg> <bundle.osgi.dynamicimport.pkg>*</bundle.osgi.dynamicimport.pkg>
<bundle.osgi.export.pkg>ru.entaxy.platform.adapter.file</bundle.osgi.export.pkg>
<bundle.osgi.private.pkg>template,
ru.entaxy.adapter</bundle.osgi.private.pkg>
<!-- <bundle.osgi.private.pkg>ru.entaxy.adapter</bundle.osgi.private.pkg>--> <!-- <bundle.osgi.private.pkg>ru.entaxy.adapter</bundle.osgi.private.pkg>-->
</properties> </properties>
@ -30,11 +32,30 @@
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<instructions> <instructions>
<Entaxy-Adapter>true</Entaxy-Adapter> <!-- Entaxy-Adapter>true</Entaxy-Adapter>
<Entaxy-Adapter-Class/> <Entaxy-Adapter-Class / -->
<Entaxy-Factory-Provider>true</Entaxy-Factory-Provider>
<Entaxy-Template-Provider>true</Entaxy-Template-Provider>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-file</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-util</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>base-support</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project> </project>

View File

@ -0,0 +1,69 @@
/*-
* ~~~~~~licensing~~~~~~
* file-adapter
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.adapter.file;
import java.io.File;
import java.util.Map;
import org.apache.camel.component.file.FileComponent;
import org.apache.camel.component.file.GenericFileEndpoint;
import org.apache.camel.util.StringHelper;
import ru.entaxy.platform.base.support.CommonUtils;
public class ExtendedFileComponent extends FileComponent {
protected String rootDirectory = "";
@Override
protected GenericFileEndpoint<File> buildFileEndpoint(String uri, String remaining, Map<String, Object> parameters)
throws Exception {
// copied from parent
if (StringHelper.hasStartToken(remaining, "simple")) {
throw new IllegalArgumentException("Invalid directory: " + remaining + ". Dynamic expressions with ${ } placeholders is not allowed."
+ " Use the fileName option to set the dynamic expression.");
}
String current = remaining;
if (CommonUtils.isValid(rootDirectory)) {
current = rootDirectory;
if (CommonUtils.isValid(remaining) && !".".equals(remaining)) {
if (!current.endsWith("/"))
current += "/";
if (remaining.startsWith("/"))
current += remaining.substring(1);
else
current += remaining;
}
}
log.debug("CREATING ENDPOINT FOR [{}]", current);
return super.buildFileEndpoint(uri, current, parameters);
}
public String getRootDirectory() {
return rootDirectory;
}
public void setRootDirectory(String rootDirectory) {
this.rootDirectory = rootDirectory;
}
}

View File

@ -516,7 +516,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${directoryName}" "expression": "${directoryName}"
} }
}, },
{ {

View File

@ -0,0 +1,47 @@
[#ftl attributes={"generated.type":"blueprint"}]
[#--
~~~~~~licensing~~~~~~
file-adapter
==========
Copyright (C) 2020 - 2021 EmDev LLC
==========
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.
~~~~~~/licensing~~~~~~
--]
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"
>
<service interface="org.apache.camel.Component" ref="[=objectId]">
<service-properties>
<entry key="connection.name" value="[=objectId]"/>
</service-properties>
</service>
<bean id="[=objectId]" class="ru.entaxy.platform.adapter.file.ExtendedFileComponent">
[#if properties??]
[#list properties as key, value]
[#if !key?starts_with("##") && !key?starts_with("__")] [#-- we skip additional properties --]
<property name="[=key]" value="[=value]"/>
[/#if]
[/#list]
[/#if]
</bean>
</blueprint>

View File

@ -45,7 +45,7 @@
</service-properties> </service-properties>
</service> </service>
<bean id="[=connection.name]" class="org.apache.camel.component.file.FileComponent"> <bean id="[=connection.name]" class="ru.entaxy.platform.adapter.file.ExtendedFileComponent">
[#if connection.properties??] [#if connection.properties??]
[#list connection.properties as key, value] [#list connection.properties as key, value]
<property name="[=key]" value="[='$']{[=connection.configurationPid].[=key]}"/> <property name="[=key]" value="[='$']{[=connection.configurationPid].[=key]}"/>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -110,7 +110,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${dataSourceName}" "expression": "${dataSourceName}"
} }
}, },
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -665,7 +665,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${destinationType}:${destinationName}" "expression": "${destinationType}:${destinationName}"
} }
}, },
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId> <groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>connecting</artifactId> <artifactId>connecting</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -110,7 +110,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${dataSourceName}" "expression": "${dataSourceName}"
} }
}, },
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -55,7 +55,7 @@
"type": "pathParameter", "type": "pathParameter",
"generator": "", "generator": "",
"config": { "config": {
"expession": "${destinationType}:${destinationName}" "expression": "${destinationType}:${destinationName}"
} }
}, },
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId> <groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>connecting</artifactId> <artifactId>connecting</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>generator</artifactId> <artifactId>generator</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting.generator</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting.generator</groupId>
<artifactId>common-templates-collection</artifactId> <artifactId>common-templates-collection</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>generator</artifactId> <artifactId>generator</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -20,7 +20,6 @@
<bundle.osgi.export.pkg> <bundle.osgi.export.pkg>
ru.entaxy.esb.platform.runtime.base.connecting.generator.ftl ru.entaxy.esb.platform.runtime.base.connecting.generator.ftl
</bundle.osgi.export.pkg> </bundle.osgi.export.pkg>
<freemarker.version>2.3.29</freemarker.version>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -105,6 +105,22 @@ public class FTLGenerator extends AbstractSelfPublishGenerator<FTLGenerator>
return generateForTemplate(template, properties); return generateForTemplate(template, properties);
} }
@Override
public boolean isGeneratable(Map<String, Object> properties) throws Exception {
prepareTemplate(properties);
if (template == null)
return false;
URL templateURL = template.getTemplateLocation()==null
?FrameworkUtil.getBundle(FTLGenerator.class).getEntry(DEFAULT_TEMPLATE_PATH)
:template.getTemplateLocation();
try {
Template temp = getTemplateByFullName(templateURL, template.getTemplateFullName());
return (temp != null);
} catch (Exception e) {
return false;
}
}
public Generated generateForTemplate(ru.entaxy.base.generator.template.Template template, public Generated generateForTemplate(ru.entaxy.base.generator.template.Template template,
Map<String, Object> properties) throws Exception { Map<String, Object> properties) throws Exception {
@ -194,19 +210,19 @@ public class FTLGenerator extends AbstractSelfPublishGenerator<FTLGenerator>
if (this.template != null) if (this.template != null)
return; return;
Map<String, Object> finalPropertes = new HashMap<>(); Map<String, Object> finalProperties = new HashMap<>();
finalPropertes.putAll(initialProperties); finalProperties.putAll(initialProperties);
finalPropertes.putAll(generationProperties); finalProperties.putAll(generationProperties);
TemplateImpl temp = new TemplateImpl(); TemplateImpl temp = new TemplateImpl();
temp.setBundleContext( temp.setBundleContext(
(BundleContext)finalPropertes.getOrDefault(Generator.PROP_TARGET_BUNDLE_CONTEXT (BundleContext)finalProperties.getOrDefault(Generator.PROP_TARGET_BUNDLE_CONTEXT
, FrameworkUtil.getBundle(FTLGenerator.class).getBundleContext()) , FrameworkUtil.getBundle(FTLGenerator.class).getBundleContext())
); );
temp.setTemplateName((String)finalPropertes.getOrDefault(PROP_TEMPLATE_NAME temp.setTemplateName((String)finalProperties.getOrDefault(PROP_TEMPLATE_NAME
, (String)finalPropertes.getOrDefault(Generator.PROP_USAGE_TYPE , (String)finalProperties.getOrDefault(Generator.PROP_USAGE_TYPE
, "root"))); , "root")));
temp.setPath((String)finalPropertes.getOrDefault(PROP_TEMPLATE_NAME temp.setPath((String)finalProperties.getOrDefault(PROP_TEMPLATE_NAME
, DEFAULT_TEMPLATE_PATH) , DEFAULT_TEMPLATE_PATH)
); );

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>generator</artifactId> <artifactId>generator</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -20,6 +20,7 @@
package ru.entaxy.base.generator.template; package ru.entaxy.base.generator.template;
import java.net.URL; import java.net.URL;
import java.util.Map;
public interface Template { public interface Template {
@ -29,5 +30,5 @@ public interface Template {
public String getTemplateName(); public String getTemplateName();
public String getTemplateFileName(); public String getTemplateFileName();
public String getTemplateFullName(); public String getTemplateFullName();
public Map<String, String> getAdditionalProperties();
} }

View File

@ -21,6 +21,7 @@ package ru.entaxy.base.generator.template;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -45,6 +46,8 @@ public class TemplateImpl implements Template {
protected String templateLocation; protected String templateLocation;
protected Map<String, String> additionalProperties = null;
public void load(ProvidedTemplate providedTemplate) { public void load(ProvidedTemplate providedTemplate) {
id = providedTemplate.getId(); id = providedTemplate.getId();
name = providedTemplate.getName(); name = providedTemplate.getName();
@ -55,6 +58,7 @@ public class TemplateImpl implements Template {
if (!path.endsWith("/")) if (!path.endsWith("/"))
path += "/"; path += "/";
description = providedTemplate.getDescription(); description = providedTemplate.getDescription();
additionalProperties = providedTemplate.getAdditionalProperties();
} }
@Override @Override
@ -121,4 +125,12 @@ public class TemplateImpl implements Template {
this.bundleContext = bundleContext; this.bundleContext = bundleContext;
} }
public Map<String, String> getAdditionalProperties() {
return additionalProperties;
}
public void setAdditionalProperties(Map<String, String> additionalProperties) {
this.additionalProperties = additionalProperties;
}
} }

View File

@ -25,6 +25,7 @@ public interface TemplateService {
public static final String TEMPLATE_PROVIDER_HEADER = "Entaxy-Template-Provider"; public static final String TEMPLATE_PROVIDER_HEADER = "Entaxy-Template-Provider";
public static final String PROP_PREFIX = "template.";
public static final String PROP_ID = "template.id"; public static final String PROP_ID = "template.id";
public static final String PROP_TYPE = "template.type"; public static final String PROP_TYPE = "template.type";
public static final String PROP_NAME = "template.name"; public static final String PROP_NAME = "template.name";

View File

@ -85,6 +85,11 @@ public class LegacyTemplateAdapter {
return template.getTemplateFileName() + ".ftl"; return template.getTemplateFileName() + ".ftl";
} }
@Override
public Map<String, String> getAdditionalProperties() {
return null;
}
} }
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, unbind = "removeTemplate") @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, unbind = "removeTemplate")

View File

@ -19,6 +19,8 @@
*/ */
package ru.entaxy.base.generator.template.impl; package ru.entaxy.base.generator.template.impl;
import java.util.Map;
import org.osgi.framework.ServiceRegistration; import org.osgi.framework.ServiceRegistration;
import ru.entaxy.base.generator.template.Template; import ru.entaxy.base.generator.template.Template;
@ -32,6 +34,7 @@ public class ProvidedTemplate {
protected String type; protected String type;
protected String path; protected String path;
protected String description; protected String description;
protected Map<String, String> additionalProperties = null;
public ServiceRegistration<Template> registration; public ServiceRegistration<Template> registration;
@ -47,6 +50,7 @@ public class ProvidedTemplate {
this.type = templateMetadata.getType(); this.type = templateMetadata.getType();
this.path = templateMetadata.getPath(); this.path = templateMetadata.getPath();
this.description = templateMetadata.getDescription(); this.description = templateMetadata.getDescription();
this.additionalProperties = templateMetadata.getAdditionalProperties();
} }
public String getId() { public String getId() {
@ -105,5 +109,13 @@ public class ProvidedTemplate {
this.description = description; this.description = description;
} }
public Map<String, String> getAdditionalProperties() {
return additionalProperties;
}
public void setAdditionalProperties(Map<String, String> additionalProperties) {
this.additionalProperties = additionalProperties;
}
} }

View File

@ -24,9 +24,9 @@ import java.io.InputStreamReader;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Dictionary; import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Optional; import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
@ -93,7 +93,12 @@ public class TemplateBundleTrackerCustomizer implements BundleTrackerCustomizer<
if (!isTemplateProvider) if (!isTemplateProvider)
return null; return null;
// Enumeration<String> entries = bundle.getEntryPaths(TemplateProvider.TEMPLATE_PATH + "/metadata.json");
URL metadataUrl = bundle.getEntry(TemplateProvider.TEMPLATE_PATH + "/metadata.json"); URL metadataUrl = bundle.getEntry(TemplateProvider.TEMPLATE_PATH + "/metadata.json");
if (metadataUrl != null) {
// descriptor is found
String metadata = new BufferedReader ( String metadata = new BufferedReader (
new InputStreamReader( new InputStreamReader(
metadataUrl.openStream(), StandardCharsets.UTF_8)) metadataUrl.openStream(), StandardCharsets.UTF_8))
@ -118,6 +123,49 @@ public class TemplateBundleTrackerCustomizer implements BundleTrackerCustomizer<
result.providedTemplates.add(providedTemplate); result.providedTemplates.add(providedTemplate);
} }
} else {
// try to locate templates
log.debug("BEGIN :: Searching for templates in " + bundle.getBundleId());
Enumeration<URL> foundEntries = bundle.findEntries(TemplateProvider.TEMPLATE_PATH, "*.*", true);
while (foundEntries.hasMoreElements()) {
URL entry = foundEntries.nextElement();
log.debug("FOUND :: " + entry.toString());
if (entry.toString().endsWith("/")) {
log.debug(":: .. is folder");
continue;
}
String localPath = entry.toString();
localPath = localPath.substring(localPath.indexOf(TemplateProvider.TEMPLATE_PATH) + TemplateProvider.TEMPLATE_PATH.length() + 1);
String fullname = localPath.substring(localPath.lastIndexOf("/")+1);
String path = localPath.lastIndexOf("/")>=0
?localPath.substring(0, localPath.lastIndexOf("/"))
:"";
String fullPath = TemplateProvider.TEMPLATE_PATH + "/" + path;
String fileName = fullname.substring(0, fullname.lastIndexOf("."));
String fileType = fullname.substring(fullname.lastIndexOf(".")+1);
String id = path.replace("/", ".")
+ (path.isEmpty()?"":".")
+ fileName;
log.debug(":: localPath = " + localPath + "; fullName = " + fullname + "; fileName = " + fileName
+ "; fileType = " + fileType + "; path = " + path);
TemplateMetadata meta = new TemplateMetadata();
meta.setId(id);
meta.setFilename(fileName);
meta.setFullname(fullname);
meta.setName(id);
meta.setType(fileType);
meta.setPath(fullPath);
meta.setDescription("Found in bundle [" + bundle.getBundleId() + "] on path [" + localPath + "]");
ProvidedTemplate providedTemplate = new ProvidedTemplate(meta);
result.providedTemplates.add(providedTemplate);
}
log.debug("END :: Searching for templates in " + bundle.getBundleId());
}
return result; return result;
} }
@ -135,6 +183,9 @@ public class TemplateBundleTrackerCustomizer implements BundleTrackerCustomizer<
props.put(TemplateService.PROP_NAME, provided.getName()); props.put(TemplateService.PROP_NAME, provided.getName());
props.put(TemplateService.PROP_TYPE, provided.getType()); props.put(TemplateService.PROP_TYPE, provided.getType());
props.put(TemplateService.PROP_DESCRIPTION, provided.getDescription()); props.put(TemplateService.PROP_DESCRIPTION, provided.getDescription());
if (provided.getAdditionalProperties() != null) {
provided.getAdditionalProperties().forEach((k,v) -> {props.put(TemplateService.PROP_PREFIX + k, v);});
}
ServiceRegistration<Template> registration = ServiceRegistration<Template> registration =
templateProvider.bundleContext.registerService( templateProvider.bundleContext.registerService(

View File

@ -19,6 +19,7 @@
*/ */
package ru.entaxy.base.generator.template.impl; package ru.entaxy.base.generator.template.impl;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import ru.entaxy.platform.base.support.CommonUtils; import ru.entaxy.platform.base.support.CommonUtils;
@ -32,6 +33,7 @@ public class TemplateMetadata {
protected String fullname; protected String fullname;
protected String path; protected String path;
protected String description = ""; protected String description = "";
protected Map<String, String> additionalProperties;
public String getId() { public String getId() {
return id; return id;
@ -93,5 +95,11 @@ public class TemplateMetadata {
public void setDescription(String description) { public void setDescription(String description) {
this.description = description; this.description = description;
} }
public Map<String, String> getAdditionalProperties() {
return additionalProperties;
}
public void setAdditionalProperties(Map<String, String> additionalProperties) {
this.additionalProperties = additionalProperties;
}
} }

View File

@ -29,7 +29,7 @@ public interface Generated {
public static final String GENERATED_TYPE_BLUEPRINT = "blueprint"; public static final String GENERATED_TYPE_BLUEPRINT = "blueprint";
public static final String GENERATED_TYPE_BLUEPRINT_NODE = "blueprint-node"; public static final String GENERATED_TYPE_BLUEPRINT_FRAGMENT = "blueprint.fragment";
public static Generated create() { public static Generated create() {
return new GeneratedImpl(); return new GeneratedImpl();

View File

@ -28,4 +28,5 @@ public interface Generator {
public String getGeneratorId(); public String getGeneratorId();
public Generated generate(Map<String, Object> properties) throws Exception; public Generated generate(Map<String, Object> properties) throws Exception;
public boolean isGeneratable(Map<String, Object> properties) throws Exception;
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>generator</artifactId> <artifactId>generator</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId> <groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>connecting</artifactId> <artifactId>connecting</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -21,5 +21,6 @@
<module>ftl-generator</module> <module>ftl-generator</module>
<module>generator-factory</module> <module>generator-factory</module>
<module>common-templates-collection</module> <module>common-templates-collection</module>
<module>template-service-shell</module>
</modules> </modules>
</project> </project>

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,50 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>generator</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting.generator</groupId>
<artifactId>template-service-shell</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: BASE :: TEMPLATES :: SHELL</name>
<description>ENTAXY :: PLATFORM :: BASE :: TEMPLATES :: SHELL</description>
<properties>
<bundle.osgi.remove.headers>NONE</bundle.osgi.remove.headers>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.karaf</groupId>
<artifactId>org.apache.karaf.util</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.core</artifactId>
<version>${karaf.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.base.connecting.generator
</groupId>
<artifactId>generator-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.base.connecting.generator
</groupId>
<artifactId>generator-factory</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>base-support</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,88 @@
/*-
* ~~~~~~licensing~~~~~~
* template-service-test
* ==========
* Copyright (C) 2020 - 2021 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.base.generator.template.shell;
import java.util.HashMap;
import java.util.Map;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import ru.entaxy.base.generator.template.Template;
import ru.entaxy.base.generator.template.TemplateAwareGenerator;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generator;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.factory.GeneratorFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
@Service
@Command(scope = "templates", name = "generate")
public class Generate extends TemplateServiceSupport implements Action {
@Argument(index = 0, name = "template-id", required = true)
String templateId;
@Argument(index = 1, name = "parameters", required = false)
String params;
@Override
public Object execute() throws Exception {
Template t = templateService.getTemplateById(templateId);
if (t == null) {
System.out.println("Template [" + templateId + "] not found");
return null;
}
TemplateAwareGenerator g = GeneratorFactory.createGenerator(t);
if (g == null) {
System.out.println("Generator for template [" + templateId + "] not found");
return null;
}
Generated result = null;
if (CommonUtils.isValid(params)) {
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
JsonElement je = (new JsonParser()).parse(params);
Map<String, Object> map = JSONUtils.element2map(je);
result = g.generate(t, map);
} else {
result = g.generate(t, new HashMap<>());
}
if (result == null) {
System.out.println("Generated is empty, template: [" + templateId + "] not found");
return null;
} else {
System.out.println("Generated: ");
System.out.println("\ttype: " + result.getType());
System.out.println("\tcontent: " + (result.getObject()==null?"null":"[==\n" + result.getObject().toString() + "\n==]"));
}
return null;
}
}

View File

@ -0,0 +1,69 @@
/*-
* ~~~~~~licensing~~~~~~
* template-service-test
* ==========
* Copyright (C) 2020 - 2021 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.base.generator.template.shell;
import java.util.Comparator;
import java.util.stream.Collectors;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.support.table.ShellTable;
import ru.entaxy.base.generator.template.Template;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generator;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.factory.GeneratorFactory;
@Service
@Command(scope = "templates", name = "list")
public class ListTemplates extends TemplateServiceSupport implements Action {
@Override
public Object execute() throws Exception {
ShellTable table = new ShellTable();
table.column("id");
table.column("File");
table.column("Location");
table.column("Generator");
for (Template t: templateService.getAllTemplates().stream().sorted(new Comparator<Template>() {
@Override
public int compare(Template o1, Template o2) {
return o1.getId().compareToIgnoreCase(o2.getId());
}
}).collect(Collectors.toList()) ) {
Generator g = (Generator)GeneratorFactory.createGenerator(t);
table.addRow().addContent(
t.getId(),
t.getTemplateFullName(),
t.getTemplateLocation()==null?"":t.getTemplateLocation().toString(),
(g==null?"NOT FOUND":g.getGeneratorId())
);
}
table.print(System.out);
return null;
}
}

View File

@ -0,0 +1,31 @@
/*-
* ~~~~~~licensing~~~~~~
* template-service-test
* ==========
* Copyright (C) 2020 - 2021 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.base.generator.template.shell;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import ru.entaxy.base.generator.template.TemplateService;
public class TemplateServiceSupport {
@Reference
TemplateService templateService;
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime</groupId> <groupId>ru.entaxy.esb.platform.runtime</groupId>
<artifactId>base</artifactId> <artifactId>base</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>producer</artifactId> <artifactId>producer</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId> <groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>connecting</artifactId> <artifactId>connecting</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId> <groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
<artifactId>producer</artifactId> <artifactId>producer</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>ru.entaxy.esb.platform.runtime</groupId> <groupId>ru.entaxy.esb.platform.runtime</groupId>
<artifactId>base</artifactId> <artifactId>base</artifactId>
<version>1.8.1</version> <version>1.8.2</version>
</parent> </parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId> <groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>management-core</artifactId> <artifactId>management-core</artifactId>

View File

@ -46,7 +46,7 @@ public class AnnotatedMBean<I> extends StandardMBean {
@Override @Override
public MBeanInfo getMBeanInfo() { public MBeanInfo getMBeanInfo() {
log.info(this.interfaceClass==null?">> INTERFACE IS NULL":">> " + this.interfaceClass.getName()); log.debug(this.interfaceClass==null?">> INTERFACE IS NULL":">> " + this.interfaceClass.getName());
MBeanExportPolicy policy = MBeanExportPolicy.IGNORE_ANNOTATIONS; MBeanExportPolicy policy = MBeanExportPolicy.IGNORE_ANNOTATIONS;
MBeanAnnotated anno = this.interfaceClass.getAnnotation(MBeanAnnotated.class); MBeanAnnotated anno = this.interfaceClass.getAnnotation(MBeanAnnotated.class);
if (anno != null) if (anno != null)

View File

@ -0,0 +1,34 @@
/*-
* ~~~~~~licensing~~~~~~
* management-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.esb.platform.base.management.core.api;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(TYPE)
@Inherited
public @interface EntaxyRuntimeTyped {
String name() default "";
}

View File

@ -0,0 +1,32 @@
/*-
* ~~~~~~licensing~~~~~~
* management-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.esb.platform.base.management.core.api;
public interface RuntimeTypedMBean {
@Attribute(desc = "Type of Entaxy runtime object")
public default String getRuntimeType() {
if (this.getClass().isAnnotationPresent(EntaxyRuntimeTyped.class)) {
return ((EntaxyRuntimeTyped)this.getClass().getAnnotation(EntaxyRuntimeTyped.class)).name();
} else
return "";
}
}

View File

@ -122,7 +122,7 @@ public class BundleAwareMBeanImpl<T extends BundleAwareManagedObject, I>
public void refreshBundleInfo() { public void refreshBundleInfo() {
Bundle b = FrameworkUtil.getBundle(getClass()).getBundleContext().getBundle(getBundleId()); Bundle b = FrameworkUtil.getBundle(getClass()).getBundleContext().getBundle(getBundleId());
// track bundeState // track bundleState
AttributeChangeTracker tracker = new AttributeChangeTracker(); AttributeChangeTracker tracker = new AttributeChangeTracker();
tracker.oldValue(this.managedObject.getBundleState()); tracker.oldValue(this.managedObject.getBundleState());
this.managedObject.bundleState(b.getState()); this.managedObject.bundleState(b.getState());

View File

@ -39,6 +39,6 @@ public interface BundleAwareManagedObject {
BundleAwareManagedObject bundleId(long bundleId); BundleAwareManagedObject bundleId(long bundleId);
BundleAwareManagedObject bundleSymbolicName(String bundleSeymbolicName); BundleAwareManagedObject bundleSymbolicName(String bundleSymbolicName);
} }

View File

@ -98,8 +98,8 @@ public class BundleAwareManagedObjectImpl implements BundleAwareManagedObject {
} }
@Override @Override
public BundleAwareManagedObject bundleSymbolicName(String bundleSeymbolicName) { public BundleAwareManagedObject bundleSymbolicName(String bundleSymbolicName) {
setBundleSymbolicName(bundleSeymbolicName); setBundleSymbolicName(bundleSymbolicName);
return this; return this;
} }

View File

@ -22,7 +22,7 @@ package ru.entaxy.esb.platform.base.management.core.utils;
import org.osgi.framework.ServiceRegistration; import org.osgi.framework.ServiceRegistration;
public class ManagedObjectDescriptor<S, I, C extends I> { public class ManagedObjectDescriptor<S, I, C extends I> {
S object; public S object;
C service; public C service;
ServiceRegistration<I> registration; public ServiceRegistration<I> registration;
} }

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,56 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>objects-base</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.base.objects-base</groupId>
<artifactId>object-factory</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: BASE :: OBJECT FACTORING :: OBJECT FACTORY</name>
<description>ENTAXY :: PLATFORM :: BASE :: OBJECT FACTORING :: OBJECT FACTORY</description>
<properties>
<bundle.osgi.export.pkg>
ru.entaxy.platform.base.objects.factory,
ru.entaxy.platform.base.objects.factory.configuration,
ru.entaxy.platform.base.objects.factory.impl,
ru.entaxy.platform.base.objects.factory.tracker
</bundle.osgi.export.pkg>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>base-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.base.connecting.generator
</groupId>
<artifactId>generator-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.base.connecting.generator
</groupId>
<artifactId>generator-factory</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,207 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.gson.JsonObject;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
public interface EntaxyFactory extends EntaxyFactoryElements.EntaxyFactoryExtendedElement {
/*
* public constants, enums etc
*/
public static interface SERVICE {
String PROP_ID = "factory.id";
String PROP_TYPE = "factory.type";
String PROP_ORIGIN_BUNDLE = "factory.origin.bundle";
}
public static interface CONFIGURATION {
String FACTORY_SECTION_NAME = "factory";
String FIELDS_SECTION_NAME = "fields";
String OUTPUTS_SECTION_NAME = "outputs";
public static interface FACTORY {
String ID = "id";
String TYPE = "type";
String DESCRIPTION = "description";
String LABEL = "label";
String CATEGORY = "category";
}
public static interface FIELDS {
public static interface REGULAR_TYPES {
String STRING = "String";
String BOOLEAN = "Boolean";
String LONG = "Long";
String DOUBLE = "Double";
public static Set<String> asSet() {
return new HashSet<>() {{
add(STRING);
add(BOOLEAN);
add(DOUBLE);
add(LONG);
}};
}
}
public static interface ATTRIBUTES {
String FIELD_TYPE = "type";
String DEFAULT_VALUE = "defaultValue";
String REQUIRED = "required";
String IMMUTABLE = "immutable";
String IS_REF = "isRef";
}
String OBJECT_ID = "objectId";
}
public static interface OUTPUTS {
String OUTPUT_TYPE_INIT = "init";
String OUTPUT_TYPE_REF = "ref";
public static interface ATTRIBUTES {
String IS_DEFAULT = "isDefault";
String CONFIG = "config";
String GENERATOR = "generator";
String FIELDS = "fields";
String SCOPES = "scopes";
}
}
}
static public enum SCOPE {
PUBLIC("public"),
PROTECTED("protected"),
PRIVATE("private");
public String label;
private SCOPE(String label) {
this.label = label;
}
public static SCOPE valueOfLabel(String label) {
for (SCOPE e : values()) {
if (e.label.equals(label)) {
return e;
}
}
return null;
}
}
static public SCOPE DEFAULT_SCOPE = SCOPE.PUBLIC;
/*
* inner structure elements
*/
public static interface OutputInfo {
public String getType();
public String getGenerator();
public List<String> getScopes();
public Map<String, Object> getConfig();
public List<FieldInfo> getFields();
public boolean isDefault();
}
public static interface FieldInfo {
public String getName();
public String getType();
public String getDisplayName();
public String getDescription();
public boolean isImmutable();
public boolean isRequired();
public Object getDefaultValue();
public boolean isConditional();
public String getCondition();
public boolean isRef();
public JsonObject getJsonOrigin();
}
public static interface RefFieldInfo extends FieldInfo {
public boolean isBackRef();
public boolean isRefByValueOnly();
public String getRefField();
}
/*
* Factory itself
*/
@Deprecated()
public default String getFactoryId() {
return getId();
};
@Deprecated
public default String getFactoryType() {
return getType();
};
public List<OutputInfo> getOutputs();
public OutputInfo getDefaultOutput();
public OutputInfo getOutputByType(String outputType);
public List<FieldInfo> getFields();
public List<FieldInfo> getFields(String outputType);
public Generated generate(Map<String, Object> parameters) throws EntaxyFactoryException ;
public Generated generate(String outputType, Map<String, Object> parameters) throws EntaxyFactoryException;
public Generated generate(String outputType, String scope, Map<String, Object> parameters) throws EntaxyFactoryException;
}

View File

@ -0,0 +1,49 @@
/*-
* ~~~~~~licensing~~~~~~
* object-factory
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory;
public interface EntaxyFactoryElements {
public interface EntaxyFactoryTypedElement {
String getType();
}
public interface EntaxyFactoryLabeledElement {
String getLabel();
}
public interface EntaxyFactoryCommonElement extends EntaxyFactoryTypedElement {
String getId();
String getDescription();
}
public interface EntaxyFactoryExtendedElement extends EntaxyFactoryCommonElement, EntaxyFactoryLabeledElement {
String getCategory();
}
}

View File

@ -0,0 +1,24 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory;
public class EntaxyFactoryException extends Exception {
}

View File

@ -0,0 +1,33 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
public abstract class AbstractElement<T> {
@SuppressWarnings("unchecked")
public T fromJson(JsonElement jsonElement) {
Gson gson = new Gson();
return (T)gson.fromJson(jsonElement, this.getClass());
};
}

View File

@ -0,0 +1,65 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public class FactoryElement extends AbstractElement<FactoryElement> {
public static final String ELEMENT_NAME = EntaxyFactory.CONFIGURATION.FACTORY_SECTION_NAME;
protected String id;
protected String type;
protected String description;
protected String label;
protected String category;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}

View File

@ -0,0 +1,168 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.JSONUtils;
public class FieldElement implements EntaxyFactory.FieldInfo {
JsonObject jsonOrigin = null;
String name;
String type;
String displayName;
String description = "";
boolean immutable = false;
boolean required = false;
Object defaultValue = "";
boolean conditional = false;
String condition = null;
boolean isRef = false;
public static FieldElement merge(FieldElement...elements) {
JsonObject result = new JsonObject();
for (int i=0; i<elements.length; i++) {
JsonElement jsonElement = elements[i].jsonOrigin;
if (jsonElement == null)
continue;
if (!jsonElement.isJsonObject())
continue;
JsonObject jsonObject = jsonElement.getAsJsonObject();
JSONUtils.mergeObjects(jsonObject, result);
}
FieldElement fe = (new Gson()).fromJson(result, FieldElement.class);
fe.setJsonOrigin(result.deepCopy());
return fe;
}
/* EntaxyFactory.FieldInfo implementation */
@Override
public String getName() {
return name;
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public String getDescription() {
return description;
}
@Override
public String getType() {
return type;
}
@Override
public Object getDefaultValue() {
return defaultValue;
}
@Override
public boolean isRequired() {
return required;
}
@Override
public boolean isImmutable() {
return immutable;
}
@Override
public JsonObject getJsonOrigin() {
return jsonOrigin;
}
@Override
public boolean isConditional() {
return conditional;
}
@Override
public String getCondition() {
return condition;
}
@Override
public boolean isRef() {
return isRef;
}
/* other */
public void setName(String name) {
this.name = name;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public void setDescription(String description) {
this.description = description;
}
public void setType(String type) {
this.type = type;
}
public void setDefaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
}
public void setRequired(boolean isRequired) {
this.required = isRequired;
}
public void setImmutable(boolean isImmuable) {
this.immutable = isImmuable;
}
public void setJsonOrigin(JsonObject jsonOrigin) {
this.jsonOrigin = jsonOrigin;
}
public void setConditional(boolean conditional) {
this.conditional = conditional;
}
public void setCondition(String condition) {
this.condition = condition;
}
public void setRef(boolean isRef) {
this.isRef = isRef;
}
}

View File

@ -0,0 +1,89 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.CONFIGURATION.FIELDS;
public class FieldsElement extends AbstractElement<FieldsElement> {
private static final Logger log = LoggerFactory.getLogger(FieldsElement.class);
public static final String ELEMENT_NAME = EntaxyFactory.CONFIGURATION.FIELDS_SECTION_NAME;
protected Map<String, FieldElement> fields = new HashMap<>();
@Override
public FieldsElement fromJson(JsonElement jsonElement) {
Gson gson = new Gson();
if (jsonElement.isJsonObject()) {
for (Entry<String, JsonElement> entry : jsonElement.getAsJsonObject().entrySet()) {
Class<? extends FieldElement> feClass = FieldElement.class;
if (entry.getValue().isJsonObject())
if (entry.getValue().getAsJsonObject().has(FIELDS.ATTRIBUTES.IS_REF)) {
JsonElement val = entry.getValue().getAsJsonObject().get(FIELDS.ATTRIBUTES.IS_REF);
if (val.isJsonPrimitive() && val.getAsJsonPrimitive().isBoolean())
if (val.getAsJsonPrimitive().getAsBoolean()) {
feClass = RefFieldElement.class;
}
}
FieldElement fe = gson.fromJson(entry.getValue(), feClass);
fe.setName(entry.getKey());
fe.setJsonOrigin(entry.getValue().isJsonObject()?entry.getValue().getAsJsonObject():new JsonObject());
addField(fe);
}
}
/*
* this.fields = gson.fromJson( jsonElement,
* TypeToken.getParameterized(ArrayList.class, FieldElement.class).getType() );
*/
// processOutputs();
return this;
}
protected void addField(FieldElement fieldElement) {
this.fields.put(fieldElement.getName(), fieldElement);
}
public Map<String, FieldElement> getFieldsMap(){
return this.fields;
}
public List<FieldElement> getFields() {
return new ArrayList<>(fields.values());
}
}

View File

@ -0,0 +1,231 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.factory.GeneratorFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.FieldInfo;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.SCOPE;
public class OutputElement implements EntaxyFactory.OutputInfo {
private static final Logger log = LoggerFactory.getLogger(OutputElement.class);
protected String type;
protected String generator = GeneratorFactory.DEFAULT_GENERATOR;
protected boolean isDefault = false;
protected List<String> scopes = Arrays.asList(new String[] {EntaxyFactory.SCOPE.PUBLIC.name()});
protected Set<SCOPE> supportedScopes = new HashSet<>( Arrays.asList(new SCOPE[] {EntaxyFactory.SCOPE.PUBLIC}) );
protected Map<String, Object> config = new HashMap<>();
protected JsonObject origin;
protected FieldsElement fields = null;
protected Map<String, FieldElement> commonFields = new HashMap<>();
protected Map<String, FieldElement> effectiveFields = new HashMap<>();
protected boolean isEffectiveCalculated = false;
public static OutputElement fromJson(JsonObject jsonObject) {
Gson gson = new Gson();
OutputElement result = gson.fromJson(jsonObject, OutputElement.class);
result.setOrigin(jsonObject);
result.updateFromOrigin();
return result;
}
public static OutputElement fromJson(String type, JsonObject jsonObject) {
OutputElement result = OutputElement.fromJson(jsonObject);
result.setType(type);
return result;
}
public OutputElement() {
super();
}
public void updateFromOrigin() {
if (origin.has(EntaxyFactory.CONFIGURATION.OUTPUTS.ATTRIBUTES.FIELDS)) {
JsonElement fieldsElement = origin.get(EntaxyFactory.CONFIGURATION.OUTPUTS.ATTRIBUTES.FIELDS);
this.fields = (new FieldsElement()).fromJson(fieldsElement);
}
if (origin.has(EntaxyFactory.CONFIGURATION.OUTPUTS.ATTRIBUTES.SCOPES)) {
JsonElement scopesElement = origin.get(EntaxyFactory.CONFIGURATION.OUTPUTS.ATTRIBUTES.SCOPES);
if (scopesElement.isJsonArray()) {
JsonArray ja = scopesElement.getAsJsonArray();
List<String> scopes = new ArrayList<>();
for (int i=0; i<ja.size(); i++)
scopes.add(ja.get(i).getAsString());
setScopes(scopes);
}
}
}
protected void calculateEffective() {
this.effectiveFields.clear();
log.debug("-> " + getType() + " calculateEffective :: " + this.commonFields.size());
Map<String, FieldElement> ownedFields;
if (fields == null) {
// get all common fields
log.debug("-> " + getType() + " taking all common fields");
ownedFields = Collections.emptyMap();
if (commonFields != null)
for (Entry<String, FieldElement> entry: commonFields.entrySet()) {
this.effectiveFields.put(entry.getKey(), entry.getValue());
}
} else {
// use only locally mentioned fields
ownedFields = fields.getFieldsMap();
log.debug("->" + getType() + " ownedFields: " + fields.getFieldsMap().size());
if (commonFields != null)
for (Entry<String, FieldElement> entry: commonFields.entrySet()) {
if (ownedFields.containsKey(entry.getKey())) {
FieldElement fe = FieldElement.merge(entry.getValue(), ownedFields.get(entry.getKey()));
fe.setName(entry.getKey());
this.effectiveFields.put(entry.getKey(), fe);
}
}
}
for (Entry<String, FieldElement> entry: ownedFields.entrySet())
if (!this.effectiveFields.containsKey(entry.getKey()))
this.effectiveFields.put(entry.getKey(), entry.getValue());
this.isEffectiveCalculated = true;
}
@Override
public String getType() {
return type;
}
@Override
public String getGenerator() {
return generator;
}
@Override
public List<String> getScopes() {
return this.supportedScopes.stream().map(s -> s.label).collect(Collectors.toList());
}
@Override
public Map<String, Object> getConfig() {
return config;
}
@Override
public List<FieldInfo> getFields() {
if (!this.isEffectiveCalculated)
calculateEffective();
return this.effectiveFields.values().stream().map(f->(FieldInfo)f).collect(Collectors.toList());
}
@Override
public boolean isDefault() {
return isDefault;
}
public void setType(String type) {
this.type = type;
}
public void setGenerator(String generator) {
this.generator = generator;
}
public void setScopes(String[] scopes) {
log.debug("\n\tsetScopes(String[] scopes)");
if (scopes == null) {
setScopes(Collections.<String>emptyList());
} else {
setScopes(Arrays.asList(scopes));
}
}
public void setScopes(List<String> scopes) {
log.debug("\n\tsetScopes(List<String> scopes)");
this.scopes.clear();
this.supportedScopes.clear();
for (String s: scopes) {
this.scopes.add(s.toLowerCase());
this.supportedScopes.add(SCOPE.valueOfLabel(s));
}
}
public Set<SCOPE> getSupportedScopes() {
return supportedScopes;
}
public boolean isScopeSupported(String scope) {
return isScopeSupported(SCOPE.valueOfLabel(scope));
}
public boolean isScopeSupported(SCOPE scope) {
return supportedScopes.contains(scope);
}
public void setDefault(boolean isDefault) {
this.isDefault = isDefault;
}
public void setConfig(Map<String, Object> config) {
this.config = config;
}
public JsonObject getOrigin() {
return origin;
}
public void setOrigin(JsonObject origin) {
this.origin = origin;
}
public void setCommonFields(Map<String, FieldElement> commonFields) {
this.commonFields = commonFields;
this.isEffectiveCalculated = false;
}
}

View File

@ -0,0 +1,111 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.CommonUtils;
public class OutputsElement extends AbstractElement<OutputsElement> {
public static final String ELEMENT_NAME = EntaxyFactory.CONFIGURATION.OUTPUTS_SECTION_NAME;
public static final String DEFAULT_OUTPUT_TYPE = "init";
// protected List<OutputElement> outputs = new ArrayList<>();
protected Map<String, OutputElement> outputsMap = new HashMap<>();
protected Map<String, FieldElement> commonFields = new HashMap<>();
protected String defaultOutputType = "";
@Override
public OutputsElement fromJson(JsonElement jsonElement) {
Gson gson = new Gson();
/*
* this.outputs = gson.fromJson( jsonElement,
* TypeToken.getParameterized(ArrayList.class, OutputElement.class).getType() );
* processOutputs();
*/
if (jsonElement.isJsonObject()) {
for (Entry<String, JsonElement> entry: jsonElement.getAsJsonObject().entrySet()) {
OutputElement oe = gson.fromJson(entry.getValue(), OutputElement.class);
oe.setType(entry.getKey());
oe.setCommonFields(commonFields);
if (entry.getValue().isJsonObject())
oe.setOrigin(entry.getValue().getAsJsonObject());
oe.updateFromOrigin();
if (oe.isDefault)
this.defaultOutputType = oe.getType();
addOutput(oe);
}
}
if (!CommonUtils.isValid(defaultOutputType))
if (outputsMap.containsKey(DEFAULT_OUTPUT_TYPE)) {
this.defaultOutputType = DEFAULT_OUTPUT_TYPE;
this.outputsMap.get(DEFAULT_OUTPUT_TYPE).setDefault(true);
}
return this;
}
protected void addOutput(OutputElement oe) {
this.outputsMap.put(oe.getType(), oe);
}
public List<OutputElement> getOutputs() {
return new ArrayList<>(outputsMap.values());
}
public String getDefaultOutputType() {
return defaultOutputType;
}
public void setDefaultOutputType(String defaultOutputType) {
this.defaultOutputType = defaultOutputType;
}
public boolean hasOutput(String type) {
return this.outputsMap.containsKey(type);
}
public OutputElement getOutput(String type) {
return this.outputsMap.get(type);
}
public void setCommonFields(Map<String, FieldElement> commonFields) {
this.commonFields = commonFields;
for (OutputElement oe: outputsMap.values())
oe.setCommonFields(commonFields);
}
}

View File

@ -0,0 +1,64 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.configuration;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.CONFIGURATION.FIELDS;
public class RefFieldElement extends FieldElement implements EntaxyFactory.RefFieldInfo {
protected boolean isBackRef = false;
protected boolean isRefByValueOnly = false;
protected String refField = FIELDS.OBJECT_ID;
/* EntaxyFactory.RefFieldInfo */
@Override
public boolean isBackRef() {
return isBackRef;
}
@Override
public boolean isRefByValueOnly() {
return isRefByValueOnly;
}
@Override
public String getRefField() {
return refField;
}
/* others */
public void setBackRef(boolean isBackRef) {
this.isBackRef = isBackRef;
}
public void setRefByValueOnly(boolean isRefByValueOnly) {
this.isRefByValueOnly = isRefByValueOnly;
}
public void setRefField(String refField) {
this.refField = refField;
}
}

View File

@ -0,0 +1,257 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.impl;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.base.objects.factory.configuration.AbstractElement;
import ru.entaxy.platform.base.objects.factory.configuration.FactoryElement;
import ru.entaxy.platform.base.objects.factory.configuration.FieldsElement;
import ru.entaxy.platform.base.objects.factory.configuration.OutputElement;
import ru.entaxy.platform.base.objects.factory.configuration.OutputsElement;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.base.support.osgi.OSGIUtils;
public class DefaultFactory implements EntaxyFactory {
private static final Logger log = LoggerFactory.getLogger(DefaultFactory.class);
protected Map<String, Class<? extends AbstractElement<?>>> elementClasses = new HashMap<>();
protected String factoryId = "";
protected String factoryType = "";
protected String description;
protected String label;
protected String category;
protected FieldsElement fields = null;
protected OutputsElement outputs = new OutputsElement();
protected Map<String, Object> factoryData = new HashMap<>();
protected GenerationHelper helper = null;
public DefaultFactory() {
super();
elementClasses.put(FactoryElement.ELEMENT_NAME, FactoryElement.class);
elementClasses.put(OutputsElement.ELEMENT_NAME, OutputsElement.class);
elementClasses.put(FieldsElement.ELEMENT_NAME, FieldsElement.class);
}
protected GenerationHelper getHelper() {
if (this.helper == null) {
try {
helper = OSGIUtils.services().ofClass(GenerationHelper.class).waitService(5000).get();
} catch (Exception e) {
// TODO Auto-generated catch block
log.error("Error getting GenerationHelper", e);
}
}
return this.helper;
}
public void configure(String configuration) {
log.debug("CONFIGURE WITH: " + configuration);
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
JsonElement je = (new JsonParser()).parse(configuration);
JsonObject root = je.getAsJsonObject();
Set<Entry<String, JsonElement>> elementSet = root.entrySet();
for (Entry<String, JsonElement> entry: elementSet) {
String name = entry.getKey();
Object result = null;
if (elementClasses.containsKey(name)) {
log.debug("FOUND element class for [" + name + "] :: " + elementClasses.get(name));
try {
result = elementClasses.get(name).getConstructor().newInstance().fromJson(entry.getValue());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
log.error("Error deserializing [" + name + "]", e);
continue;
}
// gson.fromJson(entry.getValue(), elementClasses.get(name));
} else
result = JSONUtils.element2object(entry.getValue());
factoryData.put(name, result);
postprocess(name, result);
}
}
protected void postprocess(String name, Object object) {
if (object instanceof FactoryElement) {
FactoryElement fe = (FactoryElement)object;
log.debug("POSTPROCESS :: FactoryElement");
if (CommonUtils.isValid(fe.getId()))
this.factoryId = fe.getId();
this.factoryType = fe.getType();
this.category = fe.getCategory();
this.label = fe.getLabel();
this.description = fe.getDescription();
} else if (object instanceof OutputsElement) {
log.debug("POSTPROCESS :: OutputsElement");
this.outputs = (OutputsElement)object;
log.debug("POSTPROCESS :: Default output config size -> " +
this.outputs.getOutput(this.outputs.getDefaultOutputType()).getConfig().size()
);
if (this.fields != null) {
this.outputs.setCommonFields(this.fields.getFieldsMap());
log.debug("COMMON FIELDS :: " + this.fields.getFieldsMap().size());
} else {
log.debug("fields :: null");
}
} else if (object instanceof FieldsElement) {
log.debug("POSTPROCESS :: FieldsElement");
this.fields = (FieldsElement)object;
if (this.outputs != null) {
this.outputs.setCommonFields(this.fields.getFieldsMap());
log.debug("COMMON FIELDS :: " + this.fields.getFieldsMap().size());
} else {
log.debug("outputs :: null");
}
}
}
public boolean isValid() {
return CommonUtils.isValid(this.factoryId) && CommonUtils.isValid(this.factoryType);
}
@Override
public String getId() {
return this.factoryId;
}
public void setFactoryId(String factoryId) {
this.factoryId = factoryId;
}
@Override
public String getType() {
return this.factoryType;
}
@Override
public String getDescription() {
return description;
}
@Override
public String getLabel() {
return label;
}
@Override
public String getCategory() {
return category;
}
@Override
public Generated generate(Map<String, Object> parameters) throws EntaxyFactoryException {
return generate(this.outputs.getDefaultOutputType(), parameters);
}
@Override
public Generated generate(String outputType, Map<String, Object> parameters) throws EntaxyFactoryException {
if (!this.outputs.hasOutput(outputType))
throw new EntaxyFactoryException();
return this.generate(outputType, EntaxyFactory.SCOPE.PUBLIC.label, parameters);
}
@Override
public Generated generate(String outputType, String scope, Map<String, Object> parameters) throws EntaxyFactoryException {
log.debug("Generating for: output type [{}], scope [{}]", outputType, scope);
if (!this.outputs.hasOutput(outputType)) {
log.debug("Unknown output: {}", outputType);
throw new EntaxyFactoryException();
}
OutputElement oe = this.outputs.getOutput(outputType);
if (!oe.isScopeSupported(scope)) {
log.error("Scope not supported: {}; supported scopes: [{}]"
, scope
, oe.getSupportedScopes().stream().map(s -> s.label).collect(Collectors.joining(",")));
throw new EntaxyFactoryException();
}
if (this.getHelper() != null)
try {
return this.getHelper().generateForFactory(this, outputType, SCOPE.valueOfLabel(scope), parameters);
} catch (Exception e) {
log.error("Generate failed", e);
// TODO fill the exception
throw new EntaxyFactoryException();
}
return null;
}
@Override
public List<OutputInfo> getOutputs() {
return this.outputs.getOutputs().stream().map(el->(OutputInfo)el).collect(Collectors.toList());
}
@Override
public OutputInfo getOutputByType(String outputType) {
return this.outputs.getOutput(outputType);
}
@Override
public List<FieldInfo> getFields() {
return this.fields.getFields().stream().map(f -> (FieldInfo)f).collect(Collectors.toList());
}
@Override
public List<FieldInfo> getFields(String outputType) {
return this.outputs.getOutput(outputType).getFields();
}
@Override
public OutputInfo getDefaultOutput() {
return (OutputInfo)outputs.getOutput(outputs.getDefaultOutputType());
}
}

View File

@ -0,0 +1,126 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.impl;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.base.generator.template.Template;
import ru.entaxy.base.generator.template.TemplateService;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generator;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.factory.GeneratorFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.OutputInfo;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.SCOPE;
@Component(immediate = true, service = {GenerationHelper.class})
public class GenerationHelper {
private static final Logger log = LoggerFactory.getLogger(GenerationHelper.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY, collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
protected volatile TemplateService templateService;
public Generated generateForFactory(EntaxyFactory factory, String outputType, SCOPE scope, Map<String, Object> parameters) throws Exception {
log.debug("GENERATING for factory [" + factory.getFactoryId() + "]");
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: PARAMETERS \n"
+ parameters.entrySet().stream().map(e -> e.getKey() + ":" + (null==e.getValue()?"null":e.getValue()))
.collect(Collectors.toList())
.stream().collect(Collectors.joining(", "))
);
OutputInfo outputInfo = factory.getOutputByType(outputType);
if (outputInfo == null) {
// @TODO throw Exception
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: output [{}] not found", outputType);
return null;
}
if (!outputInfo.getScopes().contains(scope.label)) {
// @TODO throw Exception
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: scope [{}] not supported", scope.label);
return null;
}
// try to generate via GeneratorFactory
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: TRY via GeneratorFactory");
Generator g = GeneratorFactory.createGenerator(outputInfo.getGenerator(), outputInfo.getConfig());
if (g.isGeneratable(parameters)) {
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: generating");
return g.generate(parameters);
} else {
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: NOT generatable");
}
// try to generate via TemplateService
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: TRY via TemplateService");
List<String> candidates = new LinkedList<>();
candidates.add(factory.getFactoryId() + "." + outputType + "." + scope.label);
candidates.add(factory.getFactoryId() + "." + outputType);
if (outputInfo.isDefault()) {
candidates.add(factory.getFactoryId() + ".default." + scope.label);
candidates.add(factory.getFactoryId() + ".default");
candidates.add(factory.getFactoryId() + "." + scope.label);
candidates.add(factory.getFactoryId());
}
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: CANDIDATES : ["
+ candidates.stream().collect(Collectors.joining(";"))
+ "]"
);
for (String candidate: candidates) {
Template t = templateService.getTemplateById(candidate);
if (t != null) {
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: FOUND TEMPLATE : ["
+ candidate + "]");
Generated result = GeneratorFactory.createGenerator(t).generate(t, parameters);
return result;
} else {
log.debug("GENERATING for factory [" + factory.getFactoryId() + "] :: NOT FOUND TEMPLATE : ["
+ candidate + "]");
}
}
return null;
}
public TemplateService getTemplateService() {
return templateService;
}
public void setTemplateService(TemplateService templateService) {
this.templateService = templateService;
}
}

View File

@ -0,0 +1,84 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.tracker;
import java.util.HashMap;
import java.util.Map;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public class TrackedFactory {
private static final Logger log = LoggerFactory.getLogger(TrackedFactory.class);
public static Map<String, TrackedFactory> trackedFactoriesMap = new HashMap<>();
private String id;
private Bundle bundle;
private String configString;
private ServiceRegistration<EntaxyFactory> serviceRegistration;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Bundle getBundle() {
return bundle;
}
public void setBundle(Bundle bundle) {
this.bundle = bundle;
}
public String getConfigString() {
return configString;
}
public void setConfigString(String configString) {
this.configString = configString;
}
public ServiceRegistration<EntaxyFactory> getServiceRegistration() {
return serviceRegistration;
}
public void setServiceRegistration(ServiceRegistration<EntaxyFactory> serviceRegistration) {
this.serviceRegistration = serviceRegistration;
}
public void unregister() {
if (this.serviceRegistration != null)
try {
this.serviceRegistration.unregister();
} catch (Exception e) {
log.warn("TrackedFactory [" + getId() + "]", e);
}
}
}

View File

@ -0,0 +1,83 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.tracker;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.osgi.tracker.UniformBundleTrackerCustomizer;
public class TrackedFactoryCustomizer extends UniformBundleTrackerCustomizer<List<TrackedFactory>> {
private static final Logger log = LoggerFactory.getLogger(TrackedFactoryCustomizer.class);
private static final String FACTORY_ROOT_PATH = "/ru/entaxy/factory/";
@Override
protected List<TrackedFactory> createManagedObject(Bundle bundle, BundleEvent event,
Map<String, List<?>> filterResults) {
List<TrackedFactory> result = new ArrayList<>();
Enumeration<URL> entries = bundle.findEntries(FACTORY_ROOT_PATH, "*.json", false);
while (entries.hasMoreElements()) {
URL entry = entries.nextElement();
String urlString = entry.toString();
log.debug("Found path: " + urlString);
if (urlString.endsWith("/"))
continue;
String id = urlString.substring(urlString.lastIndexOf("/") + 1);
id = id.substring(0, id.lastIndexOf("."));
log.debug("Found id: " + id);
try {
String config = new BufferedReader (
new InputStreamReader(
entry.openStream(), StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
TrackedFactory tf = new TrackedFactory();
tf.setId(id);
tf.setBundle(bundle);
tf.setConfigString(config);
result.add(tf);
} catch (Exception e) {
log.error("Error reading url: " + urlString, e);
}
}
return result;
}
}

View File

@ -0,0 +1,102 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.tracker;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.base.generator.template.TemplateService;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.impl.DefaultFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.osgi.tracker.BundleTrackerCustomizerListener;
public class TrackedFactoryCustomizerListener implements BundleTrackerCustomizerListener<List<TrackedFactory>> {
private static final Logger log = LoggerFactory.getLogger(TrackedFactoryCustomizerListener.class);
protected BundleContext bundleContext;
public TrackedFactoryCustomizerListener(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
public void added(List<TrackedFactory> managedObject) {
if (managedObject == null) {
log.debug("managedObject is null");
return;
}
for (TrackedFactory tf: managedObject) {
log.debug("Added factory: " + tf.getId());
if (TrackedFactory.trackedFactoriesMap.containsKey(tf.getId())) {
TrackedFactory.trackedFactoriesMap.get(tf.getId()).unregister();
}
DefaultFactory defaultFactory = new DefaultFactory();
defaultFactory.setFactoryId(tf.getId());
defaultFactory.configure(tf.getConfigString());
if (defaultFactory.isValid()) {
tf.setId(defaultFactory.getFactoryId());
Dictionary<String, String> props = new Hashtable<String, String>();
props.put(EntaxyFactory.SERVICE.PROP_ID, defaultFactory.getFactoryId());
props.put(EntaxyFactory.SERVICE.PROP_TYPE, defaultFactory.getFactoryType());
props.put(EntaxyFactory.SERVICE.PROP_ORIGIN_BUNDLE, tf.getBundle().getBundleId()+"");
tf.setServiceRegistration(
this.bundleContext.registerService(EntaxyFactory.class, defaultFactory, props)
);
TrackedFactory.trackedFactoriesMap.put(tf.getId(), tf);
}
}
}
@Override
public void modified(List<TrackedFactory> managedObject) {
// TODO Auto-generated method stub
}
@Override
public void removed(List<TrackedFactory> managedObject) {
if (managedObject == null)
return;
for (TrackedFactory tf: managedObject) {
try {
tf.getServiceRegistration().unregister();
} catch (Exception e) {
// do nothing
}
TrackedFactory.trackedFactoriesMap.remove(tf.getId());
}
}
}

View File

@ -0,0 +1,69 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* 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.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.base.objects.factory.tracker;
import java.util.List;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.util.tracker.BundleTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.osgi.tracker.BundleTrackerUtils;
import ru.entaxy.platform.base.support.osgi.tracker.filter.BundleHeaderFilter;
@Component(service = {TrackerManager.class}, immediate = true)
public class TrackerManager {
private static final Logger log = LoggerFactory.getLogger(TrackerManager.class);
protected BundleContext bundleContext;
protected BundleTracker<List<TrackedFactory>> factoryTracker;
@Activate
public void activate(ComponentContext componentContext) {
this.bundleContext = componentContext.getBundleContext();
log.debug("Activated: " + bundleContext.getBundle().getBundleId());
factoryTracker = BundleTrackerUtils.<List<TrackedFactory>>createBuilder()
.addFilter(
(new BundleHeaderFilter()).header("Entaxy-Factory-Provider")
)
.customizer(
(new TrackedFactoryCustomizer())
.listener(new TrackedFactoryCustomizerListener(bundleContext))
)
.bundleState(Bundle.ACTIVE | Bundle.INSTALLED | Bundle.RESOLVED)
.get();
factoryTracker.open();
log.debug("Factory tracker started");
}
@Deactivate
public void deactivate(ComponentContext componentContext) {
factoryTracker.close();
}
}

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

Some files were not shown because too many files have changed in this diff Show More