release version 1.10.0

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

View File

@ -0,0 +1,175 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import ru.entaxy.platform.integration.applications.ApplicationManager;
import ru.entaxy.platform.integration.applications.ApplicationStorage;
import ru.entaxy.platform.integration.applications.ApplicationStorage.ApplicationImportContent;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplicationProjectVersion;
import ru.entaxy.platform.integration.applications.exceptions.ApplicationException;
import ru.entaxy.platform.integration.applications.exceptions.ApplicationImportCausedException;
import ru.entaxy.platform.integration.applications.exceptions.StorageException;
import ru.entaxy.platform.integration.applications.exceptions.StorageNotEnabledException;
import ru.entaxy.platform.integration.applications.exceptions.StorageNotFoundException;
import ru.entaxy.platform.integration.applications.exceptions.ProjectVersionBuildNotAvailable;
import ru.entaxy.platform.integration.applications.exceptions.ProjectVersionCausedException;
import ru.entaxy.platform.integration.applications.exceptions.ProjectVersionException;
@Component(service = ApplicationManager.class, immediate = true)
public class ApplicationManagerImpl implements ApplicationManager {
protected Map<String, ApplicationStorage> storages = new HashMap<>();
protected Object storagesLock = new Object();
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
volatile ExportImportHelper exportImportHelper;
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY, unbind = "unregisterStorage")
public void registerStorage(ApplicationStorage storage) {
synchronized (storagesLock) {
storages.put(storage.getName(), storage);
}
}
public void unregisterStorage(ApplicationStorage storage) {
synchronized (storagesLock) {
storages.remove(storage.getName());
}
}
protected ApplicationStorage getStorageUnsafe(String storageName) throws StorageException {
ApplicationStorage storage = storages.get(storageName);
if (storage == null)
throw new StorageNotFoundException(storageName);
if (!storage.isEnabled())
throw new StorageNotEnabledException(storageName);
return storage;
}
/* ApplicationManager implementation */
@Override
public ApplicationStorage getStorage(String storageName) {
return storages.get(storageName);
}
@Override
public List<ApplicationStorage> getAllStorages() {
return new ArrayList<>(storages.values());
}
@Override
public void addStorage(ApplicationStorage applicationStorage) {
// TODO Auto-generated method stub
}
@Override
public void removeStorage(ApplicationStorage applicationStorage) {
// TODO Auto-generated method stub
}
@Override
public void exportToFile(EntaxyApplicationProjectVersion version, String filePath) throws ProjectVersionException {
if (!version.isBuildAvailable())
throw new ProjectVersionBuildNotAvailable(version.getApplication().getName(), version.getVersionNumber());
Map<String, Object> props = new HashMap<>();
props.put("filePath", filePath);
try {
exportImportHelper.doExport(version, "file", props);
} catch (ProjectVersionException ve) {
throw ve;
} catch (Exception e) {
throw new ProjectVersionCausedException(version.getApplication().getName(), version.getVersionNumber(), e);
}
}
@Override
public void exportToRepository(EntaxyApplicationProjectVersion version, String repositoryName)
throws ProjectVersionException {
if (!version.isBuildAvailable())
throw new ProjectVersionBuildNotAvailable(version.getApplication().getName(), version.getVersionNumber());
Map<String, Object> props = new HashMap<>();
props.put("repositoryName", repositoryName);
try {
exportImportHelper.doExport(version, "repository", props);
} catch (ProjectVersionException ve) {
throw ve;
} catch (Exception e) {
throw new ProjectVersionCausedException(version.getApplication().getName(), version.getVersionNumber(), e);
}
}
@Override
public EntaxyApplication importApplicationFromFile(String storageName, String filePath)
throws ApplicationException, StorageException {
Map<String, Object> props = new HashMap<>();
props.put("filePath", filePath);
try {
ApplicationImportContent result = exportImportHelper.doImport("file", props);
return createApplicationFromImport(storageName, result);
} catch (Exception e) {
throw new ApplicationImportCausedException(filePath, e);
}
}
@Override
public EntaxyApplication importApplicationFromRepository(String storageName, String mavenUrl)
throws ApplicationException, StorageException {
Map<String, Object> props = new HashMap<>();
props.put("mavenUrl", mavenUrl);
try {
ApplicationImportContent result = exportImportHelper.doImport("repository", props);
return createApplicationFromImport(storageName, result);
} catch (Exception e) {
throw new ApplicationImportCausedException(mavenUrl, e);
}
}
protected EntaxyApplication createApplicationFromImport(String storageName, ApplicationImportContent importContent)
throws Exception {
ApplicationStorage storage = getStorageUnsafe(storageName);
EntaxyApplication result = storage.createApplication(importContent);
importContent.clear();
return result;
}
}

View File

@ -0,0 +1,121 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.karaf.features.Feature;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.osgi.bundle.CapabilityDescriptor;
import ru.entaxy.platform.base.support.osgi.feature.FeatureCapabilityHelper;
import ru.entaxy.platform.base.support.osgi.feature.FeaturesUtils;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectExtendedDataProvider;
@Component(service = EntaxyRuntimeObjectExtendedDataProvider.class, immediate = true)
public class ApplicationObjectExtendedDataProvider implements EntaxyRuntimeObjectExtendedDataProvider {
private static final Logger LOG = LoggerFactory.getLogger(ApplicationObjectExtendedDataProvider.class);
private static final String APPLICATIONS_PROVIDER_ID = "applications";
protected final static String APP_NAMESPACE = "entaxy.application";
protected BundleContext bundleContext;
@Activate
public void activate(ComponentContext componentContext) {
this.bundleContext = componentContext.getBundleContext();
}
@Override
public String getProviderId() {
return APPLICATIONS_PROVIDER_ID;
}
@Override
public Map<String, Object> getExtendedData(EntaxyRuntimeObject runtimeObject) {
Map<String, Object> result = new HashMap<>();
try {
Bundle b = bundleContext.getBundle(runtimeObject.getBundleInfo().getBundleId());
List<Feature> features = FeaturesUtils.FeaturesHelper.create(bundleContext)
.withCapabilityNamespace(APP_NAMESPACE).containingBundle(b).find();
if (features.isEmpty())
return null;
List<Map<String, Object>> applicationData = new ArrayList<>();
for (Feature feature : features) {
List<Map<String, Object>> featureApplications = getApplicationData(feature);
if (!featureApplications.isEmpty())
applicationData.addAll(featureApplications);
}
if (applicationData.isEmpty())
return null;
result.put("application", applicationData);
result.put("managed", true);
} catch (Exception e) {
result.put("error", String.format("[%s:%s]", e.getClass().getName(), e.getMessage()));
LOG.error(String.format("Error getting extended data for [$s]", runtimeObject.getObjectFullId()), e);
}
return result;
}
protected List<Map<String, Object>> getApplicationData(Feature feature) {
List<Map<String, Object>> result = new ArrayList<>();
FeatureCapabilityHelper capabilityHelper = new FeatureCapabilityHelper(feature);
List<CapabilityDescriptor> descriptors = capabilityHelper.getProvidedCapabilities(APP_NAMESPACE);
for (CapabilityDescriptor descriptor : descriptors) {
String name = descriptor.getAttributes().getOrDefault("name", "").toString();
if (!CommonUtils.isValid(name))
continue;
String version = descriptor.getAttributes().getOrDefault("version", "").toString();
String revision = descriptor.getAttributes().getOrDefault("revision", "").toString();
Map<String, Object> data = new HashMap<>();
data.put("name", name);
data.put("version", version);
data.put("revision", revision);
result.add(data);
}
return result;
}
}

View File

@ -0,0 +1,440 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.osgi.framework.ServiceException;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.base.support.osgi.OSGIUtils;
import ru.entaxy.platform.core.artifact.Artifact;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.core.artifact.Artifacts;
import ru.entaxy.platform.core.artifact.repository.ArtifactRepository;
import ru.entaxy.platform.core.artifact.service.ArtifactService;
import ru.entaxy.platform.integration.applications.ApplicationStorage.ApplicationImportContent;
import ru.entaxy.platform.integration.applications.ApplicationStorage.ApplicationImportItem;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplicationProjectVersion;
import ru.entaxy.platform.integration.applications.EntaxyApplicationRevision;
import ru.entaxy.platform.integration.applications.EntaxyApplicationVersion;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationComponent;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationDescriptor;
import ru.entaxy.platform.integration.applications.exceptions.ApplicationDescriptorIsInvalid;
import ru.entaxy.platform.integration.applications.exceptions.ApplicationDescriptorNotFound;
@Component(service = ExportImportHelper.class, immediate = true)
public class ExportImportHelper {
private static final Logger LOG = LoggerFactory.getLogger(ExportImportHelper.class);
public final Map<String, Exporter> exporters = new HashMap<>();
public final Map<String, Importer> importers = new HashMap<>();
protected static ExportImportHelper INSTANCE = null;
@Activate
public void activate() {
exporters.put("file", new FileExporter());
exporters.put("repository", new RepositoryExporter());
importers.put("file", new FileImporter());
importers.put("repository", new RepositoryImporter());
ExportImportHelper.INSTANCE = this;
}
public void doExport(EntaxyApplicationProjectVersion version, String exporterType, Map<String, Object> properties)
throws Exception {
if (!exporters.containsKey(exporterType))
return;
Exporter exporter = exporters.get(exporterType);
exporter.execute(version, properties);
}
public ApplicationImportContent doImport(String importerType, Map<String, Object> properties)
throws Exception {
if (!importers.containsKey(importerType))
return null;
Importer importer = importers.get(importerType);
return importer.execute(properties);
}
// importers
protected static class JarFileImportContent implements ApplicationImportContent {
protected interface Cleaner {
void clean() throws Exception;
}
protected static class FileCleaner implements Cleaner {
protected File file;
public FileCleaner(File file) {
this.file = file;
}
@Override
public void clean() throws Exception {
file.delete();
}
}
protected JarFile jarFile;
protected Map<String, ApplicationImportItem> items;
protected Cleaner cleaner;
public JarFileImportContent(JarFile jarFile) {
super();
items = new HashMap<>();
this.jarFile = jarFile;
Iterator<JarEntry> entries = jarFile.entries().asIterator();
while (entries.hasNext()) {
JarEntryImportItem item = new JarEntryImportItem(jarFile, entries.next());
items.put(item.getPath(), item);
}
}
public void setCleaner(Cleaner cleaner) {
this.cleaner = cleaner;
}
@Override
public Map<String, ApplicationImportItem> getItems() {
return items;
}
@Override
public void clear() {
try {
jarFile.close();
} catch (IOException ignore) {
// NOOP
}
if (cleaner != null)
try {
cleaner.clean();
} catch (Exception ignore) {
// NOOP
}
}
}
protected static class JarEntryImportItem implements ApplicationImportItem {
protected JarFile jarFile;
protected JarEntry jarEntry;
protected String name;
protected String path;
protected String location;
public JarEntryImportItem(JarFile jarFile, JarEntry jarEntry) {
super();
this.jarEntry = jarEntry;
this.jarFile = jarFile;
init();
}
protected void init() {
path = jarEntry.getName();
int index = path.lastIndexOf('/');
if (index > 0) {
name = path.substring(index + 1);
location = path.substring(0, index);
} else {
name = path;
location = "";
}
}
@Override
public String getName() {
return name;
}
@Override
public String getLocation() {
return location;
}
@Override
public String getPath() {
return path;
}
@Override
public InputStream getInputStream() throws IOException {
return jarFile.getInputStream(jarEntry);
}
}
protected abstract static class Importer {
public abstract ApplicationImportContent execute(Map<String, Object> properties)
throws Exception;
}
protected static class FileImporter extends Importer {
@Override
public ApplicationImportContent execute(Map<String, Object> properties) throws Exception {
String filePath = properties.getOrDefault("filePath", "").toString();
if (!CommonUtils.isValid(filePath))
throw new IllegalArgumentException("Invalid filePath: " + filePath);
File targetFile = new File(filePath);
if (!targetFile.exists())
throw new IllegalArgumentException("File not exists: " + filePath);
if (targetFile.isDirectory())
throw new IllegalArgumentException("File is directory: " + filePath);
JarFile jarFile = new JarFile(targetFile);
return new JarFileImportContent(jarFile);
}
}
protected static class RepositoryImporter extends Importer {
@Override
public ApplicationImportContent execute(Map<String, Object> properties) throws Exception {
String mavenUrl = properties.getOrDefault("mavenUrl", "").toString();
if (!CommonUtils.isValid(mavenUrl))
throw new IllegalArgumentException("mavenUrl not set");
if (!mavenUrl.startsWith("mvn:"))
mavenUrl = "mvn:" + mavenUrl;
URL url = new URL(mavenUrl);
File tempFile = File.createTempFile("app-import-", Calendar.getInstance().getTimeInMillis() + "");
try (InputStream is = url.openStream()) {
Files.copy(is, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
Map<String, Object> props = new HashMap<>();
props.put("filePath", tempFile.getAbsolutePath());
ApplicationImportContent result = ExportImportHelper.INSTANCE.doImport("file", props);
((JarFileImportContent) result).setCleaner(new JarFileImportContent.FileCleaner(tempFile));
return result;
}
}
// exporters
protected abstract static class Exporter {
public abstract void execute(EntaxyApplicationProjectVersion version, Map<String, Object> properties)
throws Exception;
}
protected static class FileExporter extends Exporter {
@Override
public void execute(EntaxyApplicationProjectVersion version, Map<String, Object> properties) throws Exception {
String filePath = properties.getOrDefault("filePath", "").toString();
if (filePath.endsWith("/")) {
// it's directory
String url = version.getBuildUrl().toString();
String fileName = url.substring(url.lastIndexOf('/'));
filePath = filePath.concat(fileName);
}
if (!CommonUtils.isValid(filePath))
return;
File targetFile = new File(filePath);
targetFile.getAbsoluteFile().getParentFile().mkdirs();
try (FileOutputStream fos = new FileOutputStream(targetFile);
InputStream is = version.getBuild();) {
fos.write(is.readAllBytes());
}
}
}
protected static class RepositoryExporter extends Exporter {
@Override
public void execute(EntaxyApplicationProjectVersion version, Map<String, Object> properties) throws Exception {
ArtifactService artifactService =
OSGIUtils.services().ofClass(ArtifactService.class).waitService(20000).get();
if (artifactService == null)
throw new ServiceException("Service not found: ArtifactService.class");
String repositoryName = properties.getOrDefault("repositoryName", "").toString();
if (!CommonUtils.isValid(repositoryName))
throw new IllegalArgumentException("repositoryName not set");
ArtifactRepository repo = artifactService.getRepository(repositoryName);
if (repo == null)
throw new IllegalArgumentException("Repository not found: " + repositoryName);
if (repo.isReadOnly()) {
throw new IllegalArgumentException("Repository " + repositoryName + " is read only.");
}
Artifact artifact = Artifacts.create(Artifact.ARTIFACT_CATEGORY_JAR);
String mavenCoordinates = version.getBuildInfo().mavenUrl;
artifact.getCoordinates().update(ArtifactCoordinates.fromUrl(mavenCoordinates));
try (InputStream is = version.getBuild()) {
artifact.setContent(is);
repo.deploy(artifact);
}
}
}
public static class ApplicationImporter {
static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
protected StorageImportAdapter storageAdapter;
protected ApplicationDescriptor applicationDescriptor = null;
public ApplicationImporter(StorageImportAdapter storageAdapter) {
super();
this.storageAdapter = storageAdapter;
}
public void executeImport(ApplicationImportContent importContent) throws Exception {
// check descriptor
String applicationName = "unknown";
ApplicationImportItem descriptorItem = importContent.getItems().get(EntaxyApplication.DESCRIPTOR_NAME);
if (descriptorItem == null)
throw new ApplicationDescriptorNotFound(applicationName);
try (InputStream is = descriptorItem.getInputStream()) {
String descriptorData = new String(is.readAllBytes());
applicationDescriptor =
GSON.fromJson(JSONUtils.getJsonRootObject(descriptorData), ApplicationDescriptor.class);
} catch (Exception e1) {
throw new ApplicationDescriptorIsInvalid(applicationName);
}
if (applicationDescriptor == null)
throw new ApplicationDescriptorIsInvalid(applicationName);
// if something's wrong with descriptor, exception is thrown
storageAdapter.checkDescriptor(applicationDescriptor);
applicationName = applicationDescriptor.name;
// if something's wrong, exception is thrown
StorageApplicationContentAdapter contentAdapter =
storageAdapter.getContentAdapter(applicationName, applicationDescriptor);
fillContent(applicationDescriptor, importContent, contentAdapter);
EntaxyApplicationVersion createdVersion =
storageAdapter.getVersion(applicationName, applicationDescriptor.version);
if (createdVersion == null) {
throw new java.lang.InstantiationException("Version not created");
}
EntaxyApplicationRevision revision = createdVersion.createRevision();
if (revision == null) {
throw new java.lang.InstantiationException("Revision not created");
}
}
public ApplicationDescriptor getApplicationDescriptor() {
return applicationDescriptor;
}
protected void fillContent(ApplicationDescriptor descriptor, ApplicationImportContent source,
StorageApplicationContentAdapter target) throws Exception {
List<String> locationsToProcess = new ArrayList<>(source.getItems().keySet());
// we skip descriptor 'cause it's already there
locationsToProcess.remove(EntaxyApplication.DESCRIPTOR_NAME);
// we ignore manifest
locationsToProcess.remove("META-INF/MANIFEST.MF");
// load features
if (descriptor.features == null)
throw new IllegalArgumentException("Features not found in descriptor");
StorageItemAdapter item = target.createItem(descriptor.features);
try (InputStream is = source.getItems().get(descriptor.features.internalLocation).getInputStream()) {
item.write(is);
} catch (Exception e) {
LOG.error("Error writing [" + descriptor.features.internalLocation + "]", e);
}
locationsToProcess.remove(descriptor.features.internalLocation);
// load components
for (ApplicationComponent comp : descriptor.getComponents()) {
item = target.createItem(comp);
try (InputStream is = source.getItems().get(comp.getInternalLocation()).getInputStream()) {
item.write(is);
} catch (Exception e) {
LOG.error("Error writing [" + comp.getInternalLocation() + "]", e);
}
locationsToProcess.remove(comp.getInternalLocation());
}
// left only resources
for (String location : locationsToProcess) {
try (InputStream is = source.getItems().get(location).getInputStream()) {
target.createResource(location, is);
} catch (Exception e) {
LOG.error("Error writing [" + location + "]", e);
}
}
}
}
}

View File

@ -0,0 +1,94 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import org.apache.karaf.bundle.core.BundleService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import ru.entaxy.base.generator.template.TemplateService;
import ru.entaxy.esb.resources.EntaxyResourceService;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectService;
@Component(service = ServiceHelper.class, immediate = true)
public class ServiceHelper {
private static ServiceHelper INSTANCE;
public static ServiceHelper getInstance() {
return INSTANCE;
}
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
volatile EntaxyRuntimeObjectService entaxyRuntimeObjectService;
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
volatile EntaxyResourceService entaxyResourceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
volatile TemplateService templateService;
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
volatile BundleService bundleService;
@Activate
public void activate() {
INSTANCE = this;
}
public EntaxyRuntimeObjectService getEntaxyRuntimeObjectService() {
return entaxyRuntimeObjectService;
}
public EntaxyResourceService getEntaxyResourceService() {
return entaxyResourceService;
}
public TemplateService getTemplateService() {
return templateService;
}
public BundleService getBundleService() {
return bundleService;
}
public boolean objectExists(String objectFullId) {
return entaxyRuntimeObjectService.getRuntimeObject(objectFullId) != null;
}
public boolean resourceExists(String resourceUrl) {
return entaxyResourceService.getResource(resourceUrl).exists();
}
}

View File

@ -0,0 +1,41 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import java.io.InputStream;
import ru.entaxy.platform.integration.applications.ApplicationResource;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationComponent;
public interface StorageApplicationContentAdapter {
StorageItemAdapter createItem(ApplicationComponent applicationComponent) throws Exception;
ApplicationResource createResource(String location, InputStream inputStream) throws Exception;
StorageItemAdapter getItemAdapter(String location) throws Exception;
}

View File

@ -0,0 +1,42 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import ru.entaxy.platform.integration.applications.EntaxyApplicationVersion;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationDescriptor;
import ru.entaxy.platform.integration.applications.exceptions.ApplicationException;
import ru.entaxy.platform.integration.applications.exceptions.StorageException;
public interface StorageImportAdapter {
void checkDescriptor(ApplicationDescriptor applicationDescriptor) throws ApplicationException, StorageException;
StorageApplicationContentAdapter getContentAdapter(String applicationName,
ApplicationDescriptor applicationDescriptor) throws ApplicationException, StorageException;
EntaxyApplicationVersion getVersion(String applicationName, String version)
throws ApplicationException, StorageException;
}

View File

@ -0,0 +1,36 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl;
import java.io.InputStream;
public interface StorageItemAdapter {
InputStream getInputStream();
void write(InputStream source) throws Exception;
}

View File

@ -0,0 +1,70 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.application;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import ru.entaxy.platform.integration.applications.ApplicationContent;
import ru.entaxy.platform.integration.applications.ApplicationItem;
import ru.entaxy.platform.integration.applications.ApplicationResource;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationDescriptor;
public class ApplicationContentImpl implements ApplicationContent {
protected ApplicationDescriptor descriptor;
protected Map<String, ApplicationItemImpl> items = new HashMap<>();
protected Map<String, ApplicationResourceImpl> resources = new HashMap<>();
public ApplicationContentImpl(ApplicationDescriptor descriptor) {
super();
this.descriptor = descriptor;
}
public void setDescriptor(ApplicationDescriptor descriptor) {
this.descriptor = descriptor;
}
@Override
public ApplicationDescriptor getDescriptor() {
return descriptor;
}
@Override
public List<ApplicationItem> getItems() {
return items.values().stream().collect(Collectors.toList());
}
@Override
public List<ApplicationResource> getResources() {
return resources.values().stream().collect(Collectors.toList());
}
}

View File

@ -0,0 +1,95 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.application;
import java.io.InputStream;
import ru.entaxy.platform.integration.applications.ApplicationItem;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplication.ITEM_TYPE;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationComponent;
import ru.entaxy.platform.integration.applications.impl.StorageItemAdapter;
public class ApplicationItemImpl implements ApplicationItem {
protected String id;
protected EntaxyApplication.ITEM_TYPE type;
protected String location;
protected boolean isRevisionable = true;
protected boolean isEditable = true;
protected transient StorageItemAdapter itemAdapter;
public ApplicationItemImpl(ApplicationComponent applicationComponent, StorageItemAdapter itemAdapter) {
super();
this.itemAdapter = itemAdapter;
id = applicationComponent.id;
type = applicationComponent.type;
location = applicationComponent.internalLocation;
isRevisionable = ITEM_TYPE.CONFIG.equals(type) || ITEM_TYPE.FEATURES.equals(type);
isEditable = ITEM_TYPE.CONFIG.equals(type);
}
@Override
public InputStream getInputStream() {
return itemAdapter.getInputStream();
}
@Override
public void update(InputStream inputStream) throws Exception {
this.itemAdapter.write(inputStream);
}
@Override
public String getId() {
return id;
}
@Override
public EntaxyApplication.ITEM_TYPE getType() {
return type;
}
@Override
public String getLocation() {
return location;
}
@Override
public boolean isRevisionable() {
return isRevisionable;
}
@Override
public boolean isEditable() {
return isEditable;
}
}

View File

@ -0,0 +1,40 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.application;
import java.io.InputStream;
import ru.entaxy.platform.integration.applications.ApplicationResource;
public class ApplicationResourceImpl implements ApplicationResource {
@Override
public InputStream getInputStream() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,443 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.application;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.base.generator.template.Template;
import ru.entaxy.base.generator.template.TemplateAwareGenerator;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.factory.GeneratorFactory;
import ru.entaxy.platform.base.support.osgi.OSGIUtils;
import ru.entaxy.platform.core.artifact.Artifact;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.core.artifact.Artifacts;
import ru.entaxy.platform.core.artifact.ext.ArtifactExtended;
import ru.entaxy.platform.core.artifact.ext.features.FeatureInstaller;
import ru.entaxy.platform.core.artifact.ext.features.FeaturesInstaller;
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
import ru.entaxy.platform.core.artifact.service.ArtifactService;
import ru.entaxy.platform.integration.applications.ApplicationItem;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplicationRevision.REVISION_STATUS;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationComponent;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationFeatures;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationRequirement;
import ru.entaxy.platform.integration.applications.exceptions.RevisionCausedException;
import ru.entaxy.platform.integration.applications.exceptions.RevisionException;
import ru.entaxy.platform.integration.applications.exceptions.RevisionIllegalTransition;
import ru.entaxy.platform.integration.applications.exceptions.RevisionNotConfigurable;
import ru.entaxy.platform.integration.applications.exceptions.RevisionRequirementsNotSatisfied;
import ru.entaxy.platform.integration.applications.impl.ServiceHelper;
import ru.entaxy.platform.runtime.cellar.sequence.CellarSequenceManager;
public class RevisionHelper {
private static final Logger LOG = LoggerFactory.getLogger(RevisionHelper.class);
public static interface RevisionHelperAdapter {
REVISION_STATUS getCurrentStatus();
void updateStatus(REVISION_STATUS newStatus);
int getRevisionNumber();
void writeItem(String location, InputStream inputStream) throws Exception;
}
protected ApplicationContentImpl applicationContent;
protected RevisionHelperAdapter adapter;
protected int revisionNumber;
protected REVISION_STATUS currentStatus;
protected String applicationName;
protected String version;
public RevisionHelper(ApplicationContentImpl applicationContent, RevisionHelperAdapter adapter) {
super();
this.applicationContent = applicationContent;
this.adapter = adapter;
this.revisionNumber = this.adapter.getRevisionNumber();
this.currentStatus = this.adapter.getCurrentStatus();
this.applicationName = applicationContent.getDescriptor().name;
this.version = applicationContent.getDescriptor().version;
}
public void configure() throws RevisionException {
if (applicationContent.getEditables().isEmpty())
throw new RevisionNotConfigurable(applicationName,
version, revisionNumber);
// revision 0 is not configured !!!
if (revisionNumber == 0) {
throw new RevisionNotConfigurable(applicationName,
version, revisionNumber);
}
if (!REVISION_STATUS.NEW.equals(currentStatus) && !REVISION_STATUS.CONFIGURED.equals(currentStatus)
&& !REVISION_STATUS.DEPLOYED.equals(currentStatus))
throw new RevisionIllegalTransition(applicationName, version, revisionNumber, currentStatus,
REVISION_STATUS.CONFIGURED);
currentStatus = REVISION_STATUS.CONFIGURED;
adapter.updateStatus(currentStatus);
}
public void deploy() throws RevisionException {
if (REVISION_STATUS.INSTALLED.equals(currentStatus) || REVISION_STATUS.UNINSTALLED.equals(currentStatus)
|| REVISION_STATUS.DEPLOYED.equals(currentStatus))
throw new RevisionIllegalTransition(applicationName, version, revisionNumber, currentStatus,
REVISION_STATUS.DEPLOYED);
try {
ArtifactService artifactService =
OSGIUtils.services().ofClass(ArtifactService.class).waitService(2000).get();
if (artifactService == null)
throw new IllegalArgumentException("ArtifactService not available");
Map<String, ApplicationComponent> componentMap = new HashMap<>();
componentMap.put(applicationContent.getDescriptor().getFeatures().internalLocation,
applicationContent.getDescriptor().getFeatures());
for (ApplicationComponent comp : applicationContent.getDescriptor().getComponents())
componentMap.put(comp.internalLocation, comp);
for (ApplicationItem item : applicationContent.getItems()) {
ApplicationComponent comp = componentMap.get(item.getLocation());
if (comp == null)
continue;
Artifact artifact = Artifacts.create(ArtifactExtended.ARTIFACT_CATEGORY_UNTYPED_BINARY);
artifact.getCoordinates().set(ArtifactCoordinates.fromUrl(comp.mavenLocation));
try (InputStream is = item.getInputStream()) {
artifact.setContent(is);
artifactService.deployShared(artifact);
}
}
} catch (RevisionException rethrow) {
throw rethrow;
} catch (Exception e) {
throw new RevisionCausedException(applicationName, e, version, revisionNumber);
}
currentStatus = REVISION_STATUS.DEPLOYED;
adapter.updateStatus(currentStatus);
}
public void install() throws RevisionException {
if (!REVISION_STATUS.DEPLOYED.equals(currentStatus) && !REVISION_STATUS.UNINSTALLED.equals(currentStatus))
throw new RevisionIllegalTransition(applicationName, version, revisionNumber, currentStatus,
REVISION_STATUS.INSTALLED);
List<ApplicationRequirement> failed = checkRequirements();
if (!failed.isEmpty())
throw new RevisionRequirementsNotSatisfied(applicationName, version, revisionNumber, failed);
try {
ArtifactService artifactService =
OSGIUtils.services().ofClass(ArtifactService.class).waitService(2000).get();
if (artifactService == null)
throw new IllegalArgumentException("ArtifactService not available");
CellarSequenceManager sequenceManager =
OSGIUtils.services().ofClass(CellarSequenceManager.class).waitService(2000).get();
if (sequenceManager == null)
throw new IllegalArgumentException("CellarSequenceManager not available");
String sequenceId = applicationContent.getDescriptor().getFeatures().mavenLocation;
FeaturesInstaller installer =
artifactService.installers().cluster().typed(FeaturesInstaller.class).refresh()
.inSequence(sequenceId);
installer.setSourceLocation(applicationContent.getDescriptor().getFeatures().getFullTargetLocation());
InstallationResult result = installer.install();
if (!result.isSuccessful()) {
if (result.getError() != null)
throw new Exception(result.getMessage(), result.getError());
}
FeatureInstaller featureInstaller = artifactService.installers().cluster().typed(FeatureInstaller.class);
String featureVersion = ArtifactCoordinates
.fromUrl(applicationContent.getDescriptor().getFeatures().mavenLocation).getVersion();
InstallationResult featureResult = featureInstaller
.inSequence(sequenceId)
.feature(applicationContent.getDescriptor().getFeatures().getId())
.version(featureVersion)
.noRefresh()
.upgrade()
.install();
// set up sequence
sequenceManager.getSequence(sequenceId).getEvent().setWaitLast(false);
// process sequence
sequenceManager.produceSequence(sequenceId);
sequenceManager.releaseSequence(sequenceId);
if (!featureResult.isSuccessful()) {
InstallationResult firstFailedSubresult = null;
for (InstallationResult res : featureResult.getSubResults())
if (!res.isSuccessful()) {
firstFailedSubresult = res;
break;
}
if (firstFailedSubresult == null)
throw new Exception("Feature installation failed");
if (firstFailedSubresult.getError() != null)
throw new Exception("Feature installation failed: [" + firstFailedSubresult.getObject() != null
? firstFailedSubresult.getObject().toString()
: "unknown" + "]", firstFailedSubresult.getError());
else
throw new Exception("Feature installation failed: [" + firstFailedSubresult.getObject() != null
? firstFailedSubresult.getObject().toString()
: "unknown" + "]");
}
List<String> failedfeatures = new ArrayList<>();
for (InstallationResult res : featureResult.getSubResults())
if (!res.isSuccessful()) {
// TODO implement rollback if we have failed subresults
if (res.getObject() != null)
failedfeatures.add(res.getObject().toString());
else
failedfeatures.add("unknown_" + failedfeatures.size());
}
if (!failedfeatures.isEmpty())
throw new Exception("Feature installation failed: ["
+ failedfeatures.stream().collect(Collectors.joining(",")) + "]");
} catch (RevisionException rethrow) {
throw rethrow;
} catch (Exception e) {
throw new RevisionCausedException(applicationName, e, version, revisionNumber);
}
currentStatus = REVISION_STATUS.INSTALLED;
adapter.updateStatus(currentStatus);
}
public void uninstall() throws RevisionException {
if (!REVISION_STATUS.INSTALLED.equals(currentStatus))
throw new RevisionIllegalTransition(applicationName, version, revisionNumber, currentStatus,
REVISION_STATUS.UNINSTALLED);
try {
ArtifactService artifactService =
OSGIUtils.services().ofClass(ArtifactService.class).waitService(2000).get();
if (artifactService == null)
throw new IllegalArgumentException("ArtifactService not available");
CellarSequenceManager sequenceManager =
OSGIUtils.services().ofClass(CellarSequenceManager.class).waitService(2000).get();
if (sequenceManager == null)
throw new IllegalArgumentException("CellarSequenceManager not available");
String sequenceId = applicationContent.getDescriptor().getFeatures().mavenLocation;
FeaturesInstaller installer =
artifactService.installers().cluster().typed(FeaturesInstaller.class).refresh()
.inSequence(sequenceId);
installer.setSourceLocation(applicationContent.getDescriptor().getFeatures().getFullTargetLocation());
InstallationResult result = installer.uninstall();
if (!result.isSuccessful()) {
if (result.getError() != null)
throw new Exception(result.getMessage(), result.getError());
}
FeatureInstaller featureInstaller = artifactService.installers().cluster().typed(FeatureInstaller.class);
String featureVersion = ArtifactCoordinates
.fromUrl(applicationContent.getDescriptor().getFeatures().mavenLocation).getVersion();
InstallationResult featureResult = featureInstaller
.inSequence(sequenceId)
.feature(applicationContent.getDescriptor().getFeatures().getId())
.version(featureVersion)
.noRefresh()
.uninstall();
// set up sequence
sequenceManager.getSequence(sequenceId).getEvent().setWaitLast(false);
// process sequence
sequenceManager.produceSequence(sequenceId);
sequenceManager.releaseSequence(sequenceId);
if (!featureResult.isSuccessful()) {
InstallationResult firstFailedSubresult = null;
for (InstallationResult res : featureResult.getSubResults())
if (!res.isSuccessful()) {
firstFailedSubresult = res;
break;
}
if (firstFailedSubresult == null)
throw new Exception("Feature uninstallation failed");
if (firstFailedSubresult.getError() != null)
throw new Exception("Feature uninstallation failed: [" + firstFailedSubresult.getObject() != null
? firstFailedSubresult.getObject().toString()
: "unknown" + "]", firstFailedSubresult.getError());
else
throw new Exception("Feature uninstallation failed: [" + firstFailedSubresult.getObject() != null
? firstFailedSubresult.getObject().toString()
: "unknown" + "]");
}
List<String> failedfeatures = new ArrayList<>();
for (InstallationResult res : featureResult.getSubResults())
if (!res.isSuccessful()) {
// TODO implement rollback if we have failed subresults
if (res.getObject() != null)
failedfeatures.add(res.getObject().toString());
else
failedfeatures.add("unknown_" + failedfeatures.size());
}
if (!failedfeatures.isEmpty())
throw new Exception("Feature installation failed: ["
+ failedfeatures.stream().collect(Collectors.joining(",")) + "]");
} catch (RevisionException rethrow) {
throw rethrow;
} catch (Exception e) {
throw new RevisionCausedException(applicationName, e, version, revisionNumber);
}
currentStatus = REVISION_STATUS.UNINSTALLED;
adapter.updateStatus(currentStatus);
}
protected List<ApplicationRequirement> checkRequirements() {
List<ApplicationRequirement> result = new ArrayList<>();
for (ApplicationRequirement req : applicationContent.getDescriptor().getRequirements()) {
if (!checkRequirement(req))
result.add(req);
}
return result;
}
protected boolean checkRequirement(ApplicationRequirement req) {
if (EntaxyApplication.ITEM_TYPE.OBJECT.equals(req.getType())) {
return ServiceHelper.getInstance().objectExists(req.getId());
}
if (EntaxyApplication.ITEM_TYPE.RESOURCE.equals(req.getType())) {
return ServiceHelper.getInstance().resourceExists(req.getId());
}
return true;
}
public void update() throws Exception {
updateComponentVersions();
updateFeatures();
}
protected void updateComponentVersions() throws Exception {
List<ApplicationComponent> components = new ArrayList<>();
components.add(applicationContent.getDescriptor().features);
components.addAll(applicationContent.getDescriptor().getComponents());
List<String> revisionableIds = applicationContent.getItems().stream().filter(item -> item.isRevisionable())
.map(item -> item.getId()).collect(Collectors.toList());
for (ApplicationComponent component : components) {
if (!revisionableIds.contains(component.id))
continue;
ArtifactCoordinates coordinates = ArtifactCoordinates.fromUrl(component.mavenLocation);
coordinates.qualifier(String.format("REV_%03d", revisionNumber));
component.mavenLocation = coordinates.toMavenString();
coordinates = ArtifactCoordinates.fromUrl(component.targetLocation);
// coordinates may be null for configs
if (coordinates == null)
continue;
coordinates.qualifier(String.format("REV_%03d", revisionNumber));
component.targetLocation = coordinates.toMavenString();
}
}
protected void updateFeatures() throws Exception {
Template template =
ServiceHelper.getInstance().getTemplateService().getTemplateById("applications.builder.features");
TemplateAwareGenerator generator = GeneratorFactory.createGenerator(template);
if (generator != null) {
ApplicationFeatures features = applicationContent.getDescriptor().getFeatures();
ArtifactCoordinates coord = ArtifactCoordinates.fromUrl(features.mavenLocation);
String repoName = String.format("%s.%s-%s", coord.getGroupId(), coord.getArtifactId(), coord.getVersion());
String featureName = String.format("%s.%s", coord.getGroupId(), coord.getArtifactId());
// convert to OSGI-style version
String featureVersion = coord.getVersion().replace('-', '.');
Map<String, Object> params = new HashMap<>();
params.put("descriptor", applicationContent.getDescriptor());
params.put("repoName", repoName);
params.put("featureName", featureName);
params.put("featureVersion", featureVersion);
params.put("revisionNumber", revisionNumber + "");
Generated generated;
generated = generator.generate(template, params);
if ((generated == null) || (generated.getObject() == null)) {
throw new IllegalArgumentException("Generated features is null");
}
try (ByteArrayInputStream bis = new ByteArrayInputStream(generated.getObject().toString().getBytes())) {
adapter.writeItem(features.internalLocation, bis);
}
} else {
throw new IllegalArgumentException("Generator not defined for 'applications.builder.features'");
}
}
}

View File

@ -0,0 +1,56 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
public abstract class AbstractDescriptor {
public enum TYPE {
BUNDLE,
RESOURCE,
CONFIG
}
TYPE type;
// location within application bundle
String finalLocation;
// source location for final installation
String finalMavenLocation;
int priority = 50;
boolean consistent = true;
protected AbstractDescriptor() {
super();
type = getDescriptorType();
}
abstract public String getDescriptorId();
abstract protected TYPE getDescriptorType();
}

View File

@ -0,0 +1,74 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
public abstract class AbstractStorage<T extends AbstractDescriptor> {
public static class BuildResult {
Map<String, AbstractDescriptor> newDescriptors = new HashMap<>();
Map<String, AbstractDescriptor> changes = new HashMap<>();
}
File parentDir;
File tempDir;
File rootDirectory;
List<T> descriptors = new ArrayList<>();
protected AbstractStorage(File parentDir, File tempDir) {
super();
this.parentDir = parentDir;
this.tempDir = tempDir;
this.rootDirectory = new File(Paths.get(parentDir.getAbsolutePath(), getStorageDir()).toAbsolutePath().toUri());
this.rootDirectory.mkdirs();
}
public void addDescriptor(T descriptor) {
this.descriptors.add(descriptor);
}
protected abstract String getStorageDir();
public abstract void prepare();
public abstract void prepareDescriptor(T descriptor);
public abstract BuildResult build(ArtifactCoordinates applicationCoordinates);
}

View File

@ -0,0 +1,558 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import ru.entaxy.base.generator.template.Template;
import ru.entaxy.base.generator.template.TemplateAwareGenerator;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.factory.GeneratorFactory;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.integration.applications.ApplicationProjectContent.STANDARD_PROPERTIES;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplication.ITEM_TYPE;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationComponent;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationContentItem;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationDescriptor;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationFeatures;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationRequirement;
import ru.entaxy.platform.integration.applications.impl.ServiceHelper;
import ru.entaxy.platform.integration.applications.impl.build.AbstractStorage.BuildResult;
import ru.entaxy.platform.integration.applications.impl.jar.FolderBasedJarBuilder;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectContentImpl;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
import ru.entaxy.platform.integration.applications.impl.project.item.BundleItemImpl;
import ru.entaxy.platform.integration.applications.impl.project.item.ConfigItemImpl;
import ru.entaxy.platform.integration.applications.impl.project.item.ObjectItemImpl;
import ru.entaxy.platform.integration.applications.impl.project.item.ResourceItemImpl;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
public class ApplicationBuilder {
private static final Logger LOG = LoggerFactory.getLogger(ApplicationBuilder.class);
protected static Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final String DEFAULT_VERSION = "1.0.0";
public static final String DEFAULT_APP_NAME = "app-0";
protected static final String CONTENT_ROOT_NAME = "content";
protected static final String TEMP_ROOT_NAME = "temp";
protected static final URI ROOT_FILE_URI =
Paths.get(System.getProperty("karaf.home"), "data/tmp/.appbuilder").toAbsolutePath().toUri();
protected static File ROOT_FILE;
protected static boolean IS_INITED = false;
protected static void initRootFile() {
if (IS_INITED)
return;
ROOT_FILE = new File(ROOT_FILE_URI);
ROOT_FILE.mkdirs();
IS_INITED = true;
}
final protected ArtifactCoordinates coordinates = new ArtifactCoordinates();
protected ApplicationProjectContentImpl applicationContent;
protected String buildRootName = UUID.randomUUID().toString();
protected File buildRoot;
protected File buildContentRoot;
protected File buildTempRoot;
protected Map<String, BundleDescriptor> bundleDescriptors = new HashMap<>();
protected Map<String, ResourceDescriptor> resourceDescriptors = new HashMap<>();
protected Map<String, ConfigDescriptor> configDescriptors = new HashMap<>();
protected Map<String, AbstractDescriptor> itemToDescriptorMap = new HashMap<>();
protected BundleStorage bundleStorage;
protected ResourceStorage resourceStorage;
protected ConfigStorage configStorage;
protected ApplicationDescriptor descriptor;
protected File buildResult;
public ApplicationBuilder(ApplicationProjectContentImpl applicationContent) {
super();
initRootFile();
this.applicationContent = applicationContent;
coordinates.groupId(applicationContent.getProperties().getOrDefault(STANDARD_PROPERTIES.GROUP,
EntaxyApplication.DEFAULT_GROUP_ID).toString())
.version(applicationContent.getProperties().getOrDefault(STANDARD_PROPERTIES.VERSION,
DEFAULT_VERSION).toString())
.artifactId(applicationContent.getProperties().getOrDefault(STANDARD_PROPERTIES.APPLICATION,
DEFAULT_APP_NAME).toString());
buildRoot = new File(Paths.get(ROOT_FILE.getAbsolutePath(), buildRootName).toAbsolutePath().toUri());
buildRoot.mkdirs();
buildContentRoot = new File(Paths.get(buildRoot.getAbsolutePath(), CONTENT_ROOT_NAME).toAbsolutePath().toUri());
buildContentRoot.mkdirs();
buildTempRoot = new File(Paths.get(buildRoot.getAbsolutePath(), TEMP_ROOT_NAME).toAbsolutePath().toUri());
buildTempRoot.mkdirs();
bundleStorage = new BundleStorage(buildContentRoot, buildTempRoot);
resourceStorage = new ResourceStorage(buildContentRoot, buildTempRoot);
configStorage = new ConfigStorage(buildContentRoot, buildTempRoot);
}
public ArtifactCoordinates getCoordinates() {
return coordinates;
}
public void prepareContent() {
// get only included items
List<ApplicationProjectItemImpl> includedItems = applicationContent.getItemsMap().values().stream()
.filter(item -> !item.isRequired()).collect(Collectors.toList());
// get by type
List<BundleItemImpl> includedBundles = new ArrayList<>();
List<ObjectItemImpl> includedObjects = new ArrayList<>();
List<ConfigItemImpl> includedConfigs = new ArrayList<>();
List<ResourceItemImpl> includedResources = new ArrayList<>();
for (ApplicationProjectItemImpl item : includedItems)
if (item instanceof ConfigItemImpl)
includedConfigs.add((ConfigItemImpl) item);
else if (item instanceof ObjectItemImpl)
includedObjects.add((ObjectItemImpl) item);
else if (item instanceof BundleItemImpl)
includedBundles.add((BundleItemImpl) item);
else if (item instanceof ResourceItemImpl)
includedResources.add((ResourceItemImpl) item);
else
continue;
// collect bundles for objects
for (ObjectItemImpl item : includedObjects) {
// actualize object info
EntaxyRuntimeObject runtimeObject =
ServiceHelper.getInstance().getEntaxyRuntimeObjectService().getRuntimeObject(
item.getObject().getObjectFullId());
String containerId = runtimeObject.getContainer().getId();
BundleDescriptor desc;
if (!bundleDescriptors.containsKey(containerId)) {
long bundleId = Long.parseLong(containerId);
Bundle bundle = FrameworkUtil.getBundle(getClass()).getBundleContext().getBundle(bundleId);
desc = BundleDescriptor.forBundle(bundle);
if (!desc.consistent) {
LOG.error(String.format("Descritor is inconcistent for bundle [%s]", containerId));
continue;
}
bundleDescriptors.put(containerId, desc);
bundleStorage.addDescriptor(desc);
} else {
desc = bundleDescriptors.get(containerId);
}
itemToDescriptorMap.put(item.getId(), desc);
}
// collect other bundles
for (BundleItemImpl item : includedBundles) {
// TODO implement
}
// collect resources
for (ResourceItemImpl item : includedResources) {
ResourceDescriptor desc;
if (!resourceDescriptors.containsKey(item.getId())) {
desc = ResourceDescriptor.forResource(item.getResource());
resourceStorage.addDescriptor(desc);
} else {
desc = resourceDescriptors.get(item.getId());
}
itemToDescriptorMap.put(item.getId(), desc);
}
// collect configs
for (ConfigItemImpl item : includedConfigs) {
ConfigDescriptor desc = null;
EntaxyRuntimeObject configObject =
ServiceHelper.getInstance().getEntaxyRuntimeObjectService().getRuntimeObject(
item.getObject().getObjectFullId());
if (!configDescriptors.containsKey(item.getId())) {
/*
if (!configObject.getIncomiingSubordRelations().isEmpty()) {
// this is object config
Optional<EntaxyRuntimeRelation> rel = configObject.getIncomiingSubordRelations().stream()
.filter(r -> "config".equals(r.getName())).findFirst();
if (rel.isPresent()) {
EntaxyRuntimeObject configuredObject = rel.get().getMain();
// check data consistency
if (configuredObject.getObjectFullId()
.equals(ObjectConfig.getConfiguredObjectId(configObject.getId()))) {
}
}
}
if (desc == null) {
// this is custom config
desc = ConfigDescriptor.forConfig(item.getId());
}
*/
desc = ConfigDescriptor.forConfig(item.getId(), getCoordinates());
configStorage.addDescriptor(desc);
} else {
desc = configDescriptors.get(item.getId());
}
itemToDescriptorMap.put(item.getObject().getObjectFullId(), desc);
}
bundleStorage.prepare();
configStorage.prepare();
resourceStorage.prepare();
BuildResult result = resourceStorage.build(coordinates);
for (Entry<String, AbstractDescriptor> entry : result.changes.entrySet()) {
itemToDescriptorMap.put(entry.getKey(), entry.getValue());
}
for (Entry<String, AbstractDescriptor> entry : result.newDescriptors.entrySet()) {
if (entry.getValue() instanceof BundleDescriptor) {
// register descriptor
bundleDescriptors.put(entry.getKey(), (BundleDescriptor) entry.getValue());
// add descriptor to storage
bundleStorage.prepareDescriptor((BundleDescriptor) entry.getValue());
}
}
result = bundleStorage.build(coordinates);
// process result
// NOOP
}
public void generateDescriptor() {
descriptor = new ApplicationDescriptor();
descriptor.name = coordinates.getArtifactId();
descriptor.group = coordinates.getGroupId();
descriptor.version = coordinates.getVersion();
descriptor.buildBy = "";
descriptor.buildOn = Calendar.getInstance().getTimeInMillis() + "";
descriptor.mavenUrl = coordinates.toMavenString();
descriptor.mavenAsset = coordinates.toAssetName();
// get requirements
List<ApplicationProjectItemImpl> reqs = applicationContent.getItemsMap().values().stream()
.filter(item -> item.isRequired()).collect(Collectors.toList());
Map<String, ApplicationRequirement> requirementsMap = new LinkedHashMap<>();
for (ApplicationProjectItemImpl req : reqs) {
ApplicationRequirement appReq = convertToRequirement(req);
requirementsMap.put(appReq.id, appReq);
}
for (ApplicationRequirement appReq : requirementsMap.values())
descriptor.requirements.add(appReq);
Map<String, ApplicationContentItem> contentItems = new LinkedHashMap<>();
Map<String, ApplicationComponent> components = new LinkedHashMap<>();
for (Entry<String, AbstractDescriptor> entry : itemToDescriptorMap.entrySet()) {
String itemId = entry.getKey();
ApplicationProjectItemImpl itemImpl = applicationContent.getItemsMap().get(itemId);
ApplicationContentItem contentItem = new ApplicationContentItem();
contentItem.id = itemImpl.getId();
contentItem.type = itemImpl.getType();
contentItem.componentId = entry.getValue().getDescriptorId();
contentItems.put(contentItem.id, contentItem);
ApplicationComponent component = convertToComponent(entry.getValue());
if (component == null) {
LOG.error("Failed converting descriptor [{}]/[{}] to component", entry.getValue().getDescriptorId(),
entry.getValue().type.name());
continue;
} else {
// components.put(entry.getKey(), component);
// exclude duplicates
components.putIfAbsent(component.getId(), component);
}
}
for (ApplicationContentItem item : contentItems.values())
descriptor.items.add(item);
List<ApplicationComponent> componentList = new ArrayList<>(components.values());
Collections.sort(componentList, new Comparator<ApplicationComponent>() {
@Override
public int compare(ApplicationComponent o1, ApplicationComponent o2) {
if (o1.priority > o2.priority)
return 1;
if (o1.priority < o2.priority)
return -1;
return 0;
}
});
descriptor.components.addAll(componentList);
}
public void saveDescriptor() {
File descriptorFile =
new File(Paths.get(buildContentRoot.getAbsolutePath(), EntaxyApplication.DESCRIPTOR_NAME)
.toAbsolutePath().toUri());
try (OutputStream bos = new FileOutputStream(descriptorFile)) {
JsonElement je = GSON.toJsonTree(descriptor);
String jsonData = je.toString();
bos.write(jsonData.getBytes());
} catch (Exception e) {
LOG.error("Error saving descriptor file", e);
}
}
protected ApplicationComponent convertToComponent(AbstractDescriptor descriptor) {
switch (descriptor.type) {
case BUNDLE:
return convertToComponent((BundleDescriptor) descriptor);
case RESOURCE:
return convertToComponent((ResourceDescriptor) descriptor);
case CONFIG:
return convertToComponent((ConfigDescriptor) descriptor);
default:
return null;
}
}
protected ApplicationComponent convertToComponent(BundleDescriptor descriptor) {
ApplicationComponent result = new ApplicationComponent();
result.id = descriptor.getDescriptorId();
result.internalLocation = descriptor.finalLocation;
result.mavenLocation = descriptor.finalMavenLocation;
result.priority = descriptor.priority;
result.type = ITEM_TYPE.BUNDLE;
String temp = descriptor.installLocation;
int index1 = temp.lastIndexOf(':');
if (index1 > 0) {
result.targetProtocol = temp.substring(0, index1);
temp = temp.substring(index1 + 1);
}
int index2 = temp.indexOf('?');
if (index2 > 0) {
result.targetQueryString = temp.substring(index2 + 1);
temp = temp.substring(0, index2);
}
result.targetLocation = temp;
return result;
}
protected ApplicationComponent convertToComponent(ResourceDescriptor descriptor) {
ApplicationComponent result = new ApplicationComponent();
result.id = descriptor.getDescriptorId();
result.internalLocation = descriptor.finalLocation;
result.mavenLocation = "";
result.targetLocation = descriptor.resourceUrl;
result.priority = 25;
result.type = ITEM_TYPE.RESOURCE;
result.targetLocation = descriptor.resourceUrl;
return result;
}
protected ApplicationComponent convertToComponent(ConfigDescriptor descriptor) {
ApplicationComponent result = new ApplicationComponent();
result.id = descriptor.getDescriptorId();
result.internalLocation = descriptor.finalLocation;
result.mavenLocation = descriptor.finalMavenLocation;
result.targetLocation = descriptor.pid + ".cfg";
result.priority = 25;
result.type = ITEM_TYPE.CONFIG;
return result;
}
protected ApplicationRequirement convertToRequirement(ApplicationProjectItemImpl sourceItem) {
ApplicationRequirement result = new ApplicationRequirement();
result.id = sourceItem.getId();
result.type = sourceItem.getType();
result.scope = sourceItem.getScope();
return result;
}
public void generateFeatures() {
Template template =
ServiceHelper.getInstance().getTemplateService().getTemplateById("applications.builder.features");
TemplateAwareGenerator generator = GeneratorFactory.createGenerator(template);
if (generator != null) {
String repoName = String.format("%s.%s-%s", coordinates.getGroupId(), coordinates.getArtifactId(),
coordinates.getVersion());
String featureName = coordinates.getGroupId().concat(".").concat(coordinates.getArtifactId());
Map<String, Object> params = new HashMap<>();
params.put("descriptor", descriptor);
params.put("repoName", repoName);
params.put("featureName", featureName);
params.put("featureVersion", coordinates.getVersion());
Generated generated;
try {
generated = generator.generate(template, params);
} catch (Exception e) {
LOG.error("Error generating features", e);
return;
}
if ((generated == null) || (generated.getObject() == null)) {
LOG.error("Generated NULL");
}
ArtifactCoordinates featuresCoordinates =
ArtifactCoordinates.fromUrl(coordinates.toMavenString()).classifier("features").type("xml");
String path = featuresCoordinates.toRepositoryPath();
File featuresFile = new File(Paths.get(bundleStorage.rootDirectory.getAbsolutePath(), path).toUri());
featuresFile.getAbsoluteFile().getParentFile().mkdirs();
try (OutputStream fos = new FileOutputStream(featuresFile)) {
fos.write(generated.getObject().toString().getBytes());
} catch (Exception e) {
LOG.error("Error writing features file", e);
}
descriptor.features = new ApplicationFeatures();
descriptor.features.id = featureName;
descriptor.features.internalLocation =
buildContentRoot.toPath().relativize(featuresFile.toPath()).toString().replace('\\', '/');
descriptor.features.mavenLocation = featuresCoordinates.toMavenString();
descriptor.features.targetProtocol = "mvn";
descriptor.features.targetLocation = descriptor.features.mavenLocation;
}
}
public void pack() {
File targetFile =
new File(Paths.get(buildRoot.getAbsolutePath(), "result", coordinates.toRepositoryPath()).toUri());
targetFile.getAbsoluteFile().getParentFile().mkdirs();
FolderBasedJarBuilder builder = new FolderBasedJarBuilder(targetFile, buildContentRoot);
builder.putAttribute("Entaxy-Application", coordinates.getArtifactId());
builder.putAttribute("Entaxy-ApplicationGroup", coordinates.getGroupId());
builder.putAttribute("Entaxy-ApplicationVersion", coordinates.getVersion());
try {
builder.loadFiles();
} catch (IllegalStateException | IOException e) {
LOG.error("Error building application file", e);
}
try {
builder.close();
} catch (IOException e) {
LOG.error("Error building application file", e);
return;
}
buildResult = targetFile;
}
public void clear() {
try {
FileUtils.deleteDirectory(buildRoot);
} catch (IOException e) {
LOG.error("Error clearing ApplicationBuilder", e);
}
}
public URL build() {
prepareContent();
generateDescriptor();
generateFeatures();
saveDescriptor();
pack();
if (buildResult == null)
return null;
try {
return buildResult.toURI().toURL();
} catch (MalformedURLException e) {
LOG.error("Error creating URL for [" + buildResult.getAbsolutePath() + "]", e);
return null;
}
}
public ApplicationDescriptor getDescriptor() {
return descriptor;
}
public File getBuildResult() {
return buildResult;
}
}

View File

@ -0,0 +1,101 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import org.apache.karaf.bundle.core.BundleInfo;
import org.apache.karaf.bundle.core.BundleService;
import org.osgi.framework.Bundle;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.integration.applications.impl.ServiceHelper;
public class BundleDescriptor extends AbstractDescriptor {
private static final Logger LOG = LoggerFactory.getLogger(BundleDescriptor.class);
public static BundleDescriptor forBundle(Bundle bundle) {
BundleDescriptor result = new BundleDescriptor();
result.readBundle(bundle);
return result;
}
@Override
protected TYPE getDescriptorType() {
return TYPE.BUNDLE;
}
String symbolicName;
long id;
// origin install location
String installLocation;
// origin maven artifact location
String mavenLocation;
// location from where we can download the artifact
String sourceLocation;
public void readBundle(Bundle bundle) {
symbolicName = bundle.getSymbolicName();
id = bundle.getBundleId();
priority = ((BundleStartLevel) bundle.adapt(BundleStartLevel.class)).getStartLevel();
// installLocation = bundle.getLocation();
try {
BundleService bundleService = ServiceHelper.getInstance().getBundleService();
BundleInfo bundleInfo = bundleService.getInfo(bundle);
installLocation = bundleInfo.getUpdateLocation();
} catch (Exception e) {
LOG.error("Error reading bundle info", e);
consistent = false;
return;
}
int index = installLocation.indexOf("mvn:");
if (index < 0) {
consistent = false;
return;
}
int index2 = installLocation.indexOf('?');
if (index2 > index)
mavenLocation = installLocation.substring(index + 4, index2);
else
mavenLocation = installLocation.substring(index + 4);
sourceLocation = installLocation.substring(index);
}
@Override
public String getDescriptorId() {
return symbolicName + "~" + getDescriptorType();
}
}

View File

@ -0,0 +1,118 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
public class BundleStorage extends AbstractStorage<BundleDescriptor> {
private static final Logger LOG = LoggerFactory.getLogger(BundleStorage.class);
final String dirName = "repository";
public BundleStorage(File parentDir, File tempDir) {
super(parentDir, tempDir);
}
@Override
protected String getStorageDir() {
return dirName;
}
@Override
public void prepare() {
for (BundleDescriptor descriptor : descriptors)
prepareDescriptor(descriptor);
}
@Override
public void prepareDescriptor(BundleDescriptor descriptor) {
ArtifactCoordinates bundleCoordinates = ArtifactCoordinates.fromUrl(descriptor.mavenLocation);
if (!CommonUtils.isValid(bundleCoordinates.getType()))
bundleCoordinates.type("jar");
File targetDir = new File(
Paths.get(rootDirectory.getAbsolutePath(),
bundleCoordinates.getGroupId().replace('.', '/'),
bundleCoordinates.getArtifactId(),
bundleCoordinates.getVersion()).toAbsolutePath().toUri());
targetDir.mkdirs();
String fileName = bundleCoordinates.getArtifactId().concat("-").concat(bundleCoordinates.getVersion())
.concat(CommonUtils.isValid(bundleCoordinates.getClassifier())
? "-".concat(bundleCoordinates.getClassifier())
: "")
.concat(".".concat(bundleCoordinates.getType()));
File targetFile = new File(Paths.get(targetDir.getAbsolutePath(), fileName).toAbsolutePath().toUri());
URL sourceUrl;
try {
sourceUrl = new URL(descriptor.sourceLocation);
} catch (MalformedURLException e) {
LOG.error("Error creating URL for [" + descriptor.mavenLocation + "]", e);
return;
}
try (
InputStream is = sourceUrl.openStream();
OutputStream os = new FileOutputStream(targetFile)) {
os.write(is.readAllBytes());
String targetLocation =
dirName.concat(targetFile.getAbsolutePath().replace(rootDirectory.getAbsolutePath(), ""))
.replace('\\', '/');
descriptor.finalLocation = targetLocation;
descriptor.finalMavenLocation = descriptor.mavenLocation;
} catch (IOException e) {
LOG.error("Error reading from URL [" + sourceUrl.toString() + "]", e);
return;
}
}
@Override
public BuildResult build(ArtifactCoordinates applicationCoordinates) {
return new BuildResult();
}
}

View File

@ -0,0 +1,87 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
public class ConfigDescriptor extends AbstractDescriptor {
public static ConfigDescriptor forConfig(String configId) {
ConfigDescriptor result = new ConfigDescriptor();
result.pid = configId.split(":")[0];
return result;
}
public static ConfigDescriptor forConfig(String configId, ArtifactCoordinates applicationCoordinates) {
ConfigDescriptor result = new ConfigDescriptor();
result.pid = configId.split(":")[0];
result.init(applicationCoordinates);
return result;
}
public static ConfigDescriptor forObjectConfig(EntaxyRuntimeObject configObject,
EntaxyRuntimeObject configuredObject) {
ConfigDescriptor result = new ConfigDescriptor();
result.pid = configObject.getId();
return result;
}
String pid;
// origin install location
String installLocation;
// origin maven artifact location
String mavenLocation;
// location from where we can download the artifact
String sourceLocation;
@Override
public String getDescriptorId() {
return pid + "~" + getDescriptorType();
}
@Override
protected TYPE getDescriptorType() {
return TYPE.CONFIG;
}
public void init(ArtifactCoordinates applicationCoordinates) {
ArtifactCoordinates localCoordinates = ArtifactCoordinates.fromUrl(applicationCoordinates.toMavenString());
localCoordinates.type("cfg").classifier(pid);
mavenLocation = localCoordinates.toMavenString();
sourceLocation = "mvn:" + mavenLocation;
installLocation = pid + ".cfg";
}
}

View File

@ -0,0 +1,118 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
public class ConfigStorage extends AbstractStorage<ConfigDescriptor> {
private static final Logger LOG = LoggerFactory.getLogger(ConfigStorage.class);
final String dirName = "repository";
protected ConfigStorage(File parentDir, File tempDir) {
super(parentDir, tempDir);
}
@Override
protected String getStorageDir() {
return dirName;
}
@Override
public void prepare() {
for (ConfigDescriptor desc : descriptors)
prepareDescriptor(desc);
}
@Override
public void prepareDescriptor(ConfigDescriptor descriptor) {
ArtifactCoordinates configCoordinates = ArtifactCoordinates.fromUrl(descriptor.mavenLocation);
if (!CommonUtils.isValid(configCoordinates.getType()))
configCoordinates.type("cfg");
String fileName = configCoordinates.toAssetName();
String repositoryPath = configCoordinates.toRepositoryPath();
String subfolder =
repositoryPath.substring(0, repositoryPath.length() - fileName.length());
File targetDir = new File(
Paths.get(rootDirectory.getAbsolutePath(),
subfolder).toAbsolutePath().toUri());
targetDir.mkdirs();
File targetFile = new File(Paths.get(targetDir.getAbsolutePath(), fileName).toAbsolutePath().toUri());
URL sourceUrl;
try {
sourceUrl = Paths.get(System.getProperty("karaf.etc"), descriptor.pid + ".cfg").toAbsolutePath().toUri()
.toURL();
} catch (MalformedURLException e) {
LOG.error("Error creating URL for [" + descriptor.mavenLocation + "]", e);
return;
}
try (
InputStream is = sourceUrl.openStream();
OutputStream os = new FileOutputStream(targetFile)) {
os.write(is.readAllBytes());
String targetLocation =
dirName.concat(targetFile.getAbsolutePath().replace(rootDirectory.getAbsolutePath(), ""))
.replace('\\', '/');
descriptor.finalLocation = targetLocation;
descriptor.finalMavenLocation = descriptor.mavenLocation;
} catch (IOException e) {
LOG.error("Error reading from URL [" + sourceUrl.toString() + "]", e);
return;
}
}
@Override
public BuildResult build(ArtifactCoordinates applicationCoordinates) {
return new BuildResult();
}
}

View File

@ -0,0 +1,54 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import ru.entaxy.esb.resources.EntaxyResource;
public class ResourceDescriptor extends AbstractDescriptor {
public static ResourceDescriptor forResource(EntaxyResource entaxyResource) {
ResourceDescriptor result = new ResourceDescriptor();
result.readResource(entaxyResource);
return result;
}
public String resourceUrl;
public void readResource(EntaxyResource entaxyResource) {
resourceUrl = entaxyResource.getURL();
}
@Override
protected TYPE getDescriptorType() {
return TYPE.RESOURCE;
}
@Override
public String getDescriptorId() {
return resourceUrl + "~" + getDescriptorType();
}
}

View File

@ -0,0 +1,188 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.integration.applications.impl.ServiceHelper;
import ru.entaxy.platform.integration.applications.impl.jar.FolderBasedJarBuilder;
public class ResourceStorage extends AbstractStorage<ResourceDescriptor> {
private static final Logger LOG = LoggerFactory.getLogger(ResourceStorage.class);
static final String startDirName = "resources/resources";
static final String subDirName = "ru/entaxy/resource";
static final String storageDirName = startDirName + "/" + subDirName;
protected File startDir;
public ResourceStorage(File parentDir, File tempDir) {
super(parentDir, tempDir);
this.startDir = new File(Paths.get(parentDir.getAbsolutePath(), startDirName).toAbsolutePath().toUri());
}
@Override
protected String getStorageDir() {
return storageDirName;
}
@Override
public void prepare() {
for (ResourceDescriptor descriptor : descriptors)
prepareDescriptor(descriptor);
}
@Override
public void prepareDescriptor(ResourceDescriptor descriptor) {
EntaxyResource entaxyResource =
ServiceHelper.getInstance().getEntaxyResourceService().getResource(descriptor.resourceUrl);
if (!entaxyResource.exists()) {
LOG.error("Resource doesn't exist: [{}]", descriptor.resourceUrl);
return;
}
String targetPath = descriptor.resourceUrl.replace(':', '/');
File targetFile = new File(Paths.get(rootDirectory.getAbsolutePath(), targetPath).toAbsolutePath().toUri());
targetFile.getParentFile().mkdirs();
try (InputStream is = entaxyResource.getInputStream();
OutputStream os = new FileOutputStream(targetFile)) {
os.write(is.readAllBytes());
String targetLocation =
storageDirName.concat(targetFile.getAbsolutePath().replace(rootDirectory.getAbsolutePath(), ""))
.replace('\\', '/');
descriptor.finalLocation = targetLocation;
} catch (Exception e) {
LOG.error("Error reading resource [" + descriptor.resourceUrl + "]", e);
return;
}
}
@Override
public BuildResult build(ArtifactCoordinates applicationCoordinates) {
// first check if we have resources
try (Stream<Path> pathStream = Files.walk(startDir.getAbsoluteFile().toPath())) {
long count = pathStream
.parallel()
.filter(p -> !p.toFile().isDirectory())
.count();
if (count == 0)
return new BuildResult();
} catch (IOException e) {
LOG.error("ERROR checking the directory [" + startDir.getAbsolutePath() + "]", e);
return new BuildResult();
}
ArtifactCoordinates jarCoordinates = ArtifactCoordinates.fromUrl(applicationCoordinates.toString());
jarCoordinates.type("jar").classifier("resources");
File jarFile = new File(Paths
.get(tempDir.getAbsolutePath(), ".resources", jarCoordinates.getGroupId().replace('.', '/'),
jarCoordinates.getArtifactId(),
jarCoordinates.getVersion(),
jarCoordinates.getArtifactId().concat("-")
.concat(jarCoordinates.getVersion().concat("-")
.concat(jarCoordinates.getClassifier().concat(".")
.concat(jarCoordinates.getType()))))
.toAbsolutePath().toUri());
jarFile.getAbsoluteFile().getParentFile().mkdirs();
String bundleName = String.format("APPLICATION :: %s :: %s :: RESOURCES", jarCoordinates.getArtifactId(),
jarCoordinates.getVersion());
String bundleDecription = bundleName;
String bundleSymboliName =
jarCoordinates.getGroupId().concat(".").concat(jarCoordinates.getArtifactId()).concat(".resources");
FolderBasedJarBuilder jarBuilder = new FolderBasedJarBuilder(jarFile, startDir);
jarBuilder.getOsgiInfo()
.name(bundleName)
.symbolicName(bundleSymboliName)
.description(bundleDecription)
.version(jarCoordinates.getVersion())
.update();
jarBuilder.putAttribute("Entaxy-Resource-Provider", "true");
try {
jarBuilder.loadFiles();
} catch (IllegalStateException | IOException e) {
LOG.error("Error loading files", e);
}
try {
jarBuilder.close();
} catch (IOException e) {
LOG.error("Error closing jar", e);
}
BundleDescriptor bundleDesc = new BundleDescriptor();
bundleDesc.id = -1;
bundleDesc.symbolicName = bundleSymboliName;
bundleDesc.mavenLocation = jarCoordinates.toString();
bundleDesc.installLocation = "mvn:" + bundleDesc.mavenLocation;
try {
bundleDesc.sourceLocation = jarFile.getAbsoluteFile().toURI().toURL().toString();
} catch (MalformedURLException e) {
bundleDesc.sourceLocation = "file:///" + jarFile.getAbsolutePath().replace('\\', '/');
}
bundleDesc.priority = 90;
BuildResult result = new BuildResult();
result.newDescriptors.put(bundleSymboliName, bundleDesc);
for (ResourceDescriptor desc : descriptors)
result.changes.put(desc.resourceUrl, bundleDesc);
return result;
}
}

View File

@ -0,0 +1,61 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.jar;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import org.apache.commons.io.FileUtils;
public class FolderBasedJarBuilder extends JarBuilder {
File rootFolder;
public FolderBasedJarBuilder(File targetFile, File rootFolder) {
super(targetFile);
this.rootFolder = rootFolder;
}
public void loadFiles() throws FileNotFoundException, IOException, IllegalStateException {
if (Status.FINALIZED.equals(status))
throw new IllegalStateException("JarBuilder is finalized");
if (Status.NEW.equals(status))
open();
Iterator<File> iterator = FileUtils.iterateFiles(rootFolder, null, true);
while (iterator.hasNext()) {
File file = iterator.next();
String name = file.getAbsolutePath().replace(rootFolder.getAbsolutePath(), "").replace('\\', '/');
if (name.startsWith("/"))
name = name.substring(1);
addFile(file, name);
}
}
}

View File

@ -0,0 +1,186 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.jar;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
public class JarBuilder {
public enum Status {
NEW,
OPENED,
FINALIZED
}
public static interface OsgiAttributes {
Name NAME = new Name("Bundle-Name");
Name SYMBOLIC_NAME = new Name("Bundle-SymbolicName");
Name DESCRIPTION = new Name("Bundle-Description");
Name DOC_URL = new Name("Bundle-DocURL");
Name MANIFEST_VERSION = new Name("Bundle-ManifestVersion");
Name VENDOR = new Name("Bundle-Vendor");
Name VERSION = new Name("Bundle-Version");
}
protected Manifest manifest;
protected Status status = Status.NEW;
protected File targetFile;
protected Map<Name, Object> osgiInfo = new HashMap<>();
protected JarOutputStream jarOutputStream;
public class OsgiInfo {
public OsgiInfo() {
String fileName = targetFile.getName();
if (fileName.lastIndexOf('.') > 0)
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
osgiInfo.put(OsgiAttributes.NAME, fileName);
osgiInfo.put(OsgiAttributes.SYMBOLIC_NAME, fileName);
osgiInfo.put(OsgiAttributes.DESCRIPTION, fileName);
osgiInfo.put(OsgiAttributes.DOC_URL, "https://entaxy.ru/");
osgiInfo.put(OsgiAttributes.VENDOR, "Entaxy");
osgiInfo.put(OsgiAttributes.VERSION, "1.0.0");
}
public OsgiInfo name(String name) {
osgiInfo.put(OsgiAttributes.NAME, name);
return this;
}
public OsgiInfo symbolicName(String name) {
osgiInfo.put(OsgiAttributes.SYMBOLIC_NAME, name);
return this;
}
public OsgiInfo description(String desc) {
osgiInfo.put(OsgiAttributes.DESCRIPTION, desc);
return this;
}
public OsgiInfo docUrl(String url) {
osgiInfo.put(OsgiAttributes.DOC_URL, url);
return this;
}
public OsgiInfo vendor(String vendor) {
osgiInfo.put(OsgiAttributes.VENDOR, vendor);
return this;
}
public OsgiInfo version(String version) {
osgiInfo.put(OsgiAttributes.VERSION, version);
return this;
}
public void update() {
updateOsgiInfo();
}
}
public JarBuilder(File targetFile) {
this.targetFile = targetFile;
this.targetFile.getAbsoluteFile().getParentFile().mkdirs();
this.manifest = new Manifest();
initializeManifest();
this.osgiInfo.put(OsgiAttributes.MANIFEST_VERSION, "2");
}
public boolean isReady() {
return Status.FINALIZED.equals(status);
}
protected void initializeManifest() {
this.manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
}
public void updateOsgiInfo() {
if (Status.NEW.equals(status))
for (Entry<Name, Object> entry : osgiInfo.entrySet())
this.manifest.getMainAttributes().put(entry.getKey(), entry.getValue());
}
public OsgiInfo getOsgiInfo() {
return new OsgiInfo();
}
public void putAttribute(String name, String value) {
if (status.equals(Status.NEW))
this.manifest.getMainAttributes().putValue(name, value);
}
public void open() throws FileNotFoundException, IOException {
status = Status.OPENED;
jarOutputStream = new JarOutputStream(new FileOutputStream(targetFile), this.manifest);
}
public void addFile(File source, String targetLocation) throws IllegalStateException, IOException {
if (!Status.OPENED.equals(status))
throw new IllegalStateException("JarBuilder is not in OPENED status");
JarEntry entry = new JarEntry(targetLocation);
entry.setTime(source.lastModified());
jarOutputStream.putNextEntry(entry);
try (
BufferedInputStream in = new BufferedInputStream(new FileInputStream(source))) {
byte[] buffer = new byte[1024];
while (true) {
int count = in.read(buffer);
if (count == -1) {
break;
}
jarOutputStream.write(buffer, 0, count);
}
} finally {
jarOutputStream.closeEntry();
}
}
public File close() throws IOException {
jarOutputStream.close();
status = Status.FINALIZED;
return targetFile;
}
}

View File

@ -0,0 +1,305 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.google.gson.JsonObject;
import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.integration.applications.ApplicationProjectContent;
import ru.entaxy.platform.integration.applications.ApplicationProjectItem;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.exceptions.ItemException;
import ru.entaxy.platform.integration.applications.exceptions.ItemIsGhostException;
import ru.entaxy.platform.integration.applications.exceptions.ItemIsPlatformException;
import ru.entaxy.platform.integration.applications.exceptions.ItemNotFoundException;
import ru.entaxy.platform.integration.applications.impl.ServiceHelper;
import ru.entaxy.platform.integration.applications.impl.project.item.ItemFactory;
import ru.entaxy.platform.integration.applications.impl.project.model.ContentModel;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ContentModelItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyObjectItem;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectResource;
public class ApplicationProjectContentImpl implements ApplicationProjectContent {
final protected Map<String, Object> properties = new HashMap<>();
final protected Map<String, ApplicationProjectItemImpl> items = new HashMap<>();
final protected Object itemsLock = new Object();
protected ApplicationProjectItemImpl getItemImpl(String itemId) throws ItemException {
ApplicationProjectItemImpl result = items.get(itemId);
if (result == null)
throw new ItemNotFoundException(null, null, itemId);
return result;
}
protected JsonObject getAsJson() {
ContentModel contentModel = new ContentModel();
contentModel.update(this);
return contentModel.getAsJson();
}
public String marshall() {
return getAsJson().toString();
}
public void unmarshall(String data) {
ContentModel contentModel = ContentModel.load(JSONUtils.getJsonRootObject(data));
properties.put(STANDARD_PROPERTIES.APPLICATION, contentModel.getApplication());
properties.put(STANDARD_PROPERTIES.GROUP, contentModel.getGroup());
properties.put(STANDARD_PROPERTIES.VERSION, contentModel.getVersion());
properties.put(STANDARD_PROPERTIES.CREATED_ON, contentModel.getCreatedOn());
properties.put(STANDARD_PROPERTIES.CREATED_BY, contentModel.getCreatedBy());
properties.put(STANDARD_PROPERTIES.MODIFIED_ON, contentModel.getModifiedOn());
properties.put(STANDARD_PROPERTIES.MODIFIED_BY, contentModel.getModifiedBy());
for (ContentModelItem modelItem : contentModel.getIncludedItems()) {
ApplicationProjectItem item;
switch (modelItem.getItemType()) {
case BUNDLE:
continue;
case CONFIG:
case OBJECT:
EntaxyRuntimeObject runtimeObject = ServiceHelper.getInstance().getEntaxyRuntimeObjectService()
.getRuntimeObject(modelItem.getId());
item = addObject(runtimeObject);
break;
case RESOURCE:
EntaxyResource entaxyResource =
ServiceHelper.getInstance().getEntaxyResourceService().getResource(modelItem.getId());
item = addResource(entaxyResource);
break;
default:
continue;
}
ApplicationProjectItemImpl itemImpl = items.get(item.getId());
itemImpl.setScope(modelItem.getItemScope());
}
for (ContentModelItem modelItem : contentModel.getRequiredItems()) {
ApplicationProjectItem item;
switch (modelItem.getItemType()) {
case BUNDLE:
continue;
case CONFIG:
case OBJECT:
EntaxyRuntimeObject runtimeObject = ServiceHelper.getInstance().getEntaxyRuntimeObjectService()
.getRuntimeObject(modelItem.getId());
item = addObject(runtimeObject);
break;
case RESOURCE:
EntaxyResource entaxyResource =
ServiceHelper.getInstance().getEntaxyResourceService().getResource(modelItem.getId());
item = addResource(entaxyResource);
break;
default:
continue;
}
ApplicationProjectItemImpl itemImpl = items.get(item.getId());
itemImpl.setScope(modelItem.getItemScope());
itemImpl.setRequired(modelItem.isRequired());
itemImpl.setIgnored(modelItem.isIgnored());
}
}
public Map<String, ApplicationProjectItemImpl> getItemsMap() {
return items;
}
@Override
public List<ApplicationProjectItem> getItems() {
return new ArrayList<>(items.values());
}
@Override
public <T extends ApplicationProjectItem> List<T> getItems(Class<T> itemClass) {
return getItems().stream().filter(item -> itemClass.isInstance(item)).map(item -> itemClass.cast(item))
.collect(Collectors.toList());
}
@Override
public void addItem(ApplicationProjectItem item) throws ItemException {
ApplicationProjectItemImpl itemImpl = getItemImpl(item.getId());
if (!item.isRequired())
// already added
return;
if (item.isGhost())
throw new ItemIsGhostException(null, null, item.getId());
if (item.isPlatform())
throw new ItemIsPlatformException(null, null, item.getId());
itemImpl.setIgnored(false);
itemImpl.setRequired(false);
if (item.getType().equals(EntaxyApplication.ITEM_TYPE.OBJECT)) {
EntaxyRuntimeObject runtimeObject = ServiceHelper.getInstance().getEntaxyRuntimeObjectService()
.getRuntimeObject(((EntaxyObjectItem) item).getObject().getObjectFullId());
Map<String, ApplicationProjectItemImpl> linkedItems = new HashMap<>();
ItemFactory.INSTANCE.processDependencies(itemImpl, runtimeObject, items, linkedItems);
processColocatedObjects(runtimeObject, linkedItems);
items.putAll(linkedItems);
}
}
@Override
public void ignoreItem(ApplicationProjectItem item) throws ItemException {
ApplicationProjectItemImpl itemImpl = getItemImpl(item.getId());
itemImpl.setIgnored(true);
itemImpl.setRequired(true);
for (ApplicationProjectItem req : itemImpl.getRequirements()) {
if (!req.isRequired())
// that means it's added
continue;
if (req.getRequiredBy().size() > 1)
// required item is required by someone else
continue;
if (req.getRequiredBy().isEmpty()) {
// something strange
ignoreItem(req);
continue;
}
ApplicationProjectItem backRef = req.getRequiredBy().get(0);
if (backRef == null) {
// something strange
ignoreItem(req);
continue;
}
if (backRef.getId().equals(item.getId())) {
ignoreItem(req);
}
}
}
@Override
public void removeItem(ApplicationProjectItem item) throws ItemException {
ApplicationProjectItemImpl itemImpl = getItemImpl(item.getId());
if (itemImpl.getRequiredBy().isEmpty()) {
for (ApplicationProjectItem required : itemImpl.getRequirements()) {
// unlink required items
try {
ApplicationProjectItemImpl requiredImpl = getItemImpl(required.getId());
itemImpl.removeRequired(requiredImpl);
} catch (Exception ignore) {
// NOOP
}
}
synchronized (itemsLock) {
items.remove(itemImpl.getId());
}
} else if (!item.isPlatform()) {
// just mark as s requirement
itemImpl.setRequired(true);
itemImpl.setIgnored(false);
}
}
@Override
public ApplicationProjectItem addObject(EntaxyRuntimeObject runtimeObject) {
synchronized (itemsLock) {
Map<String, ApplicationProjectItemImpl> linked = new HashMap<>();
ApplicationProjectItemImpl result = ItemFactory.INSTANCE.createItem(runtimeObject, items, linked);
result.setScope(EntaxyApplication.ITEM_SCOPE.RUNTIME);
items.put(result.getId(), result);
items.putAll(linked);
processColocatedObjects(runtimeObject, linked);
if (result.isPlatform()) {
result.setRequired(true);
result.setIgnored(true);
} else {
result.setRequired(false);
}
return result;
}
}
protected void processColocatedObjects(EntaxyRuntimeObject runtimeObject,
Map<String, ApplicationProjectItemImpl> linked) {
List<EntaxyRuntimeObject> colocatedObjects = runtimeObject.getColocatedObjects();
for (EntaxyRuntimeObject obj : colocatedObjects) {
ApplicationProjectItemImpl item;
if (items.containsKey(obj.getObjectFullId())) {
item = items.get(obj.getObjectFullId());
} else {
linked = new HashMap<>();
item = ItemFactory.INSTANCE.createItem(obj, items, linked);
if (!items.containsKey(item.getId()))
items.put(item.getId(), item);
items.putAll(linked);
}
if (item.isPlatform()) {
item.setRequired(true);
item.setIgnored(true);
} else {
item.setRequired(false);
item.setIgnored(false);
}
item.setScope(EntaxyApplication.ITEM_SCOPE.RUNTIME);
}
}
@Override
public ApplicationProjectItem addResource(EntaxyRuntimeObjectResource runtimeObjectResource) {
synchronized (itemsLock) {
ApplicationProjectItemImpl result = ItemFactory.INSTANCE.createItem(runtimeObjectResource, items);
items.put(result.getId(), result);
return result;
}
}
@Override
public ApplicationProjectItem addResource(EntaxyResource entaxyResource) {
synchronized (itemsLock) {
ApplicationProjectItemImpl result = ItemFactory.INSTANCE.createItem(entaxyResource, items);
result.setScope(EntaxyApplication.ITEM_SCOPE.RUNTIME);
items.put(result.getId(), result);
return result;
}
}
@Override
public Map<String, Object> getProperties() {
return properties;
}
}

View File

@ -0,0 +1,175 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import ru.entaxy.platform.integration.applications.ApplicationProjectItem;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.impl.project.item.ColocationGroup;
public abstract class ApplicationProjectItemImpl implements ApplicationProjectItem {
boolean isRequired = false;
boolean isIgnored = false;
boolean isPlatform = false;
EntaxyApplication.ITEM_SCOPE scope = EntaxyApplication.ITEM_SCOPE.DESIGN;
EntaxyApplication.ITEM_TYPE type;
Map<String, ApplicationProjectItemImpl> required = new HashMap<>();
Map<String, ApplicationProjectItemImpl> requiredBy = new HashMap<>();
ColocationGroup colocationGroup;
public void setPlatform(Boolean platform) {
isPlatform = platform;
}
public void setRequired(boolean isRequired) {
this.isRequired = isRequired;
}
public void setIgnored(boolean isIgnored) {
this.isIgnored = isIgnored;
}
public void addRequired(ApplicationProjectItemImpl item) {
required.put(item.getId(), item);
item.addRequiredBy(this);
}
public void removeRequired(ApplicationProjectItemImpl item) {
item.removeRequiredBy(this);
required.remove(item.getId());
}
protected void addRequiredBy(ApplicationProjectItemImpl item) {
requiredBy.put(item.getId(), item);
}
protected void removeRequiredBy(ApplicationProjectItemImpl item) {
requiredBy.remove(item.getId());
}
public ColocationGroup getColocationGroup() {
return colocationGroup;
}
public void colocate(ColocationGroup colocationGroup) {
if (colocationGroup == null) {
if (this.colocationGroup != null)
this.colocationGroup.remove(this);
}
this.colocationGroup = colocationGroup;
if (this.colocationGroup != null)
this.colocationGroup.add(this);
}
public void updateScope(EntaxyApplication.ITEM_SCOPE newScope) {
// we'll leave most strict scope as a result
// leave scope as is
if (EntaxyApplication.ITEM_SCOPE.DESIGN.equals(newScope))
return;
scope = newScope;
}
public void setScope(EntaxyApplication.ITEM_SCOPE scope) {
this.scope = scope;
}
protected void setType(EntaxyApplication.ITEM_TYPE type) {
this.type = type;
}
@Override
public EntaxyApplication.ITEM_SCOPE getScope() {
return scope;
}
@Override
public EntaxyApplication.ITEM_TYPE getType() {
return type;
}
@Override
public boolean isGhost() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isRequired() {
return isRequired;
}
@Override
public boolean isPlatform() {
return isPlatform;
}
@Override
public List<ApplicationProjectItem> getRequiredBy() {
return new ArrayList<>(this.requiredBy.values());
}
@Override
public List<ApplicationProjectItem> getRequirements() {
return new ArrayList<>(this.required.values());
}
@Override
public boolean isIgnored() {
return isIgnored;
}
@Override
public void ignore() {
setIgnored(true);
}
@Override
public List<ApplicationProjectItem> getColocated() {
if (this.colocationGroup == null)
return Collections.emptyList();
return this.colocationGroup.getMembers().stream().filter(item -> !item.getId().equalsIgnoreCase(getId()))
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,62 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.item;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
import ru.entaxy.platform.integration.applications.item.project.EntaxyBundleItem;
public class BundleItemImpl extends ApplicationProjectItemImpl implements EntaxyBundleItem {
protected long bundleId;
protected String bundleSymbolicName;
public BundleItemImpl(long bundleId, String bundleSymbolicName) {
super();
this.bundleId = bundleId;
this.bundleSymbolicName = bundleSymbolicName;
setType(EntaxyApplication.ITEM_TYPE.BUNDLE);
}
@Override
public long getBundleId() {
return bundleId;
}
@Override
public String getId() {
return bundleSymbolicName;
}
@Override
public String getBundleSymbolicName() {
return bundleSymbolicName;
}
}

View File

@ -0,0 +1,66 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.item;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
public class ColocationGroup {
Map<String, ApplicationProjectItemImpl> members;
Object membersLock = new Object();
String id;
public ColocationGroup(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void add(ApplicationProjectItemImpl item) {
synchronized (membersLock) {
members.put(item.getId(), item);
}
}
public void remove(ApplicationProjectItemImpl item) {
synchronized (membersLock) {
members.remove(item.getId());
}
}
public List<ApplicationProjectItemImpl> getMembers() {
return new ArrayList<>(this.members.values());
}
}

View File

@ -0,0 +1,58 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.item;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.item.project.EntaxyConfigItem;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectContainer;
public class ConfigItemImpl extends ObjectItemImpl implements EntaxyConfigItem {
public static ConfigItemImpl create(EntaxyRuntimeObject runtimeObject) throws IllegalArgumentException {
EntaxyRuntimeObjectContainer container = runtimeObject.getContainer();
if (!"bundle".equals(container.getType()))
throw new IllegalArgumentException("Object container is not a bundle: " + runtimeObject.getObjectFullId());
String containerId = container.getId();
long bundleId = -1;
String bundleSymbolicName = container.getName();
try {
bundleId = Long.parseLong(containerId);
if (bundleId <= 0)
throw new Exception();
} catch (Exception e) {
throw new IllegalArgumentException("Object container id is not a bundle id: ["
+ runtimeObject.getObjectFullId() + "] [" + containerId + "]");
}
return new ConfigItemImpl(bundleId, bundleSymbolicName, runtimeObject);
}
public ConfigItemImpl(long bundleId, String bundleSymbolicName, EntaxyRuntimeObject runtimeObject) {
super(bundleId, bundleSymbolicName, runtimeObject);
setType(EntaxyApplication.ITEM_TYPE.CONFIG);
}
}

View File

@ -0,0 +1,168 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.item;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.platform.base.objects.EntaxyObject.OBJECT_RELATION;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectResource;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeRelation;
public class ItemFactory {
static public final ItemFactory INSTANCE = new ItemFactory();
static public final List<String> CONFIG_TYPES = Arrays.asList(new String[] {"entaxy.runtime.config"});
private ItemFactory() {
}
public ApplicationProjectItemImpl createItem(EntaxyRuntimeObject runtimeObject,
Map<String, ApplicationProjectItemImpl> currentStorage,
final Map<String, ApplicationProjectItemImpl> linkedItems) {
return createItem(runtimeObject, currentStorage, linkedItems, false, false);
}
public ApplicationProjectItemImpl createItem(EntaxyRuntimeObject runtimeObject,
Map<String, ApplicationProjectItemImpl> currentStorage,
final Map<String, ApplicationProjectItemImpl> linkedItems, boolean skipDependencies, boolean skipISR) {
String fullId = runtimeObject.getObjectFullId();
if (currentStorage.containsKey(fullId))
return currentStorage.get(fullId);
if (linkedItems.containsKey(fullId))
return linkedItems.get(fullId);
boolean isConfig = false;
for (String type : CONFIG_TYPES)
if (runtimeObject.getType().startsWith(type))
isConfig = true;
ApplicationProjectItemImpl result;
if (isConfig) {
result = ConfigItemImpl.create(runtimeObject);
} else {
result = ObjectItemImpl.create(runtimeObject);
}
if (!skipDependencies) {
processDependencies(result, runtimeObject, currentStorage, linkedItems, skipISR, false);
}
for (ApplicationProjectItemImpl item : linkedItems.values())
if (!currentStorage.containsKey(item.getId()))
item.setRequired(true);
return result;
}
public void processDependencies(ApplicationProjectItemImpl targetItem, EntaxyRuntimeObject runtimeObject,
Map<String, ApplicationProjectItemImpl> currentStorage,
final Map<String, ApplicationProjectItemImpl> linkedItems) {
processDependencies(targetItem, runtimeObject, currentStorage, linkedItems, false, true);
}
public void processDependencies(ApplicationProjectItemImpl targetItem, EntaxyRuntimeObject runtimeObject,
Map<String, ApplicationProjectItemImpl> currentStorage,
final Map<String, ApplicationProjectItemImpl> linkedItems, boolean skipISR, boolean skipComposition) {
List<EntaxyRuntimeRelation> relations;
if (!skipISR) {
// process object relations: incoming aggregations and compositions
relations = runtimeObject.getIncomiingSubordRelations();
for (EntaxyRuntimeRelation rel : relations) {
EntaxyRuntimeObject object = rel.getMain();
ApplicationProjectItemImpl item = createItem(object, currentStorage, linkedItems, false, false);
targetItem.addRequired(item);
item.updateScope(EntaxyApplication.ITEM_SCOPE.convert(rel.getScope()));
if (!currentStorage.containsKey(item.getId()))
item.setRequired(true);
if (!linkedItems.containsKey(item.getId()))
linkedItems.put(item.getId(), item);
}
}
// process object relations: outgoing dependencies and uses
relations = runtimeObject.getRelations(OBJECT_RELATION.DEPENDENCY);
relations.addAll(runtimeObject.getRelations(OBJECT_RELATION.USE));
for (EntaxyRuntimeRelation rel : relations) {
EntaxyRuntimeObject object = rel.getMain();
ApplicationProjectItemImpl item = createItem(object, currentStorage, linkedItems);
item.updateScope(EntaxyApplication.ITEM_SCOPE.convert(rel.getScope()));
targetItem.addRequired(item);
if (!currentStorage.containsKey(item.getId()))
item.setRequired(true);
if (!linkedItems.containsKey(item.getId()))
linkedItems.put(item.getId(), item);
}
if (!skipComposition) {
//add default route as mandatory
relations = runtimeObject.getRelations(OBJECT_RELATION.COMPOSITION);
for (EntaxyRuntimeRelation rel : relations) {
EntaxyRuntimeObject object = rel.getTarget();
ApplicationProjectItemImpl item = createItem(object, currentStorage, linkedItems, false, true);
item.updateScope(EntaxyApplication.ITEM_SCOPE.convert(rel.getScope()));
item.addRequired(targetItem);
if (!currentStorage.containsKey(item.getId()))
item.setRequired(true);
if (!linkedItems.containsKey(item.getId()))
linkedItems.put(item.getId(), item);
}
}
// process object resources
List<EntaxyRuntimeObjectResource> resources = runtimeObject.getResources();
for (EntaxyRuntimeObjectResource resource : resources) {
ApplicationProjectItemImpl item = createItem(resource, currentStorage);
item.updateScope(EntaxyApplication.ITEM_SCOPE.convert(resource.getScope()));
targetItem.addRequired(item);
if (!currentStorage.containsKey(item.getId()))
item.setRequired(true);
if (!linkedItems.containsKey(item.getId()))
linkedItems.put(item.getId(), item);
}
}
public ApplicationProjectItemImpl createItem(EntaxyRuntimeObjectResource objectResource,
Map<String, ApplicationProjectItemImpl> currentStorage) {
return new ResourceItemImpl(objectResource);
}
public ApplicationProjectItemImpl createItem(EntaxyResource entaxyResource,
Map<String, ApplicationProjectItemImpl> currentStorage) {
return new ResourceItemImpl(entaxyResource);
}
}

View File

@ -0,0 +1,77 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.item;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.item.project.EntaxyObjectItem;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectContainer;
public class ObjectItemImpl extends BundleItemImpl implements EntaxyObjectItem {
public static ObjectItemImpl create(EntaxyRuntimeObject runtimeObject) throws IllegalArgumentException {
EntaxyRuntimeObjectContainer container = runtimeObject.getContainer();
if (!"bundle".equals(container.getType()))
throw new IllegalArgumentException("Object container is not a bundle: " + runtimeObject.getObjectFullId());
String containerId = container.getId();
long bundleId = -1;
String bundleSymbolicName = container.getName();
try {
bundleId = Long.parseLong(containerId);
if (bundleId <= 0)
throw new Exception();
} catch (Exception e) {
throw new IllegalArgumentException("Object container id is not a bundle id: ["
+ runtimeObject.getObjectFullId() + "] [" + containerId + "]");
}
return new ObjectItemImpl(bundleId, bundleSymbolicName, runtimeObject);
}
protected EntaxyRuntimeObject runtimeObject;
public ObjectItemImpl(long bundleId, String bundleSymbolicName, EntaxyRuntimeObject runtimeObject) {
super(bundleId, bundleSymbolicName);
this.runtimeObject = runtimeObject;
Object isPlatform = runtimeObject.getAttribute("platform");
if ("true".equals(isPlatform)) {
this.setPlatform(true);
this.setIgnored(true);
this.setRequired(true);
}
setType(EntaxyApplication.ITEM_TYPE.OBJECT);
}
@Override
public String getId() {
return runtimeObject.getObjectFullId();
}
@Override
public EntaxyRuntimeObject getObject() {
return this.runtimeObject;
}
}

View File

@ -0,0 +1,60 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.item;
import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
import ru.entaxy.platform.integration.applications.item.project.EntaxyResourceItem;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectResource;
public class ResourceItemImpl extends ApplicationProjectItemImpl implements EntaxyResourceItem {
protected EntaxyResource entaxyResource;
public ResourceItemImpl(EntaxyRuntimeObjectResource objectResource) {
super();
this.entaxyResource = objectResource.getResource();
setType(EntaxyApplication.ITEM_TYPE.RESOURCE);
}
public ResourceItemImpl(EntaxyResource entaxyResource) {
super();
this.entaxyResource = entaxyResource;
setType(EntaxyApplication.ITEM_TYPE.RESOURCE);
}
@Override
public String getId() {
return entaxyResource.getURL();
}
@Override
public EntaxyResource getResource() {
return entaxyResource;
}
}

View File

@ -0,0 +1,49 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.base.support.JSONUtils.ObjectWrapper;
public class ContentChecker extends JSONUtils.ObjectChecker {
public ContentModel contentModel;
public ContentChecker(ContentModel contentModel) {
super();
this.contentModel = contentModel;
}
@Override
public ObjectWrapper checkObject(JsonObject object) {
if (ContentModelItemWrapper.isModelItem(object))
return new ContentModelItemWrapper(this.contentModel);
return null;
}
}

View File

@ -0,0 +1,248 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.JSONUtils.JsonTraverse;
import ru.entaxy.platform.integration.applications.ApplicationProjectContent;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectContentImpl;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
import ru.entaxy.platform.integration.applications.impl.project.model.item.BundleItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ConfigItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ContentModelItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ObjectItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ResourceItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyBundleItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyConfigItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyObjectItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyResourceItem;
public class ContentModel {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static ContentModel load(JsonObject jsonObject) {
ContentModel result = GSON.fromJson(jsonObject, ContentModel.class);
JsonTraverse traverser = new JsonTraverse().checker(new ContentChecker(result));
traverser.traverse(jsonObject);
return result;
}
String application = "";
String group = "";
String version = "";
String createdOn = Calendar.getInstance().getTimeInMillis() + "";
String createdBy = "";
String modifiedOn = "";
String modifiedBy = "";
transient List<ContentModelItem> requiredItems = new ArrayList<>();
transient List<ContentModelItem> includedItems = new ArrayList<>();
public void update(ApplicationProjectContentImpl applicationContentImpl) {
application = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.APPLICATION, application).toString();
group = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.GROUP, group).toString();
version = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.VERSION, version).toString();
createdOn = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.CREATED_ON, createdOn).toString();
createdBy = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.CREATED_BY, createdBy).toString();
modifiedOn = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.MODIFIED_ON, modifiedOn).toString();
modifiedBy = applicationContentImpl.getProperties()
.getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.MODIFIED_BY, modifiedBy).toString();
requiredItems.clear();
includedItems.clear();
for (ApplicationProjectItemImpl item : applicationContentImpl.getItemsMap().values()) {
List<ContentModelItem> targetList;
if (item.isRequired())
targetList = requiredItems;
else
targetList = includedItems;
ContentModelItem converted = convert(item);
targetList.add(converted);
}
}
public JsonObject getAsJson() {
JsonElement je = GSON.toJsonTree(this, ContentModel.class);
if (!je.isJsonObject()) {
return new JsonObject();
}
JsonObject result = je.getAsJsonObject();
// add requirements
JsonArray ja = new JsonArray();
for (ContentModelItem item : requiredItems) {
JsonElement itemElement = GSON.toJsonTree(item, item.getClass());
ja.add(itemElement);
}
result.add("requirements", ja);
// add items
ja = new JsonArray();
for (ContentModelItem item : includedItems) {
JsonElement itemElement = GSON.toJsonTree(item, item.getClass());
ja.add(itemElement);
}
result.add("items", ja);
return result;
}
protected ContentModelItem convert(ApplicationProjectItemImpl item) {
ContentModelItem result = null;
switch (item.getType()) {
case BUNDLE:
result = new BundleItem();
break;
case OBJECT:
result = new ObjectItem();
break;
case CONFIG:
result = new ConfigItem();
break;
case RESOURCE:
result = new ResourceItem();
break;
default:
return null;
}
result.setContentModel(this);
result.setId(item.getId());
result.setGhost(item.isGhost());
result.setIgnored(item.isIgnored());
result.setItemScope(item.getScope());
result.setItemType(item.getType());
result.setRequired(item.isRequired());
if (item.getColocationGroup() != null)
result.setColocationGroupId(item.getColocationGroup().getId());
if (item instanceof EntaxyBundleItem) {
BundleItem typedResult = (BundleItem) result;
EntaxyBundleItem typedOrigin = (EntaxyBundleItem) item;
typedResult.setBundleId(typedOrigin.getBundleId());
typedResult.setBundleSymbolicName(typedOrigin.getBundleSymbolicName());
}
if (item instanceof EntaxyObjectItem) {
ObjectItem typedResult = (ObjectItem) result;
EntaxyObjectItem typedOrigin = (EntaxyObjectItem) item;
}
if (item instanceof EntaxyConfigItem) {
ConfigItem typedResult = (ConfigItem) result;
EntaxyConfigItem typedOrigin = (EntaxyConfigItem) item;
}
if (item instanceof EntaxyResourceItem) {
ResourceItem typedResult = (ResourceItem) result;
EntaxyResourceItem typedOrigin = (EntaxyResourceItem) item;
}
return result;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getCreatedOn() {
return createdOn;
}
public void setCreatedOn(String createdOn) {
this.createdOn = createdOn;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public String getModifiedOn() {
return modifiedOn;
}
public void setModifiedOn(String modifiedOn) {
this.modifiedOn = modifiedOn;
}
public String getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(String modifiedBy) {
this.modifiedBy = modifiedBy;
}
public List<ContentModelItem> getRequiredItems() {
return requiredItems;
}
public List<ContentModelItem> getIncludedItems() {
return includedItems;
}
}

View File

@ -0,0 +1,101 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.JSONUtils.ObjectWrapper;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplication.ITEM_SCOPE;
import ru.entaxy.platform.integration.applications.EntaxyApplication.ITEM_TYPE;
import ru.entaxy.platform.integration.applications.impl.project.model.item.BundleItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ConfigItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ContentModelItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ObjectItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ResourceItem;
public class ContentModelItemWrapper extends ObjectWrapper {
private static final Logger LOG = LoggerFactory.getLogger(ContentModelItemWrapper.class);
public static boolean isModelItem(JsonObject object) {
return object.has("id") && object.has("scope") && object.has("type");
}
ContentModel contentModel;
ContentModelItem contentModelItem;
public ContentModelItemWrapper(ContentModel contentModel) {
super();
this.contentModel = contentModel;
}
@Override
public void wrap(JsonObject object, Map<String, Object> context, String path) {
try {
String type = object.get("type").getAsString();
EntaxyApplication.ITEM_TYPE itemType = EntaxyApplication.ITEM_TYPE.valueOf(type.toUpperCase());
switch (itemType) {
case BUNDLE:
contentModelItem = ContentModel.GSON.fromJson(object, BundleItem.class);
break;
case CONFIG:
contentModelItem = ContentModel.GSON.fromJson(object, ConfigItem.class);
break;
case OBJECT:
contentModelItem = ContentModel.GSON.fromJson(object, ObjectItem.class);
break;
case RESOURCE:
contentModelItem = ContentModel.GSON.fromJson(object, ResourceItem.class);
break;
default:
return;
}
contentModelItem.setItemType(itemType);
try {
contentModelItem.setItemScope(EntaxyApplication.ITEM_SCOPE.valueOf(object.get("scope").getAsString().toUpperCase()));
} catch (Exception e) {
contentModelItem.setItemScope(EntaxyApplication.ITEM_SCOPE.UNKNOWN);
}
if (contentModelItem.isRequired())
contentModel.requiredItems.add(contentModelItem);
else
contentModel.includedItems.add(contentModelItem);
} catch (Exception e) {
LOG.error("Error reading object", e);
}
}
}

View File

@ -0,0 +1,51 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model.item;
public class BundleItem extends ContentModelItem {
long bundleId;
String bundleSymbolicName;
public long getBundleId() {
return bundleId;
}
public void setBundleId(long bundleId) {
this.bundleId = bundleId;
}
public String getBundleSymbolicName() {
return bundleSymbolicName;
}
public void setBundleSymbolicName(String bundleSymbolicName) {
this.bundleSymbolicName = bundleSymbolicName;
}
}

View File

@ -0,0 +1,30 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model.item;
public class ConfigItem extends ObjectItem {
}

View File

@ -0,0 +1,109 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model.item;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.impl.project.model.ContentModel;
public class ContentModelItem {
transient ContentModel contentModel;
String id;
boolean required = false;
boolean ignored = false;
boolean ghost = false;
EntaxyApplication.ITEM_SCOPE scope;
EntaxyApplication.ITEM_TYPE type;
String colocationGroupId;
public ContentModel getContentModel() {
return contentModel;
}
public void setContentModel(ContentModel contentModel) {
this.contentModel = contentModel;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public boolean isIgnored() {
return ignored;
}
public void setIgnored(boolean ignored) {
this.ignored = ignored;
}
public boolean isGhost() {
return ghost;
}
public void setGhost(boolean ghost) {
this.ghost = ghost;
}
public EntaxyApplication.ITEM_SCOPE getItemScope() {
return scope;
}
public void setItemScope(EntaxyApplication.ITEM_SCOPE itemScope) {
this.scope = itemScope;
}
public EntaxyApplication.ITEM_TYPE getItemType() {
return type;
}
public void setItemType(EntaxyApplication.ITEM_TYPE itemType) {
this.type = itemType;
}
public String getColocationGroupId() {
return colocationGroupId;
}
public void setColocationGroupId(String colocationGroupId) {
this.colocationGroupId = colocationGroupId;
}
}

View File

@ -0,0 +1,30 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model.item;
public class ObjectItem extends BundleItem {
}

View File

@ -0,0 +1,30 @@
/*-
* ~~~~~~licensing~~~~~~
* application-impl
* ==========
* 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.integration.applications.impl.project.model.item;
public class ResourceItem extends ContentModelItem {
}

View File

@ -0,0 +1,31 @@
[#ftl attributes={"generated.type":"features"}]
<?xml version="1.0" encoding="UTF-8"?>
<features name="[=repoName]"
xmlns="http://karaf.apache.org/xmlns/features/v1.6.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.6.0 http://karaf.apache.org/xmlns/features/v1.6.0">
<feature name="[=featureName]" version="[=featureVersion]">
[#list descriptor.getConfigComponents() as config]
<configfile finalname="${karaf.etc}/[=config.targetLocation]"
override="true">
mvn:[=config.mavenLocation]
</configfile>
[/#list]
[#list descriptor.getBundleComponents() as bundle]
<bundle start-level="[=bundle.priority]">[=bundle.fullTargetLocation]</bundle>
[/#list]
[#if revisionNumber??]
[#assign finalRevision=revisionNumber]
[#else]
[#assign finalRevision="0"]
[/#if]
<capability>
entaxy.application;name=[=descriptor.name];version=[=descriptor.version];revision=[=finalRevision]
</capability>
</feature>
</features>