release version 1.10.0

This commit is contained in:
2024-12-14 04:07:49 +03:00
parent a5088587f7
commit c6b3d793c4
1916 changed files with 254306 additions and 0 deletions

View File

@ -0,0 +1,84 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.audit;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.audit.data.AuditEvent;
import ru.entaxy.audit.data.Outcome;
import ru.entaxy.audit.data.Severity;
import ru.entaxy.audit.service.EventConverter;
import ru.entaxy.audit.service.EventConverterInfo;
import ru.entaxy.audit.service.InterpretedEvent;
import ru.entaxy.audit.service.jmx.JMXInvokeEvent;
@Component(service = EventConverter.class, immediate = true)
@EventConverterInfo(classes = {JMXInvokeEvent.class})
public class ObjectProducerEventConverter implements EventConverter {
private static final Logger LOG = LoggerFactory.getLogger(ObjectProducerEventConverter.class);
@Override
public <T extends InterpretedEvent> AuditEvent convert(T event) {
if (!JMXInvokeEvent.class.equals(event.getClass()))
return null;
JMXInvokeEvent invokeEvent = (JMXInvokeEvent) event;
Filter filter;
try {
filter = FrameworkUtil
.createFilter(
"(&(jmx.domain=ru.entaxy.esb)(jmx.methodName=createObjectByInstructions)(jmx.property.factoryId=*))");
} catch (InvalidSyntaxException e) {
LOG.error("Error creating filter", e);
return null;
}
if (!filter.matches(event.getEventEssense())) {
if (LOG.isDebugEnabled())
LOG.debug("Event not matches: {}", event.toString());
return null;
}
String objectId = invokeEvent.getMethodParams()[0].toString();
String factoryId = event.getEventEssense().getOrDefault("jmx.property.factoryId", "unknown").toString();
AuditEvent result = AuditEvent.AuditLoggingEventBuilder.getInstance()
.target("ENTAXY OBJECTS")
.outcome(Outcome.SUCCESS)
.message(String.format("Object %s of factory %s was changed", objectId, factoryId))
.severity(Severity.INFO)
.category(String.format("%s:%s", objectId, factoryId))
.build();
return result;
}
}

View File

@ -0,0 +1,174 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
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;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObject;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
public class GeneratedObjectsPublishDataStorage {
Map<String, JsonObject> publishData = new HashMap<>();
public JsonObject getPublishData(String objectUuid) {
return publishData.getOrDefault(objectUuid, new JsonObject());
}
public JsonObject generatePublishData(FactoredObject factoredObject, EntaxyFactory factory, String outputType) {
JsonObject result = new JsonObject();
JsonObject originObject = factoredObject.origin;
result = getFilteredObject(originObject, originObject, factory, outputType);
publishData.put(factoredObject.getUuid(), result);
return getPublishData(factoredObject.getUuid());
}
protected JsonObject getFilteredObject(JsonObject originObject, JsonObject rootObject, EntaxyFactory factory,
String outputType) {
JsonObject result = new JsonObject();
Map<String, JsonObject> factoryFields = factory.getOutputByType(outputType).getFields().stream()
.collect(Collectors.toMap(fi -> fi.getName(), fi -> fi.getJsonOrigin()));
for (Entry<String, JsonElement> entry : originObject.entrySet()) {
String name = entry.getKey();
if (FactoredObject.EMBEDDED_FIELD.equals(name) || FactoredObject.IGNORE_SECTION.equals(name)
|| (name.startsWith("##") && !name.startsWith("##config")))
continue;
boolean skip = false;
// check @INTERNAL directive via factory data
JsonObject joField = factoryFields.getOrDefault(name, new JsonObject());
if (joField.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL)) {
try {
skip = joField.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL).getAsBoolean();
} catch (Exception ignore) {
// NOOP
}
}
if (skip)
continue;
// check @INTERNAL directive via object data
JsonElement je = entry.getValue();
if (je.isJsonObject()) {
JsonObject jo = je.getAsJsonObject();
if (jo.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL)) {
try {
skip = jo.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL).getAsBoolean();
} catch (Exception e) {
// NOOP
}
if (skip)
continue;
}
}
// check for @PUBLISH_UNRESOLVED directive
if (joField.has(GenerationModel.DIRECTIVE_PUBLISH_URESOLVED)) {
JsonElement publishUnresolved = joField.get(GenerationModel.DIRECTIVE_PUBLISH_URESOLVED);
String publishUnresolvedValue = publishUnresolved.getAsString();
boolean publishRef = publishUnresolvedValue.equalsIgnoreCase(GenerationModel.PUBLISH_UNRESOLVED_REF);
boolean publishObject =
publishUnresolvedValue.equalsIgnoreCase(GenerationModel.PUBLISH_UNRESOLVED_OBJECT);
if (publishRef || publishObject) {
JsonObject unresolvedRef = null;
// first we must get unresolved ref
if (je.isJsonObject()) {
if (FactoredObjectRef.isRef(je.getAsJsonObject())) {
// ref is found
unresolvedRef = je.getAsJsonObject();
}
}
if (unresolvedRef == null) {
JsonElement unresolved = JSONUtils.findElementExt(rootObject,
String.format("%s.properties.%s", GenerationModel.UNRESOLVED_CONTAINER_NAME, name));
if (unresolved != null && unresolved.isJsonObject())
unresolvedRef = unresolved.getAsJsonObject();
}
if (unresolvedRef != null) {
if (publishRef) {
result.add(name, unresolvedRef);
continue;
} else {
// get target object
JsonElement uuid = unresolvedRef.get(FactoredObjectRef.TARGET_UUID_FIELD);
if (uuid.isJsonPrimitive()) {
String objectUuid = uuid.getAsString();
if (publishData.containsKey(objectUuid)) {
JsonObject toPublish = publishData.get(objectUuid);
// we nust remove 'isEmbedded'
toPublish.remove(FactoredObject.IS_EMBEDDED_FIELD);
result.add(name, toPublish);
continue;
}
}
}
}
}
}
if (je.isJsonObject()) {
JsonObject filtered = getFilteredObject(je.getAsJsonObject(), rootObject, factory, outputType);
if (filtered != null)
result.add(name, filtered);
} else {
result.add(name, je);
}
}
return result;
}
}

View File

@ -0,0 +1,186 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
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 com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionsAware;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper;
import ru.entaxy.platform.core.producer.wrapper.DefaultFactoryWrapper;
@Component(service = {EntaxyProducer.class}, immediate = true, name = "UniformExtendableProducer")
public class UniformExtendableProducer extends CommonObjectProducer implements EntaxyExtensionsAware {
private static final Logger log = LoggerFactory.getLogger(UniformExtendableProducer.class);
public static final String PRODUCER_EXTENSION_ATTR_SUPPORTED_TYPES = "supportedTypes";
public static final String PRODUCER_EXTENSION_PATH = "producer";
public static final String PRODUCER_EXTENSION_NAME = "config.json";
public static final String PRODUCER_EXTENSION_KEY = PRODUCER_EXTENSION_PATH + "/" + PRODUCER_EXTENSION_NAME;
protected Map<EntaxyExtension, List<String>> extensionsToSupportedTypesMap = new HashMap<>();
protected Object extensionsLock = new Object();
protected ComponentContext componentContext;
protected List<EntaxyFactory> availableFactories = new ArrayList<>();
protected Object factoriesLock = new Object();
@Activate
public void activate(ComponentContext componentContext) {
this.componentContext = componentContext;
}
@Override
public void addExtension(EntaxyExtension entaxyExtension) {
if (!entaxyExtension.getResources().containsKey(PRODUCER_EXTENSION_KEY))
return;
synchronized (extensionsLock) {
try {
JsonObject config =
JSONUtils.getJsonRootObject(entaxyExtension.getResources().get(PRODUCER_EXTENSION_KEY));
if (!config.has(PRODUCER_EXTENSION_ATTR_SUPPORTED_TYPES))
return;
JsonArray ja = config.get(PRODUCER_EXTENSION_ATTR_SUPPORTED_TYPES).getAsJsonArray();
if (ja.size() == 0)
return;
final List<String> list = new ArrayList<>();
for (int i = 0; i < ja.size(); i++) {
JsonElement je = ja.get(i);
if (!je.isJsonPrimitive())
continue;
if (!je.getAsJsonPrimitive().isString())
continue;
list.add(je.getAsJsonPrimitive().getAsString());
}
if (!list.isEmpty())
this.extensionsToSupportedTypesMap.put(entaxyExtension, list);
calculateSupportedTypes();
rescanAvailables();
} catch (IOException e) {
log.error(
"Error reading resource: [" + entaxyExtension.getResources().get(PRODUCER_EXTENSION_KEY) + "]",
e);
}
}
}
@Override
public void removeExtension(EntaxyExtension entaxyExtension) {
if (extensionsToSupportedTypesMap.containsKey(entaxyExtension)) {
synchronized (extensionsLock) {
extensionsToSupportedTypesMap.remove(entaxyExtension);
calculateSupportedTypes();
rescanExisting();
}
}
}
protected void rescanAvailables() {
synchronized (factoriesLock) {
for (EntaxyFactory factory : availableFactories)
if (!factories.containsKey(factory))
addFactory(factory);
}
}
protected void rescanExisting() {
synchronized (factoriesLock) {
List<EntaxyFactory> existing = new ArrayList<>(factories.values());
for (EntaxyFactory factory : existing)
if (!isTypeSupported(factory.getType()))
super.removeFactory(factory);
}
}
protected void calculateSupportedTypes() {
final List<String> typesList = new ArrayList<>();
supportedTypes.clear();
supportedTypesPatterns.clear();
extensionsToSupportedTypesMap.values().stream()
.forEach(list -> typesList.addAll(list));
setSupportedTypes(typesList);
}
@Reference(bind = "addFactory", unbind = "removeFactory", cardinality = ReferenceCardinality.MULTIPLE,
collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
public void addFactory(EntaxyFactory factory) {
synchronized (factoriesLock) {
if (!availableFactories.contains(factory))
availableFactories.add(factory);
}
doAddFactory(factory);
}
// WE MUST DECLARE IT for @Reference annotation processor
@Override
public void removeFactory(EntaxyFactory factory) {
synchronized (factoriesLock) {
availableFactories.remove(factory);
}
super.removeFactory(factory);
}
@Override
protected AbstractFactoryWrapper doAddFactory(EntaxyFactory factory) {
AbstractFactoryWrapper wrapper = super.doAddFactory(factory, DefaultFactoryWrapper.class);
if (wrapper != null)
wrapper.setGenerationProcessor(this);
return wrapper;
}
}

View File

@ -0,0 +1,290 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.OutputInfo;
import ru.entaxy.platform.base.objects.factory.exceptions.FactoryNotFoundException;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.config.runtime.ObjectConfigHelper;
import ru.entaxy.platform.config.runtime.ObjectConfig.FactoryOutputConfiguration;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.api.ProducingCommandExecutor;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObject;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectProxy;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
// @Component(service = ProducingCommandExecutor.class, immediate = true)
// @CommandExecutor(id = "add-config", predecessors = {"enrich"}, descendants = {"validate"})
public class AddConfigCommand2 extends AbstractCommandExecutor implements ProducingCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(AddConfigCommand2.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService entaxyProducerServiceLocal;
public AddConfigCommand2() {
super(null);
}
protected AddConfigCommand2(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Activate
public void activate(ComponentContext componentContext) {
this.entaxyProducerService = this.entaxyProducerServiceLocal;
this.entaxyProducerService.registerCommand(this);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
printOutput("\n\n\t== ADD-CONFIG == \n\n");
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
objectModel.startTracking();
JsonObject incomingJson = objectModel.getJsonCurrent().deepCopy();
for (FactoredObject fo : objectModel.objects) {
// skip proxies
if (fo instanceof FactoredObjectProxy)
continue;
log.debug("OBJECT :: {}/{}", fo.getObjectId(), fo.getObjectType());
String factoryId = fo.factoryId;
EntaxyFactory factory = entaxyProducerService.findFactoryById(factoryId);
if (factory == null)
throw new FactoryNotFoundException(factoryId);
String output = fo.getOutputType();
log.debug("OUTPUT :: {}", output);
OutputInfo oi = CommonUtils.isValid(output) ? factory.getOutputByType(output) : factory.getDefaultOutput();
Map<String, Object> config = oi.getConfig();
if ((config == null) || (config.isEmpty()))
continue;
String val = config.getOrDefault(ObjectConfig.CONFIGURABLE_ATTRIBUTE_NAME, "false").toString();
Boolean configurable = Boolean.valueOf(val);
if (!configurable)
continue;
JsonObject objectOrigin = fo.origin;
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
if (objectProperties.has(ObjectConfig.CONFIG_FIELD_NAME))
continue;
@SuppressWarnings("serial")
Generated g = this.entaxyProducerService.findFactoryById("common-config")
.generate("config-field", "private", new HashMap<String, Object>() {
{
put(FIELDS.FACTORY_ID, "common-config");
put(ObjectConfig.TARGET_FACTORY_FIELD_NAME, fo.factoryId);
put(ObjectConfig.TARGET_TYPE_FIELD_NAME, fo.getObjectType());
put(ObjectConfig.TARGET_ID_FIELD_NAME, fo.getObjectId());
put(ObjectConfig.TARGET_OUTPUT_FIELD_NAME, fo.getOutputType());
}
});
objectProperties.add(ObjectConfig.CONFIG_FIELD_NAME, JSONUtils.getJsonRootObject(g.getObject().toString()));
objectModel.setDirty();
}
for (FactoredObjectRef ref : objectModel.refs) {
// process external refs and replace ref to object with ref to config if
// - ref is not marked 'directValueOnly'
// - the referenced object has config
// - the referenced field is configurable
// if (!ref.isExternal())
// continue;
log.debug("REF :: " + ref.relativePath);
if (ObjectConfigHelper.getInstance().isDirectValueOnly(ref))
continue;
String objectId = ref.getTargetId();
String objectType = ref.getTargetType();
log.debug("TO :: " + objectId + ":" + objectType);
log.debug("DEFINED IN :: " + ref.definedIn.getObjectId());
String refField = ref.getOrDefault(FIELDS.REF_FIELD, FIELDS.OBJECT_ID).toString();
if (FIELDS.OBJECT_ID.equals(refField))
// objectId can't be configured
continue;
// skip if it's already config
if (ObjectConfig.CONFIG_OBJECT_TYPE.equals(objectType))
continue;
String configurationPid = ObjectConfig.getConfigurationPid(objectId, objectType);
String factoryId = null;
JsonElement newTargetId = null;
if (ref.isExternal()) {
EntaxyObject theObject = ObjectConfigHelper.getInstance().findObject(objectId, objectType);
if (theObject == null)
// referenced object not found
continue;
factoryId = theObject.getFactoryId();
EntaxyObject configObject = ObjectConfigHelper.getInstance()
.findObject(configurationPid, ObjectConfig.CONFIG_OBJECT_TYPE);
if (configObject == null)
// config for referenced object not found
continue;
newTargetId = new JsonPrimitive(configurationPid);
} else {
log.debug("EXTERNAL :: false");
Optional<FactoredObject> theObjectOpt = objectModel.objects.stream()
.filter(obj -> objectId.equals(obj.getObjectId())).findFirst();
if (!theObjectOpt.isPresent())
continue;
FactoredObject theObject = theObjectOpt.get();
log.debug("TARGET OBJECT :: found");
factoryId = theObject.factoryId;
Optional<FactoredObjectRef> configRefOpt = objectModel.refs.stream()
.filter(r -> r.definedIn.equals(theObject))
.filter(r -> r.relativePath.endsWith(ObjectConfig.CONFIG_FIELD_NAME))
.findFirst();
if (!configRefOpt.isPresent())
continue;
log.debug("REF TO CONFIG :: found; TARGET :: " + configRefOpt.get().getTargetId());
Optional<FactoredObject> configObjectOpt = objectModel.objects.stream()
.filter(obj -> obj.getObjectId().equals(configRefOpt.get().getTargetId()))
.findFirst();
if (!configObjectOpt.isPresent())
continue;
log.debug("CONFIG OBJECT :: found");
newTargetId = new JsonPrimitive(configObjectOpt.get().getObjectId());
}
EntaxyFactory entaxyFactory = entaxyProducerService.findFactoryById(factoryId);
if (entaxyFactory == null)
// factory for referenced object not found
continue;
FactoryOutputConfiguration conf = FactoryOutputConfiguration.read(entaxyFactory,
EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT);
if (!conf.isConfigurable)
continue;
if (!ObjectConfig.isConfigurable(entaxyFactory, EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT,
refField, conf.defaultFieldsConfigurable, conf.configurations))
// field is not configurable
continue;
JSONUtils.replaceValue(ref.origin, FIELDS.OBJECT_TYPE, new JsonPrimitive(ObjectConfig.CONFIG_OBJECT_TYPE));
JSONUtils.replaceValue(ref.origin, FactoredObjectRef.TARGET_TYPE_FIELD,
new JsonPrimitive(ObjectConfig.CONFIG_OBJECT_TYPE));
JSONUtils.replaceValue(ref.origin, FactoredObjectRef.TARGET_ID_FIELD, newTargetId);
// and we must generate ref to config to merge to main object
JSONUtils.replaceValue(ref.origin, FIELDS.IS_REF_BY_VALUE_ONLY, new JsonPrimitive(false));
objectModel.setDirty();
}
if (objectModel.stopTracking()) {
// remove ##embedded
for (FactoredObject fo : objectModel.objects)
fo.origin.remove(FactoredObject.EMBEDDED_FIELD);
commandResult.planUpdate = ExecutionPlanUpdate.create()
// .updateInstructions().target("enrich").value("skip", true).complete()
.reset().target("analyze").complete();
}
JsonObject outgoingJson = objectModel.getJsonCurrent();
printOutput("\n== INCOMING JSON ==\n");
printOutput(incomingJson.toString());
printOutput("\n== OUTGOING JSON ==\n");
printOutput(outgoingJson.toString());
commandResult.resultObject(outgoingJson);
return true;
}
}

View File

@ -0,0 +1,194 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.osgi.service.component.annotations.CollectionType;
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.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedHeaders;
import ru.entaxy.platform.core.producer.impl.CommonObjectProducer;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper;
// @Component(service = EntaxyProducer.class, immediate = true)
// @EntaxyProducerInfo (supportedTypes = {ObjectConfig.CONFIG_OBJECT_TYPE})
public class ConfigProducer2 extends CommonObjectProducer implements EntaxyProducer {
private static final Logger log = LoggerFactory.getLogger(ConfigProducer2.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService entaxyProducerService;
@Reference(bind = "addFactory", unbind = "removeFactory", cardinality = ReferenceCardinality.MULTIPLE,
collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
public void addFactory(EntaxyFactory factory) {
AbstractFactoryWrapper wrapper = super.doAddFactory(factory);
if (wrapper != null)
wrapper.setGenerationProcessor(this);
}
// WE MUST DECLARE IT for @Reference annotation processor
@Override
public void removeFactory(EntaxyFactory factory) {
super.removeFactory(factory);
}
@Override
public void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters) throws EntaxyFactoryException {
super.preGenerate(wrappedFactory, outputType, scope, objectType, parameters);
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>) parameters.get(EntaxyObject.FIELDS.PROPERTIES);
// System.out.println("\n\n\tCONFIG PRODUCER :: preGenerate");
// System.out.println("\t" + parameters.toString());
// properties can be null for 'config-field' output
if (properties != null) {
/* System.out.println("\n\n\tGENERATE CONFIG: "
+ "\noutput: " + outputType
+ "\nscope: " + scope
+ "\nproperties: " + properties.toString()); */
ObjectConfig.backupProperties(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
ObjectConfig.removeConfigData(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
Map<String, Object> configurables = new HashMap<>();
Map<String, Object> immutables = new HashMap<>();
String targetFactoryId = properties.get(ObjectConfig.CONFIG_FACTORY_FIELD_NAME).toString();
String targetOutput = properties.get(ObjectConfig.CONFIG_OUTPUT_FIELD_NAME).toString();
EntaxyFactory f = entaxyProducerService.findFactoryById(targetFactoryId);
if (!CommonUtils.isValid(targetOutput))
targetOutput = f.getDefaultOutput().getType();
fillConfigMaps(f, targetOutput, scope, objectType, parameters, configurables, immutables);
parameters.put(ObjectConfig.CONFIGURABLES_FIELD_NAME, configurables);
parameters.put(ObjectConfig.IMMUTABLES_FIELD_NAME, immutables);
String configuredId = parameters.get(ObjectConfig.CONFIG_ID_FIELD_NAME).toString();
String configuredType = parameters.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).toString();
String configurationPid = ObjectConfig.getConfigurationPid(configuredId, configuredType);
String placeholderPrefix = ObjectConfig.getConfigurationPrefix(configuredId, configuredType);
// set objectId to configurationPid
parameters.put(EntaxyObject.FIELDS.OBJECT_ID, configurationPid);
parameters.put(ObjectConfig.CONFIG_PID_FIELD_NAME, configurationPid);
parameters.put(ObjectConfig.CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME, placeholderPrefix);
}
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Generated generated) throws EntaxyFactoryException {
super.postGenerate(wrappedFactory, outputType, scope, objectType, parameters, generated);
ObjectConfig.restoreBackupProperties(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>) parameters.get(EntaxyObject.FIELDS.PROPERTIES);
// properties can be null for 'config-field' output
if (properties != null) {
// enrich paramaters with configured fields placeholders
String placeholderPrefix = parameters.get(ObjectConfig.CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME).toString();
@SuppressWarnings("unchecked")
Map<String, Object> configuredFields =
(Map<String, Object>) parameters.getOrDefault(ObjectConfig.CONFIGURABLES_FIELD_NAME,
Collections.emptyMap());
configuredFields.putAll(
(Map<String, Object>) parameters.getOrDefault(ObjectConfig.IMMUTABLES_FIELD_NAME,
Collections.emptyMap()));
log.debug("CONFIGURED: \n" + configuredFields);
Map<String, Object> placeholdersMap = configuredFields.entrySet().stream()
// .map(entry -> entry.setValue(placeholderPrefix + entry.getKey() + "}"))
.collect(Collectors.toMap(Map.Entry::getKey, entry -> placeholderPrefix + entry.getKey() + "}"));
log.debug("\n\n\tPLACEHOLDERS: \n" + placeholdersMap);
parameters.putAll(placeholdersMap);
// add headers
String configuredId = parameters.get(ObjectConfig.CONFIG_ID_FIELD_NAME).toString();
String configuredType = parameters.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).toString();
String configurationPid = ObjectConfig.getConfigurationPid(configuredId, configuredType);
GeneratedHeaders headers = GeneratedHeaders.getHeaders(generated.getProperties());
headers.set(ObjectConfig.HEADER_OBJECT_CONFIG_PID,
configuredId + ":" + configuredType + ":" + configurationPid);
}
}
protected void fillConfigMaps(EntaxyFactory factory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Map<String, Object> configurables, Map<String, Object> immutables) {
@SuppressWarnings("unchecked")
Map<String, Object> properties =
(Map<String, Object>) parameters.get(ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
for (Entry<String, Object> entry : properties.entrySet()) {
Map<String, Object> targetMap =
ObjectConfig.getTargetConfigMap(factory, outputType, entry.getKey(), configurables, immutables);
if (targetMap == null) {
continue;
}
targetMap.put(entry.getKey(), entry.getValue());
}
}
}

View File

@ -0,0 +1,114 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config.support;
import java.util.Map;
import org.apache.felix.utils.properties.TypedProperties;
import org.apache.karaf.config.core.ConfigRepository;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.annotations.Component;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.config.runtime.ObjectConfigHelper;
import ru.entaxy.platform.core.producer.executor.builder.BuiltObject;
import ru.entaxy.platform.core.producer.executor.builder.DefaultBuiltObject;
import ru.entaxy.platform.core.producer.executor.builder.ObjectBuilder;
import ru.entaxy.platform.core.producer.executor.deployer.DefaultDeployedObject;
import ru.entaxy.platform.core.producer.executor.deployer.DeployedObject;
import ru.entaxy.platform.core.producer.executor.deployer.ObjectDeployer;
import ru.entaxy.platform.core.producer.executor.installer.DefaultInstalledObject;
import ru.entaxy.platform.core.producer.executor.installer.InstalledObject;
import ru.entaxy.platform.core.producer.executor.installer.ObjectInstaller;
@Component(service = {ObjectBuilder.class, ObjectDeployer.class, ObjectInstaller.class})
public class ConfigObjectSupport implements ObjectBuilder, ObjectDeployer, ObjectInstaller {
private static final String CONFIG_TYPE_PREFIX = "config:";
@Override
public boolean isBuildable(Generated generated) {
return generated.getType().startsWith(CONFIG_TYPE_PREFIX);
}
@Override
public BuiltObject build(Generated generated, Map<String, Object> instructions) throws Exception {
return new DefaultBuiltObject(new DeployableConfig(
generated.getProperties().getOrDefault("configurationPid",
generated.getProperties().getOrDefault("objectId", "unknown")).toString(),
generated.getObject().toString()));
}
@Override
public boolean isDeployable(BuiltObject object) {
return object.getObject() instanceof DeployableConfig;
}
@Override
public DeployedObject deploy(BuiltObject object, Map<String, Object> instructions) throws Exception {
return new DefaultDeployedObject(object.getObject());
}
@Override
public boolean isInstallable(DeployedObject object) {
return object.getObject() instanceof DeployableConfig;
}
@Override
public InstalledObject install(DeployedObject object, Map<String, Object> instructions) throws Exception {
DeployableConfig deployableConfig = (DeployableConfig) object.getObject();
Map<String, Object> map = deployableConfig.properties;
ServiceReference<ConfigRepository> ref = ObjectConfigHelper.getInstance().getReference(ConfigRepository.class);
ServiceReference<ConfigurationAdmin> ref2 =
ObjectConfigHelper.getInstance().getReference(ConfigurationAdmin.class);
if (ref != null) {
ConfigurationAdmin configurationAdmin = ObjectConfigHelper.getInstance().getService(ref2);
// we need this to not bind config to felix bundle
configurationAdmin.getConfiguration(deployableConfig.configurationPid, "?");
ConfigRepository configRepository = ObjectConfigHelper.getInstance().getService(ref);
TypedProperties typedProperties = configRepository.getConfig(deployableConfig.configurationPid);
typedProperties.clear();
for (Map.Entry<String, Object> entry : map.entrySet())
typedProperties.put(entry.getKey(), entry.getValue());
configRepository.update(deployableConfig.configurationPid, typedProperties);
ObjectConfigHelper.getInstance().ungetService(ref);
ObjectConfigHelper.getInstance().ungetService(ref2);
}
return new DefaultInstalledObject(map);
}
}

View File

@ -0,0 +1,95 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config.support;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import org.jline.utils.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.config.runtime.ObjectConfig.ConfigHint;
public class DeployableConfig {
private static final Logger LOG = LoggerFactory.getLogger(DeployableConfig.class);
public String jsonData;
public Map<String, Object> properties;
public String configurationPid;
public DeployableConfig(String configurationPid, String jsonData) {
this.configurationPid = configurationPid;
this.jsonData = jsonData;
Map<String, Object> origin = JSONUtils.element2map(JSONUtils.getJsonRootObject(jsonData));
properties = new HashMap<>();
if (origin == null) {
return;
}
for (Map.Entry<String, Object> entry : origin.entrySet())
if (!entry.getKey().startsWith("#"))
properties.put(entry.getKey(), entry.getValue());
try {
generateHint();
} catch (Exception e) {
Log.error("Error generating condig hint", e);
}
}
protected void generateHint() throws Exception {
properties.remove(ObjectConfig.CONFIG_HINT_FIELD_NAME);
String factoryId = properties.getOrDefault(ObjectConfig.CONFIG_FACTORY_FIELD_NAME, "").toString();
String outputType = properties.getOrDefault(ObjectConfig.CONFIG_OUTPUT_FIELD_NAME, "").toString();
ConfigHint configHint = new ConfigHint();
configHint.generate(properties, factoryId, outputType);
String jsonHint = configHint.getAsJsonString();
if (CommonUtils.isValid(jsonHint)) {
properties.put(ObjectConfig.CONFIG_HINT_FIELD_NAME,
Base64.getEncoder().encodeToString(jsonHint.getBytes()));
}
}
}

View File

@ -0,0 +1,8 @@
{
"property-placeholder": {
"targetNodeName": "##root",
"position": "inside_first",
"unique": ["persistent-id"],
"conflict": "ignore" /*[ignore, replace]*/
}
}

View File

@ -0,0 +1,103 @@
{
"factory": {
"id": "object-config",
"type": "entaxy.runtime.config",
"description": "Entaxy object configuration factory",
"isAbstract": false
},
"entaxy.runtime.config": {},
"fields": {
"configurables": {
"type": "Map",
"group": "config",
"required": true,
"defaultValue": {}
},
"immutables": {
"type": "Map",
"group": "config",
"required": true,
"defaultValue": {}
}
},
"outputs": {
"init": {
"isDefault": true,
"scopes": ["private", "public"],
"fields": {
"__entaxy_configuredId": {
"type": "String",
"isHidden": true
},
"__entaxy_configuredType": {
"type": "String",
"isHidden": true
},
"__entaxy_configuredFactoryId": {
"type": "String",
"isHidden": true
},
"__entaxy_configuredOutput": {
"type": "String",
"isHidden": true
}
}
},
"config-defaults": {
"isDefault": false,
"scopes": ["private", "public"],
"fields": {
"##publish": {
"defaultValue": {
"name": {
"@CALCULATED": {
"expression": "${properties.configurationPid}",
"lazy": true
}
},
"objectId": {
"@CALCULATED": {
"expression": "${properties.configurationPid}",
"lazy": true
}
},
"relation": [
{
"@CALCULATED": {
"expression": "${properties.__entaxy_configuredId}:${properties.__entaxy_configuredType}:config:-composition:config",
"lazy": false
}
}
],
"target": {
"@CALCULATED": {
"expression": "${properties.__entaxy_configuredId}:${properties.__entaxy_configuredType}",
"lazy": false
}
}
}
}
},
"config": {
"@PUBLISH_AS": {
"*": "configurationPid"
}
}
},
"config-link-field": {
"isDefault": false,
"generator": "",
"config": {},
"scopes": ["private", "public"]
},
"config-defaults-field": {
"isDefault": false,
"generator": "",
"config": {},
"scopes": ["private"]
},
"ref":{
"scopes": ["private", "public"]
}
}
}

View File

@ -0,0 +1,29 @@
[#ftl attributes={"generated.type":"json"}]
{
"factoryId": "object-config",
"objectId": "[=objectId]",
"scope": "private",
"outputType": "config-defaults",
"@FILL_CONFIGURABLES": "",
"properties": {
"configured": {
"@CALCULATED": {
"resultType": "String",
"expression": "${#OWNER#.objectId}",
"lazy": true
}
},
"__entaxy_configuredId":"[=targetObjectId]",
"__entaxy_configuredType":"[=targetObjectType]",
"__entaxy_configuredFactoryId":"[=targetObjectFactoryId]",
"__entaxy_configuredOutput":"[=targetObjectOutput]",
"configurationPid": [=configurationPid],
"configuredProperties": {
"@CALCULATED": {
"resultType": "Map",
"expression": "${#OWNER#.properties}",
"lazy": true
}
}
}
}

View File

@ -0,0 +1,44 @@
[#ftl attributes={"generated.type":"blueprint.fragment"}]
<!--
config for
objectId: [=__entaxy_configuredId]
type: [=__entaxy_configuredType]
pid: [=configurationPid]
prefix: [=placeholderPrefix]
configurables:
[#if configurables??]
[#list configurables as key, value]
[=key] = [#if value?is_boolean][=value?c][#else][=value][/#if]
[/#list]
[/#if]
-->
<cm:property-placeholder persistent-id="[=configurationPid]" update-strategy="reload" id="[=configurationPid].placeholder"
placeholder-prefix="[=placeholderPrefix]" placeholder-suffix="}"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
<cm:default-properties>
[#if configurables??]
[#list configurables as key, value]
<cm:property name="[=key]" value="[#if value?is_boolean][=value?c][#else][=value][/#if]" />
[/#list]
[/#if]
</cm:default-properties>
</cm:property-placeholder>
<!-- BEGIN placeholders for Camel -->
<!-- make property placeholder available in Camel context -->
<bean id="[=configurationPid].placeholder.wrapper" class="ru.entaxy.platform.core.support.runtime.camel.CmPropertiesAccessorFunction" activation="eager">
<property name="bundleContext" ref="blueprintBundleContext"/>
<property name="persistentId" value="[=configurationPid]" />
<property name="prefix" value="[=placeholderPrefix[1..placeholderPrefix?length-2]]" />
<property name="wrappedPlaceholder" ref="[=configurationPid].placeholder" />
</bean>
<propertyPlaceholder id="propertiesForCamel">
<propertiesFunction ref="[=configurationPid].placeholder.wrapper"/>
</propertyPlaceholder>
<!-- END placeholders for Camel -->

View File

@ -0,0 +1,23 @@
[#ftl attributes={"generated.type":"json"}]
{
"factoryId": "object-config",
"objectId": "[=objectId]",
"scope": "public",
"@FILL_CONFIGURABLES": "properties",
"properties": {
"__entaxy_configuredId":"[=targetObjectId]",
"__entaxy_configuredType":"[=targetObjectType]",
"__entaxy_configuredFactoryId":"[=targetObjectFactoryId]",
"__entaxy_configuredOutput":"[=targetObjectOutput]"
},
"configuredProperties": {
"@CALCULATED": {
"resultType": "Map",
"expression": "${#OWNER#.properties}",
"lazy": true
}
},
"refConfig": {
"isRefByValueOnly": true
}
}

View File

@ -0,0 +1,2 @@
[#ftl attributes={"generated.type":"config:json"}]
[=configurables_json!]

View File

@ -0,0 +1,22 @@
[#ftl attributes={"generated.type":"blueprint.fragment"}]
<cm:property-placeholder persistent-id="[=configurationPid]" update-strategy="reload" id="[=configurationPid].placeholder"
placeholder-prefix="[=placeholderPrefix]" placeholder-suffix="}"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
</cm:property-placeholder>
<!-- BEGIN placeholders for Camel -->
<!-- make property placeholder available in Camel context -->
<bean id="[=configurationPid].placeholder.wrapper" class="ru.entaxy.platform.core.support.runtime.camel.CmPropertiesAccessorFunction" activation="eager">
<property name="bundleContext" ref="blueprintBundleContext"/>
<property name="persistentId" value="[=configurationPid]" />
<property name="prefix" value="[=placeholderPrefix[1..placeholderPrefix?length-2]]" />
<property name="wrappedPlaceholder" ref="[=configurationPid].placeholder" />
</bean>
<propertyPlaceholder id="propertiesForCamel">
<propertiesFunction ref="[=configurationPid].placeholder.wrapper"/>
</propertyPlaceholder>
<!-- END placeholders for Camel -->

View File

@ -0,0 +1,37 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-resources-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.resources;
import java.util.Map;
public interface EntaxyResourceProducingProcessor {
String PROP_PROCESSOR = "processor";
String getName();
Object process(Object value, Map<String, Object> properties) throws Exception;
}

View File

@ -0,0 +1,34 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-resources-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.resources;
import java.util.Map;
public interface EntaxyResourceProducingProcessorService {
Object process(Object value, Map<String, Object> properties) throws Exception;
}

View File

@ -0,0 +1,90 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-resources-support
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.resources.impl;
import java.util.HashMap;
import java.util.Map;
import org.osgi.service.component.annotations.Activate;
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.platform.core.producer.resources.EntaxyResourceProducingProcessor;
import ru.entaxy.platform.core.producer.resources.EntaxyResourceProducingProcessorService;
@Component (service = EntaxyResourceProducingProcessorService.class, immediate = true)
public class EntaxyResourceProducingProcessorServiceImpl implements EntaxyResourceProducingProcessorService {
private static final Logger log = LoggerFactory.getLogger(EntaxyResourceProducingProcessorServiceImpl.class);
protected static EntaxyResourceProducingProcessorService _INSTANCE;
public static EntaxyResourceProducingProcessorService getInstance() {
return _INSTANCE;
}
protected Map<String, EntaxyResourceProducingProcessor> processorsMap = new HashMap<>();
@Activate
public void activate() {
_INSTANCE = this;
}
@Reference (cardinality = ReferenceCardinality.MULTIPLE, collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC
, policyOption = ReferencePolicyOption.GREEDY, unbind = "removeProcessor")
public void addProcessor(EntaxyResourceProducingProcessor processor) {
synchronized (processorsMap) {
this.processorsMap.put(processor.getName(), processor);
}
}
public void removeProcessor(EntaxyResourceProducingProcessor processor) {
synchronized (processorsMap) {
this.processorsMap.remove(processor.getName());
}
}
@Override
public Object process(Object value, Map<String, Object> properties) throws Exception{
Object val = properties.get(EntaxyResourceProducingProcessor.PROP_PROCESSOR);
if (val == null)
return value;
String processorName = val.toString();
if (!processorsMap.containsKey(processorName)) {
log.warn("Unknown processor [{}] in [{}]", processorName, properties);
return value;
}
return processorsMap.get(processorName).process(value, properties);
}
}

View File

@ -0,0 +1,62 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-shell
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.shell;
import java.util.Map;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import ru.entaxy.platform.base.support.karaf.shell.ShellTableExt;
import ru.entaxy.platform.core.producer.api.EntaxyProducerUtils;
@Service
@Command(scope = EntaxyProducerServiceSupport.SCOPE, name = "factory-essence")
public class FactoryEssence extends FactoryAwareCommand {
@Option(name = "-p", aliases = {"--prefix"})
String prefix = "";
@Override
protected Object doExecute() throws Exception {
Map<String, Object> essence = EntaxyProducerUtils.getFactoryEssence(entaxyFactory, prefix);
ShellTableExt table = new ShellTableExt();
table.column("Key");
table.column("Value");
for (Map.Entry<String, Object> entry : essence.entrySet())
table.addRow().addContent(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString());
// print output
table.print(System.out);
return null;
}
}

View File

@ -0,0 +1,91 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-shell
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.shell;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
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 org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.karaf.shell.ShellTableExt;
@Service
@Command(scope = "producer", name = "factory-find")
public class FindFactories extends EntaxyProducerServiceSupport implements Action {
@Argument(index = 0, required = true)
String filter;
@Override
public Object execute() throws Exception {
Filter osgiFilter = null;
try {
osgiFilter = FrameworkUtil.createFilter(filter);
} catch (InvalidSyntaxException e) {
// print error
System.err.println("Invalid filter:");
e.printStackTrace(System.err);
return null;
}
List<EntaxyFactory> factories =
producerService.findFactories(osgiFilter).stream().sorted(new Comparator<EntaxyFactory>() {
@Override
public int compare(EntaxyFactory o1, EntaxyFactory o2) {
return o1.getId().compareToIgnoreCase(o2.getId());
}
})
.collect(Collectors.toList());
ShellTableExt table = new ShellTableExt();
table.column("Id");
table.column("Type");
for (EntaxyFactory f : factories)
table.addRow().addContent(f.getId(), f.getType());
// print output
table.print(System.out);
return null;
}
}