release version 1.11.0
This commit is contained in:
46
platform/runtime/base/base-extensions-support/pom.xml
Normal file
46
platform/runtime/base/base-extensions-support/pom.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<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.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
|
||||
<artifactId>base-extensions-support</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>ENTAXY :: PLATFORM :: BASE :: EXTENSIONS SUPPORT</name>
|
||||
<description>ENTAXY :: PLATFORM :: BASE :: EXTENSIONS SUPPORT</description>
|
||||
|
||||
<properties>
|
||||
<bundle.osgi.export.pkg>
|
||||
ru.entaxy.esb.platform.runtime.base.extensions.api
|
||||
</bundle.osgi.export.pkg>
|
||||
<bundle.osgi.private.pkg>
|
||||
ru.entaxy.esb.platform.runtime.base.extensions.impl,
|
||||
ru.entaxy.esb.platform.runtime.base.extensions.shell
|
||||
</bundle.osgi.private.pkg>
|
||||
<bundle.osgi.remove.headers>none</bundle.osgi.remove.headers>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<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>org.apache.karaf.shell</groupId>
|
||||
<artifactId>org.apache.karaf.shell.core</artifactId>
|
||||
<version>${karaf.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface EntaxyExtendable extends EntaxyExtensionsProvider {
|
||||
|
||||
default String getExtendableId() {
|
||||
if (this.getClass().isAnnotationPresent(Extendable.class))
|
||||
return this.getClass().getAnnotation(Extendable.class).value();
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
void addExtension(EntaxyExtension entaxyExtension);
|
||||
void removeExtension(EntaxyExtension entaxyExtension);
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.api;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public interface EntaxyExtension {
|
||||
|
||||
long getBundleId();
|
||||
Map<String, URL> getResources();
|
||||
|
||||
Map<String, Object> getCustomData();
|
||||
|
||||
String getTargetExtendableId();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface EntaxyExtensionService {
|
||||
|
||||
String HEADER_EXTENSIONS_PROVIDER = "Entaxy-Extensions-Provider";
|
||||
String HEADER_EXTENSIONS_LOCATION = "Entaxy-Extensions-Location";
|
||||
|
||||
String DEFAULT_EXTENSIONS_LOCATION = "ru/entaxy/extensions";
|
||||
|
||||
List<EntaxyExtension> getExtensions();
|
||||
|
||||
List<EntaxyExtendable> getExtendables();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface EntaxyExtensionsAware {
|
||||
|
||||
void addExtension(EntaxyExtension entaxyExtension);
|
||||
default void addExtensions(List<EntaxyExtension> entaxyExtensions) {
|
||||
for (EntaxyExtension extension: entaxyExtensions)
|
||||
addExtension(extension);
|
||||
};
|
||||
|
||||
void removeExtension(EntaxyExtension entaxyExtension);
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface EntaxyExtensionsProvider {
|
||||
|
||||
List<EntaxyExtension> getExtensions();
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.api;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target(TYPE)
|
||||
public @interface Extendable {
|
||||
String value();
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
|
||||
|
||||
public class EntaxyExtensionImpl implements EntaxyExtension {
|
||||
|
||||
protected Bundle bundle;
|
||||
|
||||
protected String targetId;
|
||||
|
||||
protected final Map<String, Object> customData = new HashMap<>();
|
||||
|
||||
protected final Map<String, URL> resources = new HashMap<>();
|
||||
|
||||
public EntaxyExtensionImpl(Bundle b, String target) {
|
||||
this.bundle = b;
|
||||
this.targetId = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBundleId() {
|
||||
return bundle==null
|
||||
?-1
|
||||
:bundle.getBundleId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, URL> getResources() {
|
||||
return resources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getCustomData() {
|
||||
return customData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetExtendableId() {
|
||||
return targetId;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.BundleEvent;
|
||||
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.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicyOption;
|
||||
import org.osgi.util.tracker.BundleTracker;
|
||||
|
||||
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtendable;
|
||||
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
|
||||
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionService;
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.base.support.osgi.tracker.BundleTrackerCustomizerListener;
|
||||
import ru.entaxy.platform.base.support.osgi.tracker.BundleTrackerUtils;
|
||||
import ru.entaxy.platform.base.support.osgi.tracker.UniformBundleTrackerCustomizer;
|
||||
import ru.entaxy.platform.base.support.osgi.tracker.filter.BundleHeaderFilter;
|
||||
|
||||
@Component(service = EntaxyExtensionService.class, immediate = true)
|
||||
public class EntaxyExtensionServiceImpl
|
||||
extends UniformBundleTrackerCustomizer<List<EntaxyExtension>>
|
||||
implements EntaxyExtensionService,
|
||||
BundleTrackerCustomizerListener<List<EntaxyExtension>> {
|
||||
|
||||
protected BundleContext bundleContext;
|
||||
|
||||
protected Map<String, EntaxyExtendable> extendables = new HashMap<>();
|
||||
|
||||
protected Object extensionsLock = new Object();
|
||||
|
||||
protected final Map<String, List<EntaxyExtension>> extensions = new HashMap<>();
|
||||
|
||||
protected BundleTracker<List<EntaxyExtension>> extensionTracker;
|
||||
|
||||
@Activate
|
||||
public void activate(ComponentContext componentContext) {
|
||||
this.bundleContext = componentContext.getBundleContext();
|
||||
extensionTracker = BundleTrackerUtils.<List<EntaxyExtension>>createBuilder()
|
||||
.bundleContext(this.bundleContext)
|
||||
.addFilter(
|
||||
(new BundleHeaderFilter()).header(HEADER_EXTENSIONS_PROVIDER))
|
||||
.customizer(this.listener(this))
|
||||
.bundleState(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE)
|
||||
.get();
|
||||
extensionTracker.open();
|
||||
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
extensionTracker.close();
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY,
|
||||
unbind = "removeExtendable")
|
||||
public void addExtendable(EntaxyExtendable entaxyExtendable) {
|
||||
synchronized (extensionsLock) {
|
||||
String extendableId = entaxyExtendable.getExtendableId();
|
||||
extendables.put(extendableId, entaxyExtendable);
|
||||
if (extensions.containsKey(extendableId))
|
||||
for (EntaxyExtension extension : extensions.get(extendableId))
|
||||
entaxyExtendable.addExtension(extension);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeExtendable(EntaxyExtendable entaxyExtendable) {
|
||||
extendables.remove(entaxyExtendable.getExtendableId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void added(List<EntaxyExtension> managedObject) {
|
||||
synchronized (extensionsLock) {
|
||||
for (EntaxyExtension extension : managedObject) {
|
||||
String targetId = extension.getTargetExtendableId();
|
||||
extensions.putIfAbsent(targetId, new ArrayList<>());
|
||||
|
||||
extensions.get(targetId).add(extension);
|
||||
if (extendables.containsKey(targetId))
|
||||
extendables.get(targetId).addExtension(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modified(List<EntaxyExtension> ignore) {}
|
||||
|
||||
@Override
|
||||
public void removed(List<EntaxyExtension> managedObject) {
|
||||
synchronized (extensionsLock) {
|
||||
for (EntaxyExtension extension : managedObject) {
|
||||
String targetId = extension.getTargetExtendableId();
|
||||
if (extendables.containsKey(targetId))
|
||||
extendables.get(targetId).removeExtension(extension);
|
||||
|
||||
if (extensions.containsKey(targetId))
|
||||
extensions.get(targetId).remove(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<EntaxyExtension> createManagedObject(Bundle bundle, BundleEvent event,
|
||||
Map<String, List<?>> filterResults) {
|
||||
String resourceLocation =
|
||||
CommonUtils.getValid(bundle.getHeaders().get(HEADER_EXTENSIONS_LOCATION), DEFAULT_EXTENSIONS_LOCATION);
|
||||
Enumeration<URL> entries = bundle.findEntries(resourceLocation, "*.*", true);
|
||||
|
||||
Map<String, EntaxyExtensionImpl> localExtensions = new HashMap<>();
|
||||
|
||||
if (entries != null)
|
||||
while (entries.hasMoreElements()) {
|
||||
URL entry = entries.nextElement();
|
||||
if (entry.toString().endsWith("/"))
|
||||
continue;
|
||||
|
||||
String localPath = entry.toString();
|
||||
localPath = localPath.substring(localPath.indexOf(resourceLocation) + resourceLocation.length() + 1);
|
||||
|
||||
String resourceName = localPath.substring(localPath.lastIndexOf("/") + 1);
|
||||
|
||||
String path = localPath.lastIndexOf("/") >= 0
|
||||
? localPath.substring(0, localPath.lastIndexOf("/"))
|
||||
: "";
|
||||
int splitIndex = path.indexOf("/");
|
||||
String target = splitIndex > 0
|
||||
? path.substring(0, splitIndex)
|
||||
: "";
|
||||
|
||||
if (splitIndex > 0)
|
||||
path = path.substring(splitIndex + 1);
|
||||
|
||||
if (!CommonUtils.isValid(target) || !CommonUtils.isValid(resourceName))
|
||||
continue;
|
||||
|
||||
if (!localExtensions.containsKey(target))
|
||||
localExtensions.put(target, new EntaxyExtensionImpl(bundle, target));
|
||||
|
||||
localExtensions.get(target).getResources().put(path + "/" + resourceName, entry);
|
||||
|
||||
}
|
||||
|
||||
return localExtensions.values().stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntaxyExtension> getExtensions() {
|
||||
final List<EntaxyExtension> result = new ArrayList<>();
|
||||
extensions.values().forEach(arr -> result.addAll(arr));
|
||||
Collections.sort(result, new Comparator<EntaxyExtension>() {
|
||||
|
||||
@Override
|
||||
public int compare(EntaxyExtension o1, EntaxyExtension o2) {
|
||||
int res = o1.getTargetExtendableId().compareTo(o2.getTargetExtendableId());
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (o1.getBundleId() < o2.getBundleId())
|
||||
return -1;
|
||||
if (o1.getBundleId() > o2.getBundleId())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntaxyExtendable> getExtendables() {
|
||||
return extendables.values().stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.shell;
|
||||
|
||||
import org.apache.karaf.shell.api.action.Action;
|
||||
import org.apache.karaf.shell.api.action.lifecycle.Reference;
|
||||
|
||||
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionService;
|
||||
|
||||
public abstract class EntaxyExtensionServiceSupport implements Action {
|
||||
|
||||
@Reference
|
||||
EntaxyExtensionService extensionService;
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.shell;
|
||||
|
||||
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.esb.platform.runtime.base.extensions.api.EntaxyExtendable;
|
||||
|
||||
@Service
|
||||
@Command(scope = "entaxy", name = "extendables-list")
|
||||
public class ExtendablesList extends EntaxyExtensionServiceSupport {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Exception {
|
||||
|
||||
ShellTable table = new ShellTable();
|
||||
|
||||
table.column("Extendable id");
|
||||
|
||||
for (EntaxyExtendable ext: extensionService.getExtendables())
|
||||
table.addRow().addContent(ext.getExtendableId());
|
||||
|
||||
table.print(System.out);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-extensions-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.esb.platform.runtime.base.extensions.shell;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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 org.apache.karaf.shell.support.table.ShellTable;
|
||||
|
||||
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
|
||||
|
||||
@Service
|
||||
@Command(scope = "entaxy", name = "extension-list")
|
||||
public class ExtensionsList extends EntaxyExtensionServiceSupport {
|
||||
|
||||
@Option(name = "-r", multiValued = false)
|
||||
boolean showResources;
|
||||
|
||||
@Override
|
||||
public Object execute() throws Exception {
|
||||
ShellTable shellTable = new ShellTable();
|
||||
|
||||
shellTable.column("Target");
|
||||
shellTable.column("Bundle");
|
||||
|
||||
if (showResources) {
|
||||
shellTable.column("Resource");
|
||||
shellTable.column("Resource URL");
|
||||
}
|
||||
|
||||
List<EntaxyExtension> list = extensionService.getExtensions();
|
||||
for (EntaxyExtension ext: list)
|
||||
if (!showResources)
|
||||
shellTable.addRow().addContent(ext.getTargetExtendableId(), ext.getBundleId());
|
||||
else {
|
||||
List<String> resources = new ArrayList<>(ext.getResources().keySet());
|
||||
Collections.sort(resources);
|
||||
for (String resource: resources) {
|
||||
shellTable.addRow().addContent(
|
||||
ext.getTargetExtendableId(),
|
||||
ext.getBundleId(),
|
||||
resource,
|
||||
ext.getResources().get(resource).toString());
|
||||
}
|
||||
}
|
||||
|
||||
shellTable.print(System.out);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime</groupId>
|
||||
<artifactId>base</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
|
||||
<artifactId>base-support</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -0,0 +1,211 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.support;
|
||||
|
||||
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
|
||||
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
|
||||
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.nio.file.WatchKey;
|
||||
import java.nio.file.WatchService;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SimpleFileWatcher implements Runnable {
|
||||
|
||||
public static interface WatcherCallback {
|
||||
|
||||
default void directoryCreated(WatchEvent<?> event, Path directory) {};
|
||||
|
||||
default void directoryModified(WatchEvent<?> event, Path directory) {};
|
||||
|
||||
default void directoryDeleted(WatchEvent<?> event, Path directory) {};
|
||||
|
||||
default void fileCreated(WatchEvent<?> event, Path directory) {};
|
||||
|
||||
default void fileModified(WatchEvent<?> event, Path directory) {};
|
||||
|
||||
default void fileDeleted(WatchEvent<?> event, Path directory) {};
|
||||
|
||||
}
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SimpleFileWatcher.class);
|
||||
|
||||
protected static final WatcherCallback NULL_CALLBACK = new WatcherCallback() {};
|
||||
|
||||
protected final WatchService watchService;
|
||||
protected final Map<WatchKey, Path> keys;
|
||||
|
||||
protected WatcherCallback watcherCallback = null;
|
||||
|
||||
/**
|
||||
* Creates a WatchService and registers the given directory
|
||||
*/
|
||||
public SimpleFileWatcher(Path dir) throws IOException {
|
||||
this.watchService = FileSystems.getDefault().newWatchService();
|
||||
this.keys = new HashMap<WatchKey, Path>();
|
||||
|
||||
walkAndRegisterDirectories(dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given directory with the WatchService; This function will be called by
|
||||
* FileVisitor
|
||||
*/
|
||||
private void registerDirectory(Path dir) throws IOException {
|
||||
WatchKey key = dir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
|
||||
keys.put(key, dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given directory, and all its sub-directories, with the WatchService.
|
||||
*/
|
||||
private void walkAndRegisterDirectories(final Path start) throws IOException {
|
||||
// register directory and sub-directories
|
||||
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
registerDirectory(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setWatcherCallback(WatcherCallback watcherCallback) {
|
||||
this.watcherCallback = watcherCallback;
|
||||
}
|
||||
|
||||
protected WatcherCallback getActiveCallback() {
|
||||
return watcherCallback == null ? NULL_CALLBACK : watcherCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all events for keys queued to the watchService
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
WatchKey key = null;
|
||||
try {
|
||||
while ((key = watchService.take()) != null) {
|
||||
|
||||
Path dir = keys.get(key);
|
||||
if (dir == null) {
|
||||
System.err.println("WatchKey not recognized!!");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WatchEvent<?> event : key.pollEvents()) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
WatchEvent.Kind kind = event.kind();
|
||||
|
||||
// Context for directory entry event is the file name of entry
|
||||
@SuppressWarnings("unchecked")
|
||||
Path name = ((WatchEvent<Path>) event).context();
|
||||
Path child = dir.resolve(name);
|
||||
|
||||
// print out event
|
||||
LOG.debug("{}: {}\n", event.kind().name(), child);
|
||||
|
||||
// if directory is created, and watching recursively, then register it and its
|
||||
// sub-directories
|
||||
|
||||
if (kind == ENTRY_CREATE) {
|
||||
try {
|
||||
if (Files.isDirectory(child)) {
|
||||
walkAndRegisterDirectories(child);
|
||||
getActiveCallback().directoryCreated(event, dir);
|
||||
} else {
|
||||
LOG.debug("FOUND FILE: {}", child.toString());
|
||||
getActiveCallback().fileCreated(event, dir);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
LOG.error(String.format("FAILED processing event [%s] for [%s]", kind, child.toString()),
|
||||
x);
|
||||
}
|
||||
} else if (kind == ENTRY_MODIFY) {
|
||||
try {
|
||||
if (Files.isDirectory(child)) {
|
||||
getActiveCallback().directoryModified(event, dir);
|
||||
} else {
|
||||
getActiveCallback().fileModified(event, dir);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
LOG.error(String.format("FAILED processing event [%s] for [%s]", kind, child.toString()),
|
||||
x);
|
||||
}
|
||||
} else if (kind == ENTRY_DELETE) {
|
||||
try {
|
||||
if (Files.isDirectory(child)) {
|
||||
getActiveCallback().directoryDeleted(event, dir);
|
||||
} else {
|
||||
getActiveCallback().fileDeleted(event, dir);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
LOG.error(String.format("FAILED processing event [%s] for [%s]", kind, child.toString()),
|
||||
x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset key and remove from set if directory no longer accessible
|
||||
boolean valid = key.reset();
|
||||
if (!valid) {
|
||||
keys.remove(key);
|
||||
|
||||
// all directories are inaccessible
|
||||
if (keys.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ignore) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
for (WatchKey key : keys.keySet())
|
||||
key.cancel();
|
||||
this.watchService.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("FAILED closing SimpleFileWatcher", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to You 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.
|
||||
*/
|
||||
package ru.entaxy.platform.base.support.karaf.shell;
|
||||
|
||||
import org.jline.utils.AttributedStringBuilder;
|
||||
|
||||
/**
|
||||
* Colored support for column.
|
||||
*/
|
||||
public class AnsiColumnExt extends ColExt {
|
||||
|
||||
private int color;
|
||||
private boolean bold;
|
||||
|
||||
public AnsiColumnExt(String header, int color, boolean bold) {
|
||||
super(header);
|
||||
this.color = color;
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
public String getContent(ShellTableExt.CellData cellData) {
|
||||
String in = super.getContent(cellData);
|
||||
|
||||
AttributedStringBuilder sb = new AttributedStringBuilder();
|
||||
sb.style(sb.style().foreground(color));
|
||||
|
||||
if (bold)
|
||||
sb.style(sb.style().bold());
|
||||
|
||||
sb.append(in);
|
||||
|
||||
if (bold)
|
||||
sb.style(sb.style().boldOff());
|
||||
|
||||
sb.style(sb.style().foregroundOff());
|
||||
|
||||
return sb.toAnsi();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String getContent(String content) {
|
||||
String in = super.getContent(content);
|
||||
|
||||
AttributedStringBuilder sb = new AttributedStringBuilder();
|
||||
sb.style(sb.style().foreground(color));
|
||||
|
||||
if (bold)
|
||||
sb.style(sb.style().bold());
|
||||
|
||||
sb.append(in);
|
||||
|
||||
if (bold)
|
||||
sb.style(sb.style().boldOff());
|
||||
|
||||
sb.style(sb.style().foregroundOff());
|
||||
|
||||
return sb.toAnsi();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,381 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to You 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.
|
||||
*/
|
||||
package ru.entaxy.platform.base.support.karaf.shell;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.karaf.shell.support.ansi.SimpleAnsi;
|
||||
|
||||
/**
|
||||
* Column definition.
|
||||
*/
|
||||
public class ColExt {
|
||||
// This is kept here only for backwards compatibility
|
||||
// and is used in cyan(boolean) method
|
||||
private static final Function<String, String> COLOR_CYAN =
|
||||
(cellContent) -> SimpleAnsi.COLOR_CYAN;
|
||||
|
||||
Function<String, String> colorProvider;
|
||||
|
||||
Function<ShellTableExt.CellData, String> colorProviderExt;
|
||||
|
||||
protected ShellTableExt ownerTable = null;
|
||||
|
||||
/**
|
||||
* Column header.
|
||||
*/
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* Maximum size of this column. The default -1 means the column may grow indefinitely
|
||||
*/
|
||||
int maxSize = -1;
|
||||
|
||||
int size = 0;
|
||||
|
||||
boolean wrap;
|
||||
boolean bold;
|
||||
boolean cyan;
|
||||
|
||||
Boolean splitLists = null;
|
||||
|
||||
/**
|
||||
* Alignment
|
||||
*/
|
||||
private HAlignExt align = HAlignExt.left;
|
||||
|
||||
public ColExt(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public ColExt align(HAlignExt align) {
|
||||
this.align = align;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt alignLeft() {
|
||||
this.align = HAlignExt.left;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt alignRight() {
|
||||
this.align = HAlignExt.right;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt alignCenter() {
|
||||
this.align = HAlignExt.center;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt maxSize(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt splitLists() {
|
||||
return splitLists(true);
|
||||
}
|
||||
|
||||
public ColExt splitLists(boolean value) {
|
||||
this.splitLists = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt wrap() {
|
||||
return wrap(true);
|
||||
}
|
||||
|
||||
public ColExt wrap(boolean wrap) {
|
||||
this.wrap = wrap;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt bold() {
|
||||
return bold(true);
|
||||
}
|
||||
|
||||
public ColExt bold(boolean bold) {
|
||||
this.bold = bold;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt cyan() {
|
||||
return cyan(true);
|
||||
}
|
||||
|
||||
public ColExt cyan(boolean cyan) {
|
||||
if (cyan)
|
||||
colorProvider(COLOR_CYAN);
|
||||
|
||||
// Only remove colorProvider if argument is false and
|
||||
// member equals COLOR_CYAN
|
||||
else if (this.colorProvider == COLOR_CYAN)
|
||||
colorProvider(null);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public ColExt colorProvider(Function<String, String> colorProvider) {
|
||||
this.colorProvider = colorProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt colorProviderExt(Function<ShellTableExt.CellData, String> colorProvider) {
|
||||
this.colorProviderExt = colorProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void updateSize(int cellSize) {
|
||||
if (this.size <= cellSize) {
|
||||
this.size = getClippedSize(cellSize);
|
||||
}
|
||||
}
|
||||
|
||||
private int getClippedSize(int cellSize) {
|
||||
return this.maxSize == -1 ? cellSize : Math.min(cellSize, this.maxSize);
|
||||
}
|
||||
|
||||
/*
|
||||
String format(Object cellData) {
|
||||
if (cellData == null) {
|
||||
cellData = "";
|
||||
}
|
||||
String fullContent = String.format("%s", cellData);
|
||||
if (fullContent.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
String finalContent = cut(fullContent, getClippedSize(fullContent.length()));
|
||||
updateSize(finalContent.length());
|
||||
return finalContent;
|
||||
}
|
||||
*/
|
||||
|
||||
protected boolean isSplitLists() {
|
||||
if (this.splitLists != null)
|
||||
return this.splitLists;
|
||||
if (ownerTable != null)
|
||||
return ownerTable.isSplitLists();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ENTAXY_FIX:
|
||||
when calculating cell size we must take into account not LENGTH, but WIDTH of the data
|
||||
'cause data may contain "\n" so the LENGTH of data won't be equal to it's WIDTH
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public String format(Object cellData) {
|
||||
if (cellData == null) {
|
||||
cellData = "";
|
||||
}
|
||||
|
||||
String fullContent = String.format("%s", cellData);
|
||||
|
||||
if (isSplitLists() && (cellData instanceof List)) {
|
||||
fullContent = (String) ((List) cellData).stream().map(v -> v == null ? "" : v.toString())
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
if (fullContent.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
String finalContent = cut(fullContent, getClippedSize(fullContent.length()));
|
||||
|
||||
int finalContentWidth = 0;
|
||||
for (String s : Arrays.asList(finalContent.split("\n")))
|
||||
finalContentWidth = Math.max(finalContentWidth, s.length());
|
||||
|
||||
updateSize(finalContentWidth);
|
||||
return finalContent;
|
||||
}
|
||||
|
||||
String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
String getContent(ShellTableExt.CellData cellData) {
|
||||
|
||||
String content = cellData.cellContent;
|
||||
|
||||
List<String> lines = new ArrayList<>();
|
||||
lines.addAll(Arrays.asList(content.split("\n")));
|
||||
if (wrap) {
|
||||
List<String> wrapped = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
wrapped.addAll(wrap(line));
|
||||
}
|
||||
lines = wrapped;
|
||||
}
|
||||
|
||||
String color = null;
|
||||
if (colorProviderExt != null) {
|
||||
color = colorProviderExt.apply(cellData);
|
||||
} else if (colorProvider != null) {
|
||||
color = colorProvider.apply(content);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String line : lines) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append("\n");
|
||||
}
|
||||
line = this.align.position(cut(line, size), this.size);
|
||||
if (bold) {
|
||||
line = SimpleAnsi.INTENSITY_BOLD + line + SimpleAnsi.INTENSITY_NORMAL;
|
||||
}
|
||||
|
||||
if (color != null)
|
||||
sb.append(color);
|
||||
|
||||
sb.append(line);
|
||||
|
||||
if (color != null)
|
||||
sb.append(SimpleAnsi.COLOR_DEFAULT);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
String getContent(String content) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
lines.addAll(Arrays.asList(content.split("\n")));
|
||||
if (wrap) {
|
||||
List<String> wrapped = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
wrapped.addAll(wrap(line));
|
||||
}
|
||||
lines = wrapped;
|
||||
}
|
||||
|
||||
String color = null;
|
||||
if (colorProvider != null) {
|
||||
color = colorProvider.apply(content);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String line : lines) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append("\n");
|
||||
}
|
||||
line = this.align.position(cut(line, size), this.size);
|
||||
if (bold) {
|
||||
line = SimpleAnsi.INTENSITY_BOLD + line + SimpleAnsi.INTENSITY_NORMAL;
|
||||
}
|
||||
|
||||
if (color != null)
|
||||
sb.append(color);
|
||||
|
||||
sb.append(line);
|
||||
|
||||
if (color != null)
|
||||
sb.append(SimpleAnsi.COLOR_DEFAULT);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
protected String cut(String content, int size) {
|
||||
if (content.length() <= size) {
|
||||
return content;
|
||||
} else {
|
||||
return content.substring(0, Math.max(0, size - 1));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
protected String cut0(String content, int size) {
|
||||
if (content.length() <= size) {
|
||||
return content;
|
||||
} else {
|
||||
return content.substring(0, Math.max(0, size - 1));
|
||||
}
|
||||
}
|
||||
|
||||
protected String cut(String content, int size) {
|
||||
if (content.length() <= size) {
|
||||
return content;
|
||||
} else {
|
||||
|
||||
String[] contentSplitted = content.split("\n");
|
||||
for (int i = 0; i < contentSplitted.length; i++)
|
||||
contentSplitted[i] = cut0(contentSplitted[i], size);
|
||||
|
||||
if (contentSplitted.length == 1)
|
||||
return contentSplitted[0];
|
||||
|
||||
return Arrays.asList(contentSplitted).stream().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
protected List<String> wrap(String str) {
|
||||
List<String> result = new ArrayList<>();
|
||||
Pattern wrap = Pattern.compile("(\\S\\S{" + size + ",}|.{1," + size + "})(\\s+|$)");
|
||||
int cur = 0;
|
||||
while (cur >= 0) {
|
||||
int lst = str.indexOf('\n', cur);
|
||||
String s = (lst >= 0) ? str.substring(cur, lst) : str.substring(cur);
|
||||
if (s.length() == 0) {
|
||||
result.add(s);
|
||||
} else {
|
||||
Matcher m = wrap.matcher(s);
|
||||
while (m.find()) {
|
||||
result.add(m.group());
|
||||
}
|
||||
}
|
||||
if (lst >= 0) {
|
||||
cur = lst + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to You 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.
|
||||
*/
|
||||
package ru.entaxy.platform.base.support.karaf.shell;
|
||||
|
||||
import static ru.entaxy.platform.base.support.karaf.shell.StringUtil.length;
|
||||
import static ru.entaxy.platform.base.support.karaf.shell.StringUtil.repeat;
|
||||
|
||||
/**
|
||||
* Enumeration type which contains all possible horizontal alignments.
|
||||
*/
|
||||
public enum HAlignExt {
|
||||
|
||||
/**
|
||||
* Center align.
|
||||
*/
|
||||
center {
|
||||
@Override
|
||||
public String position(String text, int colWidth) {
|
||||
int width = colWidth - length(text);
|
||||
text = repeat(" ", width / 2) + text + repeat(" ", width / 2);
|
||||
if (length(text) < colWidth) {
|
||||
// if colWidth is odd we add space at the end.
|
||||
text += " ";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Left align.
|
||||
*/
|
||||
left {
|
||||
@Override
|
||||
public String position(String text, int colWidth) {
|
||||
return text + repeat(" ", colWidth - length(text));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Right align.
|
||||
*/
|
||||
right {
|
||||
@Override
|
||||
public String position(String text, int colWidth) {
|
||||
return repeat(" ", colWidth - length(text)) + text;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate text position.
|
||||
*
|
||||
* @param text the text to align.
|
||||
* @param colWidth the column width.
|
||||
* @return the string at the given position.
|
||||
*/
|
||||
public abstract String position(String text, int colWidth);
|
||||
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to You 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.
|
||||
*/
|
||||
package ru.entaxy.platform.base.support.karaf.shell;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class RowExt {
|
||||
|
||||
protected List<Object> data;
|
||||
protected List<String> content;
|
||||
|
||||
protected Object dataObject = null;
|
||||
|
||||
RowExt() {
|
||||
data = new ArrayList<>();
|
||||
content = new ArrayList<>();
|
||||
}
|
||||
|
||||
RowExt(Object dataObject) {
|
||||
data = new ArrayList<>();
|
||||
content = new ArrayList<>();
|
||||
this.dataObject = dataObject;
|
||||
}
|
||||
|
||||
RowExt(List<ColExt> cols) {
|
||||
this();
|
||||
for (ColExt col : cols) {
|
||||
data.add(col.getHeader());
|
||||
}
|
||||
}
|
||||
|
||||
public void addContent(List<Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void addContent(Object... cellDataAr) {
|
||||
data.addAll(Arrays.asList(cellDataAr));
|
||||
}
|
||||
|
||||
void formatContent(List<ColExt> cols) {
|
||||
content.clear();
|
||||
int c = 0;
|
||||
for (ColExt col : cols) {
|
||||
content.add(col.format(data.get(c)));
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
String getContent(List<ColExt> cols, String separator) {
|
||||
if (cols.size() != content.size()) {
|
||||
throw new RuntimeException("Number of columns and number of content elements do not match");
|
||||
}
|
||||
|
||||
List<String[]> contents = new ArrayList<>();
|
||||
int lines = 0;
|
||||
for (int col = 0; col < cols.size(); col++) {
|
||||
// String[] cnt = cols.get(col).getContent(content.get(col)).split("\n");
|
||||
String[] cnt = cols.get(col).getContent(new ShellTableExt.CellData(dataObject, content.get(col))).split("\n");
|
||||
lines = Math.max(lines, cnt.length);
|
||||
contents.add(cnt);
|
||||
}
|
||||
StringBuilder st = new StringBuilder();
|
||||
for (int line = 0; line < lines; line++) {
|
||||
if (line > 0) {
|
||||
st.append("\n");
|
||||
}
|
||||
StringBuilder st2 = new StringBuilder();
|
||||
for (int col = 0; col < cols.size(); col++) {
|
||||
String[] strings = contents.get(col);
|
||||
if (col > 0) {
|
||||
st2.append(separator);
|
||||
}
|
||||
if (line < strings.length) {
|
||||
st2.append(strings[line]);
|
||||
} else {
|
||||
st2.append(StringUtil.repeat(" ", cols.get(col).getSize()));
|
||||
}
|
||||
}
|
||||
while (st2.charAt(st2.length() - 1) == ' ') {
|
||||
st2.setLength(st2.length() - 1);
|
||||
}
|
||||
st.append(st2);
|
||||
}
|
||||
return st.toString();
|
||||
}
|
||||
|
||||
public Object getDataObject() {
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
public void setDataObject(Object dataObject) {
|
||||
this.dataObject = dataObject;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* platform-manager-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.support.karaf.shell;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.karaf.shell.support.table.Col;
|
||||
|
||||
public class ShellTableColFixed extends Col {
|
||||
|
||||
protected int maxSizeLocal = -1;
|
||||
|
||||
public ShellTableColFixed(String header) {
|
||||
super(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String cut(String content, int size) {
|
||||
if (content.length() <= size) {
|
||||
return content;
|
||||
} else {
|
||||
|
||||
String[] contentSplitted = content.split("\n");
|
||||
for (int i=0; i<contentSplitted.length; i++)
|
||||
contentSplitted[i] = super.cut(contentSplitted[i], size);
|
||||
|
||||
if (contentSplitted.length == 1)
|
||||
return contentSplitted[0];
|
||||
|
||||
return Arrays.asList(contentSplitted).stream().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShellTableColFixed maxSize(int maxSize) {
|
||||
this.maxSizeLocal = maxSize;
|
||||
return (ShellTableColFixed)super.maxSize(maxSize);
|
||||
}
|
||||
|
||||
private int getClippedSize(int cellSize) {
|
||||
return this.maxSizeLocal == -1 ? cellSize : Math.min(cellSize, this.maxSizeLocal);
|
||||
}
|
||||
/*
|
||||
@ENTAXY_FIX:
|
||||
when calculating cell size we must take into account not LENGTH, but WIDTH of the data
|
||||
'cause data may contain "\n" so the LENGTH of data won't be equal to it's WIDTH
|
||||
*/
|
||||
public String format(Object cellData) {
|
||||
if (cellData == null) {
|
||||
cellData = "";
|
||||
}
|
||||
String fullContent = String.format("%s", cellData);
|
||||
if (fullContent.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
String finalContent = cut(fullContent, getClippedSize(fullContent.length()));
|
||||
|
||||
int finalContentWidth = 0;
|
||||
for (String s: Arrays.asList(finalContent.split("\n")))
|
||||
finalContentWidth = Math.max(finalContentWidth, s.length());
|
||||
|
||||
updateSize(finalContentWidth);
|
||||
return finalContent;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,284 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to You 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.
|
||||
*/
|
||||
package ru.entaxy.platform.base.support.karaf.shell;
|
||||
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.felix.gogo.runtime.threadio.ThreadPrintStream;
|
||||
import org.apache.felix.service.command.Job;
|
||||
import org.jline.terminal.Terminal;
|
||||
|
||||
public class ShellTableExt {
|
||||
|
||||
private static final char SEP_HORIZONTAL = '─';
|
||||
private static final char SEP_VERTICAL = '│';
|
||||
private static final char SEP_CROSS = '┼';
|
||||
|
||||
private static final char SEP_HORIZONTAL_ASCII = '-';
|
||||
private static final char SEP_VERTICAL_ASCII = '|';
|
||||
private static final char SEP_CROSS_ASCII = '+';
|
||||
|
||||
private static final String DEFAULT_SEPARATOR = " " + SEP_VERTICAL + " ";
|
||||
private static final String DEFAULT_SEPARATOR_ASCII = " " + SEP_VERTICAL_ASCII + " ";
|
||||
private static final String DEFAULT_SEPARATOR_NO_FORMAT = "\t";
|
||||
|
||||
private List<ColExt> cols = new ArrayList<>();
|
||||
private List<RowExt> rows = new ArrayList<>();
|
||||
private boolean showHeaders = true;
|
||||
private String separator = DEFAULT_SEPARATOR;
|
||||
private int size;
|
||||
private String emptyTableText;
|
||||
private boolean forceAscii;
|
||||
|
||||
private boolean splitLists = false;
|
||||
|
||||
public ShellTableExt() {
|
||||
|
||||
}
|
||||
|
||||
public ShellTableExt noHeaders() {
|
||||
this.showHeaders = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShellTableExt separator(String separator) {
|
||||
this.separator = separator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShellTableExt size(int size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSplitLists() {
|
||||
return splitLists;
|
||||
}
|
||||
|
||||
public ShellTableExt splitLists() {
|
||||
return splitLists(true);
|
||||
}
|
||||
|
||||
public ShellTableExt splitLists(boolean value) {
|
||||
this.splitLists = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShellTableExt column(ColExt colunmn) {
|
||||
cols.add(colunmn);
|
||||
colunmn.ownerTable = this;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColExt column(String header) {
|
||||
ColExt col = new ColExt(header);
|
||||
col.ownerTable = this;
|
||||
cols.add(col);
|
||||
return col;
|
||||
}
|
||||
|
||||
public RowExt addRow() {
|
||||
RowExt row = new RowExt();
|
||||
rows.add(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
public RowExt addRow(Object dataObject) {
|
||||
RowExt row = addRow();
|
||||
row.setDataObject(dataObject);
|
||||
return row;
|
||||
}
|
||||
|
||||
public ShellTableExt forceAscii() {
|
||||
forceAscii = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text to display if there are no rows in the table.
|
||||
*
|
||||
* @param text the text to display when the table is empty.
|
||||
* @return the shell table.
|
||||
*/
|
||||
public ShellTableExt emptyTableText(String text) {
|
||||
this.emptyTableText = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void print(PrintStream out) {
|
||||
print(out, true);
|
||||
}
|
||||
|
||||
public void print(PrintStream out, boolean format) {
|
||||
print(out, null, format);
|
||||
}
|
||||
|
||||
public void print(PrintStream out, Charset charset, boolean format) {
|
||||
boolean unicode = supportsUnicode(out, charset);
|
||||
String separator = unicode ? this.separator : DEFAULT_SEPARATOR_ASCII;
|
||||
|
||||
// "normal" table rendering, with borders
|
||||
RowExt headerRow = new RowExt(cols);
|
||||
headerRow.formatContent(cols);
|
||||
for (RowExt row : rows) {
|
||||
row.formatContent(cols);
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
if (format && showHeaders) {
|
||||
String headerLine = headerRow.getContent(cols, separator);
|
||||
out.println(headerLine);
|
||||
int iCol = 0;
|
||||
for (ColExt col : cols) {
|
||||
if (iCol++ == 0) {
|
||||
out.print(underline(col.getSize(), false, unicode));
|
||||
} else {
|
||||
out.print(underline(col.getSize() + 3, true, unicode));
|
||||
}
|
||||
iCol++;
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
|
||||
for (RowExt row : rows) {
|
||||
if (!format) {
|
||||
if (separator == null || separator.equals(DEFAULT_SEPARATOR))
|
||||
out.println(row.getContent(cols, DEFAULT_SEPARATOR_NO_FORMAT));
|
||||
else
|
||||
out.println(row.getContent(cols, separator));
|
||||
} else {
|
||||
out.println(row.getContent(cols, separator));
|
||||
}
|
||||
}
|
||||
|
||||
if (format && rows.size() == 0 && emptyTableText != null) {
|
||||
out.println(emptyTableText);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean supportsUnicode(PrintStream out, Charset charset) {
|
||||
if (forceAscii) {
|
||||
return false;
|
||||
}
|
||||
if (charset == null) {
|
||||
charset = getEncoding(out);
|
||||
}
|
||||
if (charset == null) {
|
||||
return false;
|
||||
}
|
||||
CharsetEncoder encoder = charset.newEncoder();
|
||||
return encoder.canEncode(separator)
|
||||
&& encoder.canEncode(SEP_HORIZONTAL)
|
||||
&& encoder.canEncode(SEP_CROSS);
|
||||
}
|
||||
|
||||
private Charset getEncoding(PrintStream ps) {
|
||||
if (ps.getClass() == ThreadPrintStream.class) {
|
||||
try {
|
||||
return ((Terminal) Job.Utils.current().session().get(".jline.terminal")).encoding();
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
ps = (PrintStream) ps.getClass().getMethod("getCurrent").invoke(ps);
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
try {
|
||||
Field f = ps.getClass().getDeclaredField("charOut");
|
||||
f.setAccessible(true);
|
||||
OutputStreamWriter osw = (OutputStreamWriter) f.get(ps);
|
||||
return Charset.forName(osw.getEncoding());
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void adjustSize() {
|
||||
int currentSize = 0;
|
||||
for (ColExt col : cols) {
|
||||
currentSize += col.size + separator.length();
|
||||
}
|
||||
currentSize -= separator.length();
|
||||
int sizeToGrow = size - currentSize;
|
||||
|
||||
for (int i = cols.size() - 1; i >= 0; i--) {
|
||||
ColExt col = cols.get(i);
|
||||
if (col.maxSize == -1) {
|
||||
col.size = Math.max(0, col.size + sizeToGrow);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String underline(int length, boolean crossAtBeg, boolean supported) {
|
||||
char[] exmarks = new char[length];
|
||||
Arrays.fill(exmarks, supported ? SEP_HORIZONTAL : SEP_HORIZONTAL_ASCII);
|
||||
if (crossAtBeg) {
|
||||
exmarks[1] = supported ? SEP_CROSS : SEP_CROSS_ASCII;
|
||||
}
|
||||
return new String(exmarks);
|
||||
}
|
||||
|
||||
public static class CellData {
|
||||
public Object dataObject;
|
||||
public String cellContent;
|
||||
|
||||
public CellData(Object dataObject, String cellContent) {
|
||||
this.dataObject = dataObject;
|
||||
this.cellContent = cellContent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* platform-manager-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.support.karaf.shell;
|
||||
|
||||
import org.apache.karaf.shell.support.table.ShellTable;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ru.entaxy.platform.base.support.karaf.shell.ShellTableExt} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class ShellTableFixed extends ShellTable {
|
||||
|
||||
@Override
|
||||
public ShellTableColFixed column(String header) {
|
||||
ShellTableColFixed col = new ShellTableColFixed(header);
|
||||
column(col);
|
||||
return col;
|
||||
}
|
||||
|
||||
public ShellTableFixed column(ShellTableColFixed colunmn) {
|
||||
super.column(colunmn);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to You 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.
|
||||
*/
|
||||
package ru.entaxy.platform.base.support.karaf.shell;
|
||||
|
||||
public class StringUtil {
|
||||
|
||||
/**
|
||||
* Returns length of the string.
|
||||
*
|
||||
* @param string String.
|
||||
* @return Length.
|
||||
*/
|
||||
public static int length(String string) {
|
||||
return string == null ? 0 : string.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to repeat string.
|
||||
*
|
||||
* @param string String to repeat.
|
||||
* @param times Number of times.
|
||||
* @return Repeat string.
|
||||
*/
|
||||
public static String repeat(String string, int times) {
|
||||
if (times <= 0) {
|
||||
return "";
|
||||
} else if (times % 2 == 0) {
|
||||
return repeat(string + string, times / 2);
|
||||
} else {
|
||||
return string + repeat(string + string, times / 2);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* artifact-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* artifact-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.support.osgi.feature;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.karaf.features.Capability;
|
||||
import org.apache.karaf.features.Feature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.base.support.osgi.bundle.CapabilityDescriptorImpl;
|
||||
import ru.entaxy.platform.base.support.osgi.bundle.CapabilityHelper;
|
||||
|
||||
public class FeatureCapabilityHelper extends CapabilityHelper {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FeatureCapabilityHelper.class);
|
||||
|
||||
protected Feature feature;
|
||||
|
||||
public FeatureCapabilityHelper(Feature feature) {
|
||||
super();
|
||||
setMultipleNamespacesSupported(true);
|
||||
this.feature = feature;
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
super.load();
|
||||
List<? extends Capability> featureCapabilities = feature.getCapabilities();
|
||||
for (Capability c : featureCapabilities) {
|
||||
String[] caps = c.getValue().split(",");
|
||||
for (String cap : caps)
|
||||
try {
|
||||
CapabilityDescriptorImpl descriptor = parseCapability(cap);
|
||||
if (descriptor != null)
|
||||
addProvidedCapability(descriptor);
|
||||
} catch (Exception e) {
|
||||
LOG.error(String.format("Error parsing capability [%s] for feature [%s/%s]", cap, feature.getName(),
|
||||
feature.getVersion()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.support.osgi.feature;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.karaf.bundle.core.BundleService;
|
||||
import org.apache.karaf.features.Feature;
|
||||
import org.apache.karaf.features.FeaturesService;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.FrameworkUtil;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
|
||||
public class FeaturesUtils {
|
||||
|
||||
public static class FeaturesHelper {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FeaturesUtils.FeaturesHelper.class);
|
||||
|
||||
public static FeaturesHelper create() {
|
||||
return new FeaturesHelper();
|
||||
}
|
||||
|
||||
public static FeaturesHelper create(BundleContext bundleContext) {
|
||||
return create().bundleContext(bundleContext);
|
||||
}
|
||||
|
||||
protected BundleContext bundleContext = FrameworkUtil.getBundle(FeaturesUtils.class).getBundleContext();
|
||||
|
||||
protected String capabilityNamespace = null;
|
||||
|
||||
protected boolean installedOnly = false;
|
||||
|
||||
protected Bundle bundle = null;
|
||||
|
||||
protected FeaturesHelper() {
|
||||
super();
|
||||
}
|
||||
|
||||
public List<Feature> find() throws Exception {
|
||||
|
||||
|
||||
ServiceReference<FeaturesService> ref = bundleContext.getServiceReference(FeaturesService.class);
|
||||
FeaturesService featuresService = bundleContext.getService(ref);
|
||||
|
||||
Feature[] featureArray =
|
||||
isInstalledOnly() ? featuresService.listInstalledFeatures() : featuresService.listFeatures();
|
||||
|
||||
List<Feature> features = Arrays.asList(featureArray);
|
||||
|
||||
if (bundle != null) {
|
||||
|
||||
ServiceReference<BundleService> ref0 = bundleContext.getServiceReference(BundleService.class);
|
||||
BundleService bundleService = bundleContext.getService(ref0);
|
||||
final String location = bundleService.getInfo(bundle).getUpdateLocation();
|
||||
bundleContext.ungetService(ref0);
|
||||
|
||||
features = features.stream().filter(
|
||||
f -> (f.getBundles().stream().filter(bi -> bi.getLocation().equals(location))
|
||||
.count() > 0))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
if (CommonUtils.isValid(capabilityNamespace)) {
|
||||
features = features.stream()
|
||||
.filter(f -> (new FeatureCapabilityHelper(f).isCapabilityProvided(capabilityNamespace)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
bundleContext.ungetService(ref);
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
public FeaturesUtils.FeaturesHelper bundleContext(BundleContext BundleContextValue) {
|
||||
this.setBundleContext(BundleContextValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FeaturesUtils.FeaturesHelper withCapabilityNamespace(String capabilityNamespaceValue) {
|
||||
this.setCapabilityNamespace(capabilityNamespaceValue);
|
||||
return this;
|
||||
};
|
||||
|
||||
public FeaturesUtils.FeaturesHelper installedOnly() {
|
||||
this.setInstalledOnly(true);
|
||||
return this;
|
||||
};
|
||||
|
||||
public FeaturesUtils.FeaturesHelper installedOnly(boolean InstalledOnlyValue) {
|
||||
this.setInstalledOnly(InstalledOnlyValue);
|
||||
return this;
|
||||
};
|
||||
|
||||
public FeaturesUtils.FeaturesHelper containingBundle(Bundle bundleValue) {
|
||||
this.setBundle(bundleValue);
|
||||
return this;
|
||||
};
|
||||
|
||||
public BundleContext getBundleContext() {
|
||||
return bundleContext;
|
||||
}
|
||||
|
||||
public void setBundleContext(BundleContext bundleContext) {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
public String getCapabilityNamespace() {
|
||||
return capabilityNamespace;
|
||||
}
|
||||
|
||||
public void setCapabilityNamespace(String capabilityNamespace) {
|
||||
this.capabilityNamespace = capabilityNamespace;
|
||||
}
|
||||
|
||||
public boolean isInstalledOnly() {
|
||||
return installedOnly;
|
||||
}
|
||||
|
||||
public void setInstalledOnly(boolean installedOnly) {
|
||||
this.installedOnly = installedOnly;
|
||||
}
|
||||
|
||||
public Bundle getBundle() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public void setBundle(Bundle bundle) {
|
||||
this.bundle = bundle;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* system-commons
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* system-commons
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* system-commons
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* system-commons
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* profile-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* profile-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* profile-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* profile-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* profile-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* profile-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime</groupId>
|
||||
<artifactId>base</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# ~~~~~~licensing~~~~~~
|
||||
# branding
|
||||
# ==========
|
||||
# Copyright (C) 2020 - 2024 EmDev LLC
|
||||
# Copyright (C) 2020 - 2025 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
|
||||
|
89
platform/runtime/base/cellar-extensions/pom.xml
Normal file
89
platform/runtime/base/cellar-extensions/pom.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<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.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
|
||||
<artifactId>cellar-extensions</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>ENTAXY :: PLATFORM :: BASE :: CELLAR EXTENSIONS</name>
|
||||
<description>ENTAXY :: PLATFORM :: BASE :: CELLAR EXTENSIONS</description>
|
||||
|
||||
<properties>
|
||||
<bundle.osgi.export.pkg>
|
||||
ru.entaxy.platform.runtime.cellar.helper,
|
||||
ru.entaxy.platform.runtime.cellar.sequence
|
||||
</bundle.osgi.export.pkg>
|
||||
<bundle.osgi.private.pkg>
|
||||
org.apache.karaf.features.internal.model,
|
||||
org.apache.felix.utils.version,
|
||||
org.apache.felix.utils.properties,
|
||||
org.apache.karaf.util,
|
||||
ru.entaxy.platform.runtime.cellar.sequence.process,
|
||||
ru.entaxy.platform.runtime.cellar.sequence.impl
|
||||
</bundle.osgi.private.pkg>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>org.apache.felix.configadmin</artifactId>
|
||||
<version>${felix.configadmin.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.compendium</artifactId>
|
||||
<version>${osgi.compendium.version}</version>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.karaf.features</groupId>
|
||||
<artifactId>org.apache.karaf.features.core</artifactId>
|
||||
<version>${karaf.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
|
||||
<artifactId>base-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.karaf.shell</groupId>
|
||||
<artifactId>org.apache.karaf.shell.core</artifactId>
|
||||
</exclusion>
|
||||
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.karaf</groupId>
|
||||
<artifactId>org.apache.karaf.util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.karaf.cellar</groupId>
|
||||
<artifactId>org.apache.karaf.cellar.core</artifactId>
|
||||
<version>${cellar.version}</version>
|
||||
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.karaf.cellar</groupId>
|
||||
<artifactId>org.apache.karaf.cellar.event</artifactId>
|
||||
<version>${cellar.version}</version>
|
||||
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.karaf.cellar</groupId>
|
||||
<artifactId>org.apache.karaf.cellar.features</artifactId>
|
||||
<version>${cellar.version}</version>
|
||||
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,738 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package ru.entaxy.platform.runtime.cellar.helper;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.CompositeDataSupport;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.OpenType;
|
||||
import javax.management.openmbean.SimpleType;
|
||||
import javax.management.openmbean.TabularData;
|
||||
import javax.management.openmbean.TabularDataSupport;
|
||||
import javax.management.openmbean.TabularType;
|
||||
|
||||
// import org.apache.karaf.cellar.bundle.BundleState;
|
||||
import org.apache.karaf.cellar.core.CellarSupport;
|
||||
import org.apache.karaf.cellar.core.ClusterManager;
|
||||
import org.apache.karaf.cellar.core.Configurations;
|
||||
import org.apache.karaf.cellar.core.Group;
|
||||
import org.apache.karaf.cellar.core.GroupManager;
|
||||
import org.apache.karaf.cellar.core.control.SwitchStatus;
|
||||
import org.apache.karaf.cellar.core.event.EventProducer;
|
||||
import org.apache.karaf.cellar.core.event.EventType;
|
||||
import org.apache.karaf.cellar.features.ClusterFeaturesEvent;
|
||||
import org.apache.karaf.cellar.features.ClusterRepositoryEvent;
|
||||
import org.apache.karaf.cellar.features.Constants;
|
||||
import org.apache.karaf.cellar.features.FeatureState;
|
||||
import org.apache.karaf.cellar.features.management.CellarFeaturesMBean;
|
||||
import org.apache.karaf.features.Feature;
|
||||
import org.apache.karaf.features.FeatureEvent;
|
||||
import org.apache.karaf.features.FeaturesService;
|
||||
import org.apache.karaf.features.RepositoryEvent;
|
||||
// import org.osgi.framework.BundleEvent;
|
||||
import org.apache.karaf.features.internal.model.Features;
|
||||
import org.apache.karaf.features.internal.model.JaxbUtil;
|
||||
import org.osgi.service.cm.ConfigurationAdmin;
|
||||
|
||||
/**
|
||||
* Implementation of the Cellar Features MBean.
|
||||
*/
|
||||
public class CellarFeaturesHelper implements CellarFeaturesMBean {
|
||||
|
||||
private ClusterManager clusterManager;
|
||||
private GroupManager groupManager;
|
||||
private EventProducer eventProducer;
|
||||
private FeaturesService featuresService;
|
||||
private ConfigurationAdmin configurationAdmin;
|
||||
|
||||
public CellarFeaturesHelper() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ClusterManager getClusterManager() {
|
||||
return this.clusterManager;
|
||||
}
|
||||
|
||||
public void setClusterManager(ClusterManager clusterManager) {
|
||||
this.clusterManager = clusterManager;
|
||||
}
|
||||
|
||||
public GroupManager getGroupManager() {
|
||||
return this.groupManager;
|
||||
}
|
||||
|
||||
public void setGroupManager(GroupManager groupManager) {
|
||||
this.groupManager = groupManager;
|
||||
}
|
||||
|
||||
public EventProducer getEventProducer() {
|
||||
return eventProducer;
|
||||
}
|
||||
|
||||
public void setEventProducer(EventProducer eventProducer) {
|
||||
this.eventProducer = eventProducer;
|
||||
}
|
||||
|
||||
public FeaturesService getFeaturesService() {
|
||||
return featuresService;
|
||||
}
|
||||
|
||||
public void setFeaturesService(FeaturesService featuresService) {
|
||||
this.featuresService = featuresService;
|
||||
}
|
||||
|
||||
public ConfigurationAdmin getConfigurationAdmin() {
|
||||
return configurationAdmin;
|
||||
}
|
||||
|
||||
public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
|
||||
this.configurationAdmin = configurationAdmin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installFeature(String groupName, String name, String version, boolean noRefresh, boolean noStart,
|
||||
boolean noManage, boolean upgrade) throws Exception {
|
||||
// check if the group exists
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
// check if the producer is ON
|
||||
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
|
||||
throw new IllegalStateException("Cluster event producer is OFF");
|
||||
}
|
||||
|
||||
// check if the feature is allowed outbound
|
||||
CellarSupport support = new CellarSupport();
|
||||
support.setClusterManager(this.clusterManager);
|
||||
support.setGroupManager(this.groupManager);
|
||||
support.setConfigurationAdmin(this.configurationAdmin);
|
||||
if (!support.isAllowed(group, Constants.CATEGORY, name, EventType.OUTBOUND)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Feature " + name + " is blocked outbound for cluster group " + groupName);
|
||||
}
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
try {
|
||||
|
||||
// get the features in the cluster group
|
||||
Map<String, FeatureState> clusterFeatures =
|
||||
clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
|
||||
|
||||
// check if the feature exist
|
||||
FeatureState feature = null;
|
||||
String key = null;
|
||||
|
||||
String targetKey = null;
|
||||
|
||||
// collect features to remove if upgrade = true
|
||||
List<String> featuresToRemove = new ArrayList<>();
|
||||
|
||||
for (String k : clusterFeatures.keySet()) {
|
||||
FeatureState state = clusterFeatures.get(k);
|
||||
key = k;
|
||||
if (version == null) {
|
||||
if (state.getName().equals(name)) {
|
||||
feature = state;
|
||||
targetKey = key;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (state.getName().equals(name)) {
|
||||
if (state.getVersion().equals(version)) {
|
||||
feature = state;
|
||||
targetKey = key;
|
||||
if (!upgrade)
|
||||
break;
|
||||
} else if (upgrade)
|
||||
featuresToRemove.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feature == null) {
|
||||
if (version == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Feature " + name + " doesn't exist in cluster group " + groupName);
|
||||
else
|
||||
throw new IllegalArgumentException(
|
||||
"Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName);
|
||||
}
|
||||
|
||||
// update the cluster group
|
||||
|
||||
// set previous features uninstalled if we upgrade
|
||||
// actual uninstallation will be executed on end nodes
|
||||
if (upgrade) {
|
||||
for (String featureKey : featuresToRemove) {
|
||||
FeatureState fs = clusterFeatures.get(featureKey);
|
||||
fs.setInstalled(false);
|
||||
clusterFeatures.put(featureKey, fs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set current feature installed
|
||||
feature.setInstalled(true);
|
||||
clusterFeatures.put(targetKey, feature);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
|
||||
// broadcast the cluster event
|
||||
ClusterFeaturesEvent event = new ClusterFeaturesEvent(name, version, noRefresh, noStart, noManage, upgrade,
|
||||
FeatureEvent.EventType.FeatureInstalled);
|
||||
event.setSourceGroup(group);
|
||||
eventProducer.produce(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installFeature(String groupName, String name, String version) throws Exception {
|
||||
this.installFeature(groupName, name, version, false, false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installFeature(String groupName, String name) throws Exception {
|
||||
this.installFeature(groupName, name, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void installFeature(String groupName, String name, boolean noRefresh, boolean noStart, boolean noManage,
|
||||
boolean upgrade) throws Exception {
|
||||
this.installFeature(groupName, name, null, noRefresh, noStart, noManage, upgrade);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallFeature(String groupName, String name, String version) throws Exception {
|
||||
this.uninstallFeature(groupName, name, version, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallFeature(String groupName, String name, String version, boolean noRefresh) throws Exception {
|
||||
// check if the group exists
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
// check if the producer is ON
|
||||
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
|
||||
throw new IllegalStateException("Cluster event producer is OFF");
|
||||
}
|
||||
|
||||
// check if the feature is allowed outbound
|
||||
CellarSupport support = new CellarSupport();
|
||||
support.setClusterManager(this.clusterManager);
|
||||
support.setGroupManager(this.groupManager);
|
||||
support.setConfigurationAdmin(this.configurationAdmin);
|
||||
if (!support.isAllowed(group, Constants.CATEGORY, name, EventType.OUTBOUND)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Feature " + name + " is blocked outbound for cluster group " + groupName);
|
||||
}
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
try {
|
||||
|
||||
// get the features in the cluster group
|
||||
Map<String, FeatureState> clusterFeatures =
|
||||
clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
|
||||
|
||||
// check if the feature exist
|
||||
FeatureState feature = null;
|
||||
String key = null;
|
||||
for (String k : clusterFeatures.keySet()) {
|
||||
FeatureState state = clusterFeatures.get(k);
|
||||
key = k;
|
||||
if (version == null) {
|
||||
if (state.getName().equals(name)) {
|
||||
feature = state;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (state.getName().equals(name) && state.getVersion().equals(version)) {
|
||||
feature = state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feature == null) {
|
||||
if (version == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Feature " + name + " doesn't exist in cluster group " + groupName);
|
||||
else
|
||||
throw new IllegalArgumentException(
|
||||
"Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName);
|
||||
}
|
||||
|
||||
// update the cluster group
|
||||
feature.setInstalled(false);
|
||||
clusterFeatures.put(key, feature);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
|
||||
// broadcast the cluster event
|
||||
ClusterFeaturesEvent event = new ClusterFeaturesEvent(name, version, noRefresh, false, false, false,
|
||||
FeatureEvent.EventType.FeatureUninstalled);
|
||||
event.setSourceGroup(group);
|
||||
eventProducer.produce(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallFeature(String groupName, String name) throws Exception {
|
||||
this.uninstallFeature(groupName, name, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallFeature(String groupName, String name, boolean noRefresh) throws Exception {
|
||||
this.uninstallFeature(groupName, name, null, noRefresh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabularData getFeatures(String groupName) throws Exception {
|
||||
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
CellarSupport support = new CellarSupport();
|
||||
support.setClusterManager(clusterManager);
|
||||
support.setGroupManager(groupManager);
|
||||
support.setConfigurationAdmin(configurationAdmin);
|
||||
|
||||
CompositeType featuresType = new CompositeType("Feature", "Karaf Cellar feature",
|
||||
new String[] {"name", "version", "installed", "located", "blocked"},
|
||||
new String[] {"Name of the feature", "Version of the feature",
|
||||
"Whether the feature is installed or not",
|
||||
"Location of the feature (on the cluster or the local node)",
|
||||
"Feature block policy"},
|
||||
new OpenType[] {SimpleType.STRING, SimpleType.STRING, SimpleType.BOOLEAN, SimpleType.STRING,
|
||||
SimpleType.STRING});
|
||||
|
||||
TabularType tabularType = new TabularType("Features", "Table of all Karaf Cellar features",
|
||||
featuresType, new String[] {"name", "version"});
|
||||
TabularData table = new TabularDataSupport(tabularType);
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
try {
|
||||
Map<String, ExtendedFeatureState> features = gatherFeatures(groupName);
|
||||
if (features != null && !features.isEmpty()) {
|
||||
for (ExtendedFeatureState feature : features.values()) {
|
||||
|
||||
String located = "";
|
||||
boolean cluster = feature.isCluster();
|
||||
boolean local = feature.isLocal();
|
||||
if (cluster && local)
|
||||
located = "cluster/local";
|
||||
if (cluster && !local)
|
||||
located = "cluster";
|
||||
if (local && !cluster)
|
||||
located = "local";
|
||||
|
||||
String blocked = "";
|
||||
boolean inbound =
|
||||
support.isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.INBOUND);
|
||||
boolean outbound =
|
||||
support.isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND);
|
||||
if (!inbound && !outbound)
|
||||
blocked = "in/out";
|
||||
if (!inbound && outbound)
|
||||
blocked = "in";
|
||||
if (!outbound && inbound)
|
||||
blocked = "out";
|
||||
|
||||
CompositeData data = new CompositeDataSupport(featuresType,
|
||||
new String[] {"name", "version", "installed", "located", "blocked"},
|
||||
new Object[] {feature.getName(), feature.getVersion(), feature.getInstalled(), located,
|
||||
blocked});
|
||||
table.put(data);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
private Map<String, ExtendedFeatureState> gatherFeatures(String groupName) throws Exception {
|
||||
Map<String, ExtendedFeatureState> features = new HashMap<String, ExtendedFeatureState>();
|
||||
|
||||
// get cluster features
|
||||
Map<String, FeatureState> clusterFeatures =
|
||||
clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
|
||||
for (String key : clusterFeatures.keySet()) {
|
||||
FeatureState state = clusterFeatures.get(key);
|
||||
ExtendedFeatureState extendedState = new ExtendedFeatureState();
|
||||
extendedState.setName(state.getName());
|
||||
extendedState.setInstalled(state.getInstalled());
|
||||
extendedState.setVersion(state.getVersion());
|
||||
extendedState.setCluster(true);
|
||||
extendedState.setLocal(true);
|
||||
features.put(key, extendedState);
|
||||
}
|
||||
|
||||
// get local features
|
||||
for (Feature feature : featuresService.listFeatures()) {
|
||||
String key = feature.getName() + "/" + feature.getVersion();
|
||||
if (features.containsKey(key)) {
|
||||
ExtendedFeatureState extendedState = features.get(key);
|
||||
if (featuresService.isInstalled(feature))
|
||||
extendedState.setInstalled(true);
|
||||
extendedState.setLocal(true);
|
||||
} else {
|
||||
ExtendedFeatureState extendedState = new ExtendedFeatureState();
|
||||
extendedState.setCluster(false);
|
||||
extendedState.setLocal(true);
|
||||
extendedState.setName(feature.getName());
|
||||
extendedState.setVersion(feature.getVersion());
|
||||
if (featuresService.isInstalled(feature))
|
||||
extendedState.setInstalled(true);
|
||||
else
|
||||
extendedState.setInstalled(false);
|
||||
features.put(key, extendedState);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRepositories(String groupName) throws Exception {
|
||||
// check if the group exists
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
// get the features repositories in the cluster group
|
||||
Map<String, String> clusterRepositories =
|
||||
clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
|
||||
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String clusterRepository : clusterRepositories.keySet()) {
|
||||
result.add(clusterRepository);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRepository(String groupName, String nameOrUrl) throws Exception {
|
||||
this.addRepository(groupName, nameOrUrl, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRepository(String groupName, String nameOrUrl, String version) throws Exception {
|
||||
this.addRepository(groupName, nameOrUrl, version, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRepository(String groupName, String nameOrUrl, String version, boolean install) throws Exception {
|
||||
// check if the group exists
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
// check if the event producer is ON
|
||||
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
|
||||
throw new IllegalStateException("Cluster event producer is OFF");
|
||||
}
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
try {
|
||||
// get the features repositories in the cluster group
|
||||
Map<String, String> clusterRepositories =
|
||||
clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
|
||||
// get the features in the cluster group
|
||||
Map<String, FeatureState> clusterFeatures =
|
||||
clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
|
||||
|
||||
URI uri = featuresService.getRepositoryUriFor(nameOrUrl, version);
|
||||
if (uri == null) {
|
||||
uri = new URI(nameOrUrl);
|
||||
}
|
||||
|
||||
// check if the URL is already registered
|
||||
String name = null;
|
||||
for (String repository : clusterRepositories.keySet()) {
|
||||
if (repository.equals(uri)) {
|
||||
name = clusterRepositories.get(repository);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
// parsing the features repository to get content
|
||||
Features repository = JaxbUtil.unmarshal(uri.toASCIIString(), true);
|
||||
|
||||
// update the cluster group
|
||||
clusterRepositories.put(uri.toString(), repository.getName());
|
||||
|
||||
// update the features in the cluster group
|
||||
for (Feature feature : repository.getFeature()) {
|
||||
FeatureState state = new FeatureState();
|
||||
state.setName(feature.getName());
|
||||
state.setVersion(feature.getVersion());
|
||||
state.setInstalled(featuresService.isInstalled(feature));
|
||||
clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), state);
|
||||
}
|
||||
|
||||
// broadcast the cluster event
|
||||
ClusterRepositoryEvent event =
|
||||
new ClusterRepositoryEvent(uri.toString(), RepositoryEvent.EventType.RepositoryAdded);
|
||||
event.setInstall(install);
|
||||
event.setSourceGroup(group);
|
||||
event.setSourceNode(clusterManager.getNode());
|
||||
eventProducer.produce(event);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Features repository URL " + uri + " already registered");
|
||||
}
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshRepository(String groupName, String nameOrUrl) throws Exception {
|
||||
// check if the group exists
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
// check if the event producer is ON
|
||||
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
|
||||
throw new IllegalStateException("Cluster event producer is OFF");
|
||||
}
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
try {
|
||||
String uri = null;
|
||||
if (nameOrUrl != null) {
|
||||
// get the cluster features repositories
|
||||
Map<String, String> clusterFeaturesRepositories =
|
||||
clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
|
||||
|
||||
for (Map.Entry<String, String> entry : clusterFeaturesRepositories.entrySet()) {
|
||||
if (entry.getKey().equals(nameOrUrl) || entry.getValue().equals(nameOrUrl)) {
|
||||
uri = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Features repository " + nameOrUrl + " doesn't exist in cluster group " + groupName);
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast the cluster event
|
||||
ClusterRepositoryEvent event = new ClusterRepositoryEvent(uri, RepositoryEvent.EventType.RepositoryAdded);
|
||||
event.setRefresh(true);
|
||||
event.setSourceGroup(group);
|
||||
event.setSourceNode(clusterManager.getNode());
|
||||
eventProducer.produce(event);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRepository(String groupName, String repository) throws Exception {
|
||||
this.removeRepository(groupName, repository, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRepository(String groupName, String repo, boolean uninstall) throws Exception {
|
||||
// check if the group exists
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
// check if the event producer is ON
|
||||
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
|
||||
throw new IllegalStateException("Cluster event producer is OFF");
|
||||
}
|
||||
|
||||
// get the features repositories in the cluster group
|
||||
Map<String, String> clusterRepositories =
|
||||
clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
|
||||
// get the features in the cluster group
|
||||
Map<FeatureState, Boolean> clusterFeatures =
|
||||
clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
|
||||
List<String> urls = new ArrayList<String>();
|
||||
Pattern pattern = Pattern.compile(repo);
|
||||
for (String repositoryUrl : clusterRepositories.keySet()) {
|
||||
String repositoryName = clusterRepositories.get(repositoryUrl);
|
||||
if (repositoryName != null && !repositoryName.isEmpty()) {
|
||||
// repository has name, try regex on the name
|
||||
Matcher nameMatcher = pattern.matcher(repositoryName);
|
||||
if (nameMatcher.matches()) {
|
||||
urls.add(repositoryUrl);
|
||||
} else {
|
||||
// the name regex doesn't match, fallback to repository URI regex
|
||||
Matcher uriMatcher = pattern.matcher(repositoryUrl);
|
||||
if (uriMatcher.matches()) {
|
||||
urls.add(repositoryUrl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the repository name is not defined, use repository URI regex
|
||||
Matcher uriMatcher = pattern.matcher(repositoryUrl);
|
||||
if (uriMatcher.matches()) {
|
||||
urls.add(repositoryUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String url : urls) {
|
||||
// looking for the URL in the list
|
||||
boolean found = false;
|
||||
for (String repository : clusterRepositories.keySet()) {
|
||||
if (repository.equals(url)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
Features repositoryModel = JaxbUtil.unmarshal(url, true);
|
||||
|
||||
// update the features repositories in the cluster group
|
||||
clusterRepositories.remove(url);
|
||||
|
||||
// update the features in the cluster group
|
||||
for (Feature feature : repositoryModel.getFeature()) {
|
||||
clusterFeatures.remove(feature.getName() + "/" + feature.getVersion());
|
||||
}
|
||||
|
||||
// broadcast a cluster event
|
||||
ClusterRepositoryEvent event =
|
||||
new ClusterRepositoryEvent(url, RepositoryEvent.EventType.RepositoryRemoved);
|
||||
event.setUninstall(uninstall);
|
||||
event.setSourceGroup(group);
|
||||
event.setSourceNode(clusterManager.getNode());
|
||||
eventProducer.produce(event);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Features repository URL " + url + " not found in cluster group " + groupName);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void block(String groupName, String featurePattern, boolean whitelist, boolean blacklist, boolean in,
|
||||
boolean out) throws Exception {
|
||||
|
||||
Group group = groupManager.findGroupByName(groupName);
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
|
||||
}
|
||||
|
||||
CellarSupport support = new CellarSupport();
|
||||
support.setClusterManager(clusterManager);
|
||||
support.setGroupManager(groupManager);
|
||||
support.setConfigurationAdmin(configurationAdmin);
|
||||
|
||||
if (in) {
|
||||
if (whitelist)
|
||||
support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND,
|
||||
featurePattern);
|
||||
if (blacklist)
|
||||
support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND,
|
||||
featurePattern);
|
||||
}
|
||||
if (out) {
|
||||
if (whitelist)
|
||||
support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND,
|
||||
featurePattern);
|
||||
if (blacklist)
|
||||
support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND,
|
||||
featurePattern);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ExtendedFeatureState extends FeatureState {
|
||||
|
||||
private boolean cluster;
|
||||
private boolean local;
|
||||
|
||||
public boolean isCluster() {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
public void setCluster(boolean cluster) {
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
public void setLocal(boolean local) {
|
||||
this.local = local;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.helper;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.karaf.cellar.core.ClusterManager;
|
||||
import org.apache.karaf.cellar.core.GroupManager;
|
||||
import org.apache.karaf.cellar.core.event.EventProducer;
|
||||
import org.apache.karaf.cellar.features.management.CellarFeaturesMBean;
|
||||
import org.apache.karaf.features.FeaturesService;
|
||||
import org.osgi.service.cm.ConfigurationAdmin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HelperFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HelperFactory.class);
|
||||
|
||||
public static <T> T createHelper(Class<T> targetClass) {
|
||||
|
||||
return createHelper(targetClass, Collections.emptyMap());
|
||||
|
||||
}
|
||||
|
||||
public static <T> T createHelper(Class<T> targetClass, Map<Object, Object> parameters) {
|
||||
|
||||
if (CellarFeaturesMBean.class.equals(targetClass))
|
||||
return (T) createFeaturesHelper(parameters);
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected static CellarFeaturesHelper createFeaturesHelper(Map<Object, Object> parameters) {
|
||||
CellarFeaturesHelper result = new CellarFeaturesHelper();
|
||||
|
||||
if (parameters.containsKey(ClusterManager.class.getName()))
|
||||
result.setClusterManager((ClusterManager) parameters.get(ClusterManager.class.getName()));
|
||||
else if (Services.INSTANCE != null)
|
||||
result.setClusterManager(Services.INSTANCE.clusterManager);
|
||||
|
||||
if (parameters.containsKey(ConfigurationAdmin.class.getName()))
|
||||
result.setConfigurationAdmin((ConfigurationAdmin) parameters.get(ConfigurationAdmin.class.getName()));
|
||||
else if (Services.INSTANCE != null)
|
||||
result.setConfigurationAdmin(Services.INSTANCE.configurationAdmin);
|
||||
|
||||
if (parameters.containsKey(EventProducer.class.getName()))
|
||||
result.setEventProducer((EventProducer) parameters.get(EventProducer.class.getName()));
|
||||
else if (Services.INSTANCE != null)
|
||||
result.setEventProducer(Services.INSTANCE.eventProducer);
|
||||
|
||||
if (parameters.containsKey(FeaturesService.class.getName()))
|
||||
result.setFeaturesService((FeaturesService) parameters.get(FeaturesService.class.getName()));
|
||||
else if (Services.INSTANCE != null)
|
||||
result.setFeaturesService(Services.INSTANCE.featuresService);
|
||||
|
||||
if (parameters.containsKey(GroupManager.class.getName()))
|
||||
result.setGroupManager((GroupManager) parameters.get(GroupManager.class.getName()));
|
||||
else if (Services.INSTANCE != null)
|
||||
result.setGroupManager(Services.INSTANCE.groupManager);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.helper;
|
||||
|
||||
import org.apache.karaf.cellar.core.ClusterManager;
|
||||
import org.apache.karaf.cellar.core.GroupManager;
|
||||
import org.apache.karaf.cellar.core.event.EventProducer;
|
||||
import org.apache.karaf.features.FeaturesService;
|
||||
import org.osgi.service.cm.ConfigurationAdmin;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
|
||||
@Component(service = Services.class, immediate = true)
|
||||
public class Services {
|
||||
|
||||
public static Services INSTANCE = null;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
|
||||
public volatile ClusterManager clusterManager;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
|
||||
public volatile ConfigurationAdmin configurationAdmin;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
|
||||
public volatile EventProducer eventProducer;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
|
||||
public volatile FeaturesService featuresService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
|
||||
public volatile GroupManager groupManager;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
INSTANCE = this;
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
INSTANCE = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.karaf.cellar.core.event.Event;
|
||||
|
||||
public class CellarSequenceEvent extends Event implements Serializable {
|
||||
|
||||
List<CellarSequenceItemEvent> sequence = new ArrayList<>();
|
||||
|
||||
boolean waitLast = true;
|
||||
|
||||
public CellarSequenceEvent(String sequenceId) {
|
||||
super(sequenceId);
|
||||
}
|
||||
|
||||
public List<CellarSequenceItemEvent> getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public boolean isWaitLast() {
|
||||
return waitLast;
|
||||
}
|
||||
|
||||
public void setWaitLast(boolean waitLast) {
|
||||
this.waitLast = waitLast;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence;
|
||||
|
||||
import org.apache.karaf.cellar.core.event.Event;
|
||||
|
||||
public class CellarSequenceItemEvent extends Event {
|
||||
|
||||
Event event;
|
||||
|
||||
// -1 - infinite
|
||||
// 0 - don't wait
|
||||
// x - time in mills
|
||||
int operationTimeout = -1;
|
||||
|
||||
public CellarSequenceItemEvent(String id, Event event) {
|
||||
super(id);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public Event getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public int getOperationTimeout() {
|
||||
return operationTimeout;
|
||||
}
|
||||
|
||||
public void setOperationTimeout(int operationTimeout) {
|
||||
this.operationTimeout = operationTimeout;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence;
|
||||
|
||||
public interface CellarSequenceManager {
|
||||
|
||||
void releaseSequence(String sequenceId);
|
||||
|
||||
void produceSequence(String sequenceId);
|
||||
|
||||
<T> T getSequencedHelper(String sequenceId, Class<T> targetClass);
|
||||
|
||||
SequenceBuilder getSequence(String sequenceId);
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence;
|
||||
|
||||
import org.apache.karaf.cellar.core.control.BasicSwitch;
|
||||
import org.apache.karaf.cellar.core.control.Switch;
|
||||
import org.apache.karaf.cellar.core.event.Event;
|
||||
import org.apache.karaf.cellar.core.event.EventProducer;
|
||||
|
||||
public class SequenceBuilder<E extends Event> implements EventProducer<E> {
|
||||
|
||||
protected CellarSequenceEvent cellarSequenceEvent;
|
||||
|
||||
protected Switch eventSwitch = new BasicSwitch(getClass().getName());
|
||||
|
||||
public SequenceBuilder(String sequenceId) {
|
||||
super();
|
||||
this.cellarSequenceEvent = new CellarSequenceEvent(sequenceId);
|
||||
}
|
||||
|
||||
public CellarSequenceEvent getEvent() {
|
||||
return cellarSequenceEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Switch getSwitch() {
|
||||
return eventSwitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void produce(Event event) {
|
||||
|
||||
cellarSequenceEvent.sequence.add(new CellarSequenceItemEvent(event.getId(), event));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.apache.karaf.cellar.core.control.BasicSwitch;
|
||||
import org.apache.karaf.cellar.core.control.Switch;
|
||||
import org.apache.karaf.cellar.core.event.EventHandler;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.runtime.cellar.sequence.process.SequenceTask;
|
||||
|
||||
@Component(service = EventHandler.class, immediate = true)
|
||||
public class SequenceEventHandler implements EventHandler<CellarSequenceEvent> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SequenceEventHandler.class);
|
||||
|
||||
protected Switch eventSwitch = new BasicSwitch(getClass().getName());
|
||||
|
||||
protected ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
|
||||
@Override
|
||||
public Class<CellarSequenceEvent> getType() {
|
||||
return CellarSequenceEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Switch getSwitch() {
|
||||
return eventSwitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(CellarSequenceEvent event) {
|
||||
LOG.info("Received event: " + event.getId());
|
||||
threadPool.execute(new SequenceTask(event, Thread.currentThread().getContextClassLoader()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.karaf.cellar.core.event.EventProducer;
|
||||
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 ru.entaxy.platform.runtime.cellar.helper.HelperFactory;
|
||||
import ru.entaxy.platform.runtime.cellar.sequence.CellarSequenceManager;
|
||||
import ru.entaxy.platform.runtime.cellar.sequence.SequenceBuilder;
|
||||
|
||||
@Component(service = CellarSequenceManager.class, immediate = true)
|
||||
public class CellarSequenceManagerImpl implements CellarSequenceManager {
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
|
||||
protected volatile EventProducer eventProducer;
|
||||
|
||||
protected final Map<String, SequenceBuilder> sequences = new HashMap<>();
|
||||
protected Object sequencesLock = new Object();
|
||||
|
||||
@Override
|
||||
public <T> T getSequencedHelper(String sequenceId, Class<T> targetClass) {
|
||||
|
||||
Map<Object, Object> properties = new HashMap<>();
|
||||
properties.put(EventProducer.class.getName(), getSequenceBuilder(sequenceId));
|
||||
|
||||
return HelperFactory.createHelper(targetClass, properties);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void produceSequence(String sequenceId) {
|
||||
synchronized (sequencesLock) {
|
||||
if (sequences.containsKey(sequenceId))
|
||||
eventProducer.produce(sequences.get(sequenceId).getEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseSequence(String sequenceId) {
|
||||
synchronized (sequencesLock) {
|
||||
sequences.remove(sequenceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceBuilder getSequence(String sequenceId) {
|
||||
return getSequenceBuilder(sequenceId);
|
||||
}
|
||||
|
||||
protected SequenceBuilder getSequenceBuilder(String sequenceId) {
|
||||
synchronized (sequencesLock) {
|
||||
if (!sequences.containsKey(sequenceId))
|
||||
sequences.put(sequenceId, new SequenceBuilder(sequenceId));
|
||||
return sequences.get(sequenceId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence.process;
|
||||
|
||||
public interface ChangeListener {
|
||||
|
||||
public interface CallBack {
|
||||
void success();
|
||||
|
||||
default void fail() {};
|
||||
|
||||
default void timeout() {};
|
||||
}
|
||||
|
||||
void setCallback(CallBack callBack);
|
||||
|
||||
void register();
|
||||
|
||||
void unregister();
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence.process;
|
||||
|
||||
import org.apache.karaf.cellar.core.event.Event;
|
||||
import org.apache.karaf.cellar.features.ClusterFeaturesEvent;
|
||||
import org.apache.karaf.cellar.features.ClusterRepositoryEvent;
|
||||
import org.apache.karaf.features.FeatureEvent;
|
||||
import org.apache.karaf.features.FeaturesListener;
|
||||
import org.apache.karaf.features.RepositoryEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.runtime.cellar.helper.Services;
|
||||
|
||||
public class ChangeListenerFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ChangeListenerFactory.class);
|
||||
|
||||
public static ChangeListener create(Event originEvent) {
|
||||
|
||||
if (originEvent instanceof ClusterRepositoryEvent) {
|
||||
return new RepositoryListener((ClusterRepositoryEvent) originEvent);
|
||||
}
|
||||
|
||||
if (originEvent instanceof ClusterFeaturesEvent) {
|
||||
return new FeatureListener((ClusterFeaturesEvent) originEvent);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static abstract class AbstractChangeListener<T extends Event> implements ChangeListener {
|
||||
|
||||
protected CallBack callBack;
|
||||
|
||||
protected T originEvent;
|
||||
|
||||
public AbstractChangeListener(T event) {
|
||||
super();
|
||||
this.originEvent = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCallback(CallBack callBack) {
|
||||
this.callBack = callBack;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class RepositoryListener extends AbstractChangeListener<ClusterRepositoryEvent>
|
||||
implements FeaturesListener {
|
||||
|
||||
public RepositoryListener(ClusterRepositoryEvent event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Services.INSTANCE.featuresService.registerListener(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
Services.INSTANCE.featuresService.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void featureEvent(FeatureEvent event) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repositoryEvent(RepositoryEvent event) {
|
||||
if (event.getRepository().getURI().toString().equals(originEvent.getId())) {
|
||||
if (originEvent.getType().equals(event.getType())) {
|
||||
LOG.debug("REPOSITORY EVENT for [{}]", originEvent.getId());
|
||||
callBack.success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
protected static class FeatureListener extends AbstractChangeListener<ClusterFeaturesEvent>
|
||||
implements FeaturesListener {
|
||||
|
||||
public FeatureListener(ClusterFeaturesEvent event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Services.INSTANCE.featuresService.registerListener(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
Services.INSTANCE.featuresService.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void featureEvent(FeatureEvent event) {
|
||||
if (event.getFeature().getId().equals(originEvent.getId())) {
|
||||
if (originEvent.getType().equals(event.getType())) {
|
||||
LOG.debug("FEATURE EVENT for [{}]", originEvent.getId());
|
||||
callBack.success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repositoryEvent(RepositoryEvent event) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* cellar-extensions
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.runtime.cellar.sequence.process;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.apache.karaf.cellar.core.event.Event;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.runtime.cellar.helper.Services;
|
||||
import ru.entaxy.platform.runtime.cellar.sequence.CellarSequenceEvent;
|
||||
import ru.entaxy.platform.runtime.cellar.sequence.CellarSequenceItemEvent;
|
||||
|
||||
public class SequenceTask implements Runnable, ChangeListener.CallBack {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SequenceTask.class);
|
||||
|
||||
protected enum EVENT_RESULT {
|
||||
NONE,
|
||||
SUCCESS,
|
||||
ERROR,
|
||||
TIMEOUT
|
||||
}
|
||||
|
||||
protected CellarSequenceEvent sequence;
|
||||
|
||||
protected ArrayDeque<CellarSequenceItemEvent> events;
|
||||
|
||||
protected Object eventsLock = new Object();
|
||||
|
||||
protected CellarSequenceItemEvent currentEvent;
|
||||
|
||||
protected ChangeListener currentChangeListener;
|
||||
|
||||
protected Object currentChangeListenerLock = new Object();
|
||||
|
||||
protected ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
|
||||
protected Future<Object> future;
|
||||
|
||||
protected Object futureLock = new Object();
|
||||
|
||||
protected EVENT_RESULT currentResult;
|
||||
|
||||
protected Object currentResultLock = new Object();
|
||||
|
||||
public SequenceTask(CellarSequenceEvent event, ClassLoader classLoader) {
|
||||
super();
|
||||
this.sequence = event;
|
||||
events = new ArrayDeque<>(this.sequence.getSequence());
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
LOG.debug("\n--> CREATED SequenceTask for [{}]", sequence.getId());
|
||||
}
|
||||
|
||||
protected void updateCurrentResult(EVENT_RESULT newResult) {
|
||||
synchronized (currentResultLock) {
|
||||
LOG.debug("\n--> CURRENT RESULT set to [{}]", newResult.name());
|
||||
this.currentResult = newResult;
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetResult() {
|
||||
updateCurrentResult(EVENT_RESULT.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
LOG.debug("\n--> RUNNING SequenceTask for [{}]", sequence.getId());
|
||||
|
||||
resetResult();
|
||||
|
||||
// global limit for operation = 5 min
|
||||
long maxExecution = 300000;
|
||||
long executionStep = 500;
|
||||
|
||||
while (!events.isEmpty()) {
|
||||
next();
|
||||
long executionPeriod = 0;
|
||||
while (EVENT_RESULT.NONE.equals(currentResult) && (executionPeriod < maxExecution)) {
|
||||
try {
|
||||
LOG.debug("\n--> WAITING FOR RESULT [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
executionPeriod += executionStep;
|
||||
Thread.sleep(executionStep);
|
||||
} catch (InterruptedException e) {
|
||||
LOG.debug("\n--> INTERRUPTED WAITING FOR RESULT [{}]",
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
updateCurrentResult(EVENT_RESULT.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// maxExecution reached
|
||||
if (EVENT_RESULT.NONE.equals(currentResult)) {
|
||||
LOG.debug("\n--> CURRENT RESULT is NONE for [{}]",
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
updateCurrentResult(EVENT_RESULT.ERROR);
|
||||
}
|
||||
|
||||
if (EVENT_RESULT.SUCCESS.equals(currentResult)) {
|
||||
LOG.debug("\n--> CURRENT RESULT is SUCCESS for [{}]",
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
resetResult();
|
||||
} else {
|
||||
LOG.debug("\n--> CURRENT RESULT is [{}] for [{}]",
|
||||
currentResult == null ? "null" : currentResult.name(),
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
LOG.error("Failed processing sequence event");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected boolean haveToWait() {
|
||||
if (events.isEmpty() && !sequence.isWaitLast())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void next() {
|
||||
synchronized (eventsLock) {
|
||||
LOG.debug("\n--> NEXT event");
|
||||
currentEvent = null;
|
||||
currentChangeListener = null;
|
||||
|
||||
if (events.isEmpty())
|
||||
return;
|
||||
|
||||
currentEvent = events.pop();
|
||||
LOG.debug("\n--> CURRENT event is [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
|
||||
if (haveToWait()) {
|
||||
|
||||
LOG.debug("\n--> WILL WAIT for result for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
|
||||
currentChangeListener = ChangeListenerFactory.create(currentEvent.getEvent());
|
||||
if (currentChangeListener == null) {
|
||||
updateCurrentResult(EVENT_RESULT.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
currentChangeListener.setCallback(this);
|
||||
currentChangeListener.register();
|
||||
|
||||
Callable<Object> task = new Callable<Object>() {
|
||||
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
Event eventToSend = currentEvent.getEvent();
|
||||
eventToSend.setDestination(Collections.singleton(Services.INSTANCE.clusterManager.getNode()));
|
||||
|
||||
LOG.debug("\n--> EVENT SENT: [{}]:[{}]", eventToSend.getClass().getName(), eventToSend.getId());
|
||||
Services.INSTANCE.eventProducer.produce(eventToSend);
|
||||
|
||||
// timeout for operation
|
||||
// Thread.sleep(100000);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
future = threadPool.submit(task);
|
||||
try {
|
||||
Object result = future.get(100, TimeUnit.SECONDS);
|
||||
LOG.debug("\n--> RESULT RECEIVED for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
} catch (TimeoutException timeoutEx) {
|
||||
LOG.debug("\n--> TimeoutException for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
updateCurrentResult(EVENT_RESULT.TIMEOUT);
|
||||
unregisterChangeListener();
|
||||
} catch (InterruptedException ignore) {
|
||||
// NOOP
|
||||
LOG.debug("\n--> InterruptedException for [{}]",
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
} catch (CancellationException ignore) {
|
||||
// NOOP
|
||||
LOG.debug("\n--> CancellationException for [{}]",
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
} catch (Exception e) {
|
||||
LOG.debug("\n--> Exception for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
LOG.error("Exception on next event processing", e);
|
||||
updateCurrentResult(EVENT_RESULT.ERROR);
|
||||
unregisterChangeListener();
|
||||
} finally {
|
||||
// unregisterChangeListener();
|
||||
}
|
||||
} else {
|
||||
LOG.debug("\n--> WILL NOT WAIT for result for [{}]",
|
||||
currentEvent == null ? "null" : currentEvent.getId());
|
||||
|
||||
threadPool.execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Event eventToSend = currentEvent.getEvent();
|
||||
eventToSend.setDestination(Collections.singleton(Services.INSTANCE.clusterManager.getNode()));
|
||||
Services.INSTANCE.eventProducer.produce(eventToSend);
|
||||
LOG.debug("\n--> EVENT SENT: [{}]:[{}]", eventToSend.getClass().getName(), eventToSend.getId());
|
||||
}
|
||||
});
|
||||
updateCurrentResult(EVENT_RESULT.SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void unregisterChangeListener() {
|
||||
synchronized (currentChangeListenerLock) {
|
||||
if (currentChangeListener != null)
|
||||
currentChangeListener.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success() {
|
||||
LOG.debug("\n--> CALLED 'success' for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
synchronized (futureLock) {
|
||||
if (this.future != null)
|
||||
future.cancel(true);
|
||||
}
|
||||
unregisterChangeListener();
|
||||
updateCurrentResult(EVENT_RESULT.SUCCESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timeout() {
|
||||
LOG.debug("\n--> CALLED 'timeout' for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
synchronized (futureLock) {
|
||||
if (this.future != null)
|
||||
future.cancel(true);
|
||||
}
|
||||
unregisterChangeListener();
|
||||
updateCurrentResult(EVENT_RESULT.TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
LOG.debug("\n--> CALLED 'fail' for [{}]", currentEvent == null ? "null" : currentEvent.getId());
|
||||
synchronized (futureLock) {
|
||||
if (this.future != null)
|
||||
future.cancel(true);
|
||||
}
|
||||
unregisterChangeListener();
|
||||
updateCurrentResult(EVENT_RESULT.ERROR);
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime</groupId>
|
||||
<artifactId>base</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
|
||||
<artifactId>config-extensions</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* config-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* configuration-test-1
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* configuration-test-1
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* configuration-test-1
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* configuration-test-1
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* configuration-test-1
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* configuration-test-1
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
|
||||
<artifactId>generator</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting.generator</groupId>
|
||||
<artifactId>common-templates-collection</artifactId>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
|
||||
<artifactId>generator</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* ftl-generator
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
|
||||
<artifactId>generator</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.generator.template;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public interface LegacyTemplate {
|
||||
String getTemplateName();
|
||||
|
||||
URL getTemplateLocation();
|
||||
|
||||
Map<String, String> getParams();
|
||||
|
||||
void setBundleContext(BundleContext bundleContext);
|
||||
|
||||
String getTemplateFileName();
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* system-commons
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 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.base.generator.template.exception;
|
||||
|
||||
public class TemplateNotFound extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TemplateNotFound() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TemplateNotFound(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public TemplateNotFound(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TemplateNotFound(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TemplateNotFound(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
|
||||
<artifactId>generator</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* generator-factory
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 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
|
||||
|
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
|
||||
<artifactId>connecting</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting</groupId>
|
||||
<artifactId>generator</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.base.connecting.generator</groupId>
|
||||
<artifactId>template-service-shell</artifactId>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user