release version 1.10.0
This commit is contained in:
@ -0,0 +1,211 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* base-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.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 - 2024 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user