updated from master and fix merge conflicts

remotes/1731000850486189418/master
Amalka Subasinghe 8 months ago
commit 89bc0281c0

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>analytics-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>io.entgra.device.mgt.core.parent</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -21,7 +21,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>application-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -0,0 +1,52 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common;
import java.io.InputStream;
public class ChunkDescriptor {
private FileDescriptor associateFileDescriptor;
private long size;
private InputStream chunk;
public FileDescriptor getAssociateFileDescriptor() {
return associateFileDescriptor;
}
public void setAssociateFileDescriptor(FileDescriptor associateFileDescriptor) {
this.associateFileDescriptor = associateFileDescriptor;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public InputStream getChunk() {
return chunk;
}
public void setChunk(InputStream chunk) {
this.chunk = chunk;
}
}

@ -0,0 +1,79 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common;
import java.io.InputStream;
public class FileDescriptor {
private String fileName;
private String extension;
private String fullQualifiedName;
private String absolutePath;
private long actualFileSize;
private InputStream file;
public InputStream getFile() {
return file;
}
public void setFile(InputStream file) {
this.file = file;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension;
}
public String getAbsolutePath() {
return absolutePath;
}
public void setAbsolutePath(String absolutePath) {
this.absolutePath = absolutePath;
}
public long getActualFileSize() {
return actualFileSize;
}
public void setActualFileSize(long actualFileSize) {
this.actualFileSize = actualFileSize;
}
public String getFullQualifiedName() {
return fullQualifiedName;
}
public void setFullQualifiedName(String fullQualifiedName) {
this.fullQualifiedName = fullQualifiedName;
}
}

@ -0,0 +1,60 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common;
public class FileMetaEntry {
private String fileName;
private String extension;
private long size;
private String absolutePath;
public String getAbsolutePath() {
return absolutePath;
}
public void setAbsolutePath(String absolutePath) {
this.absolutePath = absolutePath;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
}

@ -0,0 +1,108 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common;
import java.util.Objects;
public class TransferLink {
private static final String SCHEMA_SEPARATOR = "://";
private static final String URL_SEPARATOR = "/";
private static final String COLON = ":";
private final String schema;
private final String host;
private final String port;
private final String endpoint;
private final String artifactHolderUUID;
private TransferLink(String schema, String host, String port, String endpoint, String artifactHolderUUID) {
this.schema = schema;
this.host = host;
this.port = port;
this.endpoint = endpoint;
this.artifactHolderUUID = artifactHolderUUID;
}
public String getDirectTransferLink() {
return schema + SCHEMA_SEPARATOR + host + COLON + port + URL_SEPARATOR + endpoint + URL_SEPARATOR + artifactHolderUUID;
}
public String getRelativeTransferLink() {
return endpoint + URL_SEPARATOR + artifactHolderUUID;
}
@Override
public String toString() {
return getDirectTransferLink();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TransferLink that = (TransferLink) o;
return Objects.equals(schema, that.schema) && Objects.equals(host, that.host) && Objects.equals(port, that.port)
&& Objects.equals(endpoint, that.endpoint) && Objects.equals(artifactHolderUUID, that.artifactHolderUUID);
}
@Override
public int hashCode() {
return Objects.hash(schema, host, port, endpoint, artifactHolderUUID);
}
public static class TransferLinkBuilder {
private static final String DEFAULT_SCHEMA = "https";
private static final String ENDPOINT = "application-mgt-publisher/v1.0/applications/uploads";
private static final String IOT_GW_HOST_ENV_VAR = "iot.gateway.host";
private static final String IOT_GW_HTTPS_PORT_ENV_VAR = "iot.gateway.https.port";
private static final String IOT_GW_HTTP_PORT_ENV_VAR = "iot.gateway.http.port";
private String schema;
private String endpoint;
private final String artifactHolderUUID;
public TransferLinkBuilder(String artifactHolderUUID) {
this.schema = DEFAULT_SCHEMA;
this.endpoint = ENDPOINT;
this.artifactHolderUUID = artifactHolderUUID;
}
public TransferLinkBuilder withSchema(String schema) {
this.schema = schema;
return this;
}
public TransferLinkBuilder withEndpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}
public TransferLink build() {
return new TransferLink(this.schema, resolveHost(), resolvePort(), this.endpoint, this.artifactHolderUUID);
}
private String resolveHost() {
return System.getProperty(IOT_GW_HOST_ENV_VAR);
}
private String resolvePort() {
return Objects.equals(this.schema, DEFAULT_SCHEMA) ? System.getProperty(IOT_GW_HTTPS_PORT_ENV_VAR)
: System.getProperty(IOT_GW_HTTP_PORT_ENV_VAR);
}
}
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common.exception;
public class FileDownloaderServiceException extends Exception {
public FileDownloaderServiceException(String msg) {
super(msg);
}
public FileDownloaderServiceException(String msg, Throwable t) {
super(msg, t);
}
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common.exception;
public class FileTransferServiceException extends Exception {
public FileTransferServiceException(String msg) {
super(msg);
}
public FileTransferServiceException(String msg, Throwable throwable) {
super(msg, throwable);
}
}

@ -371,11 +371,9 @@ public interface ApplicationManager {
*
* @param releaseUuid UUID of the application release.
* @param entAppReleaseWrapper {@link ApplicationReleaseDTO}
* @param applicationArtifact {@link ApplicationArtifact}
* @return If the application release is updated correctly True returns, otherwise retuen False
*/
ApplicationRelease updateEntAppRelease(String releaseUuid, EntAppReleaseWrapper entAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException;
ApplicationRelease updateEntAppRelease(String releaseUuid, EntAppReleaseWrapper entAppReleaseWrapper) throws ApplicationManagementException;
/**
@ -383,33 +381,27 @@ public interface ApplicationManager {
*
* @param releaseUuid UUID of the application release.
* @param publicAppReleaseWrapper {@link ApplicationReleaseDTO}
* @param applicationArtifact {@link ApplicationArtifact}
* @return If the application release is updated correctly True returns, otherwise retuen False
*/
ApplicationRelease updatePubAppRelease(String releaseUuid, PublicAppReleaseWrapper publicAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException;
ApplicationRelease updatePubAppRelease(String releaseUuid, PublicAppReleaseWrapper publicAppReleaseWrapper) throws ApplicationManagementException;
/**
* Use to update existing web app release
*
* @param releaseUuid UUID of the application release.
* @param webAppReleaseWrapper {@link ApplicationReleaseDTO}
* @param applicationArtifact {@link ApplicationArtifact}
* @return If the application release is updated correctly True returns, otherwise retuen False
*/
ApplicationRelease updateWebAppRelease(String releaseUuid, WebAppReleaseWrapper webAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException;
ApplicationRelease updateWebAppRelease(String releaseUuid, WebAppReleaseWrapper webAppReleaseWrapper) throws ApplicationManagementException;
/**
* Use to update existing custom app release
*
* @param releaseUuid UUID of the application release.
* @param customAppReleaseWrapper {@link ApplicationReleaseDTO}
* @param applicationArtifact {@link ApplicationArtifact}
* @return If the application release is updated correctly True returns, otherwise retuen False
*/
ApplicationRelease updateCustomAppRelease(String releaseUuid, CustomAppReleaseWrapper customAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException;
ApplicationRelease updateCustomAppRelease(String releaseUuid, CustomAppReleaseWrapper customAppReleaseWrapper) throws ApplicationManagementException;
/**
* To validate the application creating request
@ -546,4 +538,13 @@ public interface ApplicationManager {
*/
void updateAppIconInfo(ApplicationRelease applicationRelease, String oldPackageName)
throws ApplicationManagementException;
/**
* Delete all application related data of a tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementException thrown if an error occurs when deleting data
*/
void deleteApplicationDataOfTenant(int tenantId) throws ApplicationManagementException;
void deleteApplicationDataByTenantDomain(String tenantDomain) throws ApplicationManagementException;
}

@ -132,4 +132,12 @@ public interface ApplicationStorageManager {
* @throws StorageManagementException if errors while generating md5 string
*/
String getMD5(InputStream inputStream) throws StorageManagementException;
/**
* Delete the folder containing all the app releases of a tenant
*
* @param tenantId Tenant ID
* @throws ApplicationStorageManagementException thrown if
*/
void deleteAppFolderOfTenant(int tenantId) throws ApplicationStorageManagementException;
}

@ -0,0 +1,29 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common.services;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileDownloaderServiceException;
import java.net.URL;
public interface FileDownloaderService {
FileDescriptor download(URL downloadUrl) throws FileDownloaderServiceException;
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common.services;
import io.entgra.device.mgt.core.application.mgt.common.ChunkDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry;
import io.entgra.device.mgt.core.application.mgt.common.TransferLink;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferServiceException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.NotFoundException;
import java.io.InputStream;
import java.net.URL;
public interface FileTransferService {
/**
* Create an upload link
* @param fileMetaEntry {@link FileMetaEntry}
* @return {@link TransferLink}
* @throws FileTransferServiceException Throws when error encountered while generating upload link
*/
TransferLink generateUploadLink(FileMetaEntry fileMetaEntry) throws FileTransferServiceException;
/**
* Resolve {@link ChunkDescriptor} using artifactHolder UUID and a given chunk
* @param artifactHolder Artifact holder's UUID string
* @param chunk Data chunk
* @return {@link ChunkDescriptor}
* @throws FileTransferServiceException Throws when error encountered while resolving chunk descriptor
* @throws NotFoundException Throws when artifact holder not exists in the file system
*/
ChunkDescriptor resolve(String artifactHolder, InputStream chunk) throws FileTransferServiceException, NotFoundException;
/**
* Write chunk of data
* @param chunkDescriptor {@link ChunkDescriptor}
* @throws FileTransferServiceException Throws when error encountered while writing chunk
*/
void writeChunk(ChunkDescriptor chunkDescriptor) throws FileTransferServiceException;
/**
* Check if the provided download url point to a file which exists on the local env or not
* @param downloadUrl Download URL
* @return Returns true if the download URL point to a file which resides in local
* @throws FileTransferServiceException Throws when error encountered while checking
*/
boolean isExistsOnLocal(URL downloadUrl) throws FileTransferServiceException;
/**
* Resolve {@link FileDescriptor} from a given download URL
* @param downloadUrl Download URL
* @return {@link java.io.FileDescriptor}
* @throws FileTransferServiceException Throws when error encountered while resolving file descriptor
*/
FileDescriptor resolve(URL downloadUrl) throws FileTransferServiceException;
}

@ -83,6 +83,44 @@ public class CustomAppReleaseWrapper {
@ApiModelProperty(name = "icon",
value = "banner of the application")
private Base64File banner;
private boolean remoteStatus;
public boolean isRemoteStatus() {
return remoteStatus;
}
public void setRemoteStatus(boolean remoteStatus) {
this.remoteStatus = remoteStatus;
}
private String artifactLink;
private List<String> screenshotLinks;
private String iconLink;
private String bannerLink;
public String getArtifactLink() {
return artifactLink;
}
public void setArtifactLink(String artifactLink) {
this.artifactLink = artifactLink;
}
public List<String> getScreenshotLinks() {
return screenshotLinks;
}
public void setScreenshotLinks(List<String> screenshotLinks) {
this.screenshotLinks = screenshotLinks;
}
public String getIconLink() {
return iconLink;
}
public void setIconLink(String iconLink) {
this.iconLink = iconLink;
}
public String getReleaseType() {
return releaseType;
@ -173,4 +211,12 @@ public class CustomAppReleaseWrapper {
public void setBanner(Base64File banner) {
this.banner = banner;
}
public String getBannerLink() {
return bannerLink;
}
public void setBannerLink(String bannerLink) {
this.bannerLink = bannerLink;
}
}

@ -86,6 +86,44 @@ public class EntAppReleaseWrapper {
@ApiModelProperty(name = "icon",
value = "banner of the application")
private Base64File banner;
private boolean remoteStatus;
public boolean isRemoteStatus() {
return remoteStatus;
}
public void setRemoteStatus(boolean remoteStatus) {
this.remoteStatus = remoteStatus;
}
private String artifactLink;
private List<String> screenshotLinks;
private String iconLink;
private String bannerLink;
public String getArtifactLink() {
return artifactLink;
}
public void setArtifactLink(String artifactLink) {
this.artifactLink = artifactLink;
}
public List<String> getScreenshotLinks() {
return screenshotLinks;
}
public void setScreenshotLinks(List<String> screenshotLinks) {
this.screenshotLinks = screenshotLinks;
}
public String getIconLink() {
return iconLink;
}
public void setIconLink(String iconLink) {
this.iconLink = iconLink;
}
public String getReleaseType() {
return releaseType;
@ -174,4 +212,12 @@ public class EntAppReleaseWrapper {
public void setBanner(Base64File banner) {
this.banner = banner;
}
public String getBannerLink() {
return bannerLink;
}
public void setBannerLink(String bannerLink) {
this.bannerLink = bannerLink;
}
}

@ -86,6 +86,18 @@ public class PublicAppReleaseWrapper {
@ApiModelProperty(name = "icon",
value = "banner of the application")
private Base64File banner;
private boolean remoteStatus;
public boolean isRemoteStatus() {
return remoteStatus;
}
public void setRemoteStatus(boolean remoteStatus) {
this.remoteStatus = remoteStatus;
}
private List<String> screenshotLinks;
private String iconLink;
private String bannerLink;
public String getReleaseType() {
return releaseType;
@ -162,4 +174,28 @@ public class PublicAppReleaseWrapper {
public void setBanner(Base64File banner) {
this.banner = banner;
}
public List<String> getScreenshotLinks() {
return screenshotLinks;
}
public void setScreenshotLinks(List<String> screenshotLinks) {
this.screenshotLinks = screenshotLinks;
}
public String getIconLink() {
return iconLink;
}
public void setIconLink(String iconLink) {
this.iconLink = iconLink;
}
public String getBannerLink() {
return bannerLink;
}
public void setBannerLink(String bannerLink) {
this.bannerLink = bannerLink;
}
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.common.wrapper;
public class TransferLinkWrapper {
private String directTransferLink;
private String relativeTransferLink;
public String getDirectTransferLink() {
return directTransferLink;
}
public void setDirectTransferLink(String directTransferLink) {
this.directTransferLink = directTransferLink;
}
public String getRelativeTransferLink() {
return relativeTransferLink;
}
public void setRelativeTransferLink(String relativeTransferLink) {
this.relativeTransferLink = relativeTransferLink;
}
}

@ -77,6 +77,42 @@ public class WebAppReleaseWrapper {
@ApiModelProperty(name = "icon",
value = "banner of the application")
private Base64File banner;
private boolean remoteStatus;
public boolean isRemoteStatus() {
return remoteStatus;
}
public void setRemoteStatus(boolean remoteStatus) {
this.remoteStatus = remoteStatus;
}
private List<String> screenshotLinks;
private String iconLink;
private String bannerLink;
public List<String> getScreenshotLinks() {
return screenshotLinks;
}
public void setScreenshotLinks(List<String> screenshotLinks) {
this.screenshotLinks = screenshotLinks;
}
public String getIconLink() {
return iconLink;
}
public void setIconLink(String iconLink) {
this.iconLink = iconLink;
}
public String getBannerLink() {
return bannerLink;
}
public void setBannerLink(String bannerLink) {
this.bannerLink = bannerLink;
}
public String getReleaseType() {
return releaseType;

@ -21,7 +21,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>application-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -105,6 +105,9 @@
<systemPropertyVariables>
<jacoco-agent.destfile>${basedir}/target/coverage-reports/jacoco-unit.exec</jacoco-agent.destfile>
<log4j.configuration>file:src/test/resources/log4j.properties</log4j.configuration>
<iot.gateway.http.port>8280</iot.gateway.http.port>
<iot.gateway.https.port>8280</iot.gateway.https.port>
<iot.gateway.host>test</iot.gateway.host>
</systemPropertyVariables>
</configuration>
</plugin>
@ -112,7 +115,6 @@
</build>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
@ -367,6 +369,26 @@
<artifactId>org.wso2.carbon.ntask.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.multitenancy</groupId>
<artifactId>org.wso2.carbon.tenant.mgt</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

@ -238,4 +238,52 @@ public interface ApplicationDAO {
int getApplicationCount(Filter filter, int deviceTypeId, int tenantId) throws ApplicationManagementDAOException;
void deleteApplication(int appId, int tenantId) throws ApplicationManagementDAOException;
/**
* Delete favourite applications of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteAppFavouritesByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Application category mapping of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteApplicationCategoryMappingByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Application categories of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteApplicationCategoriesByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Application tags mapping of Tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteApplicationTagsMappingByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Application tags of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteApplicationTagsByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Applications of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteApplicationsByTenant(int tenantId) throws ApplicationManagementDAOException;
}

@ -127,4 +127,12 @@ public interface ApplicationReleaseDAO {
*/
List<ApplicationReleaseDTO> getReleaseByPackages(List<String> packages, int tenantId)
throws ApplicationManagementDAOException;
/**
* Delete Application releases of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteReleasesByTenant(int tenantId) throws ApplicationManagementDAOException;
}

@ -18,6 +18,7 @@
package io.entgra.device.mgt.core.application.mgt.core.dao;
import io.entgra.device.mgt.core.application.mgt.common.LifecycleState;
import io.entgra.device.mgt.core.application.mgt.core.exception.ApplicationManagementDAOException;
import io.entgra.device.mgt.core.application.mgt.core.exception.LifeCycleManagementDAOException;
import java.util.List;
@ -75,4 +76,11 @@ public interface LifecycleStateDAO {
*/
String getAppReleaseCreatedUsername(int appId, String uuid, int tenantId) throws LifeCycleManagementDAOException;
}
/**
* Delete Application lifecycle states of tenant
*
* @param tenantId Tenant ID
* @throws LifeCycleManagementDAOException thrown if an error occurs while deleting data
*/
void deleteAppLifecycleStatesByTenant(int tenantId) throws LifeCycleManagementDAOException;
}

@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.application.mgt.core.dao;
import io.entgra.device.mgt.core.application.mgt.common.response.Review;
import io.entgra.device.mgt.core.application.mgt.common.PaginationRequest;
import io.entgra.device.mgt.core.application.mgt.common.dto.ReviewDTO;
import io.entgra.device.mgt.core.application.mgt.core.exception.ApplicationManagementDAOException;
import io.entgra.device.mgt.core.application.mgt.core.exception.ReviewManagementDAOException;
import java.util.List;
@ -119,4 +120,11 @@ import java.util.List;
void deleteAllChildCommentsOfReview(int rootParentId, int tenantId) throws ReviewManagementDAOException;
/**
* Delete reviews of a tenant
*
* @param tenantId Tenant ID
* @throws ReviewManagementDAOException thrown if an error occurs while deleting data
*/
void deleteReviewsByTenant(int tenantId) throws ReviewManagementDAOException;
}

@ -128,4 +128,20 @@ public interface SPApplicationDAO {
* @throws ApplicationManagementDAOException if any db error occurred
*/
void deleteIdentityServer(int id, int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Identity servers of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteIdentityServerByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Service provide mapping details of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteSPApplicationMappingByTenant(int tenantId) throws ApplicationManagementDAOException;
}

@ -264,4 +264,52 @@ public interface SubscriptionDAO {
* @throws ApplicationManagementDAOException if error occurred while retrieving the app details
*/
Activity getOperationAppDetails(int operationId, int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Operation mapping details of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteOperationMappingByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete device subscriptions of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteDeviceSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete group subscriptions of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteGroupSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete role subscriptions of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteRoleSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete user subscriptions of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteUserSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete scheduled subscription details of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteScheduledSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException;
}

@ -17,6 +17,7 @@
*/
package io.entgra.device.mgt.core.application.mgt.core.dao;
import io.entgra.device.mgt.core.application.mgt.core.exception.ApplicationManagementDAOException;
import io.entgra.device.mgt.core.application.mgt.core.exception.VisibilityManagementDAOException;
import java.util.List;
@ -70,4 +71,11 @@ public interface VisibilityDAO {
*/
void deleteAppUnrestrictedRoles(int applicationId, int tenantId) throws VisibilityManagementDAOException;
/**
* Delete app unrestricted roles of tenant
*
* @param tenantId Tenant ID
* @throws VisibilityManagementDAOException thrown if an error occurs while deleting data
*/
void deleteAppUnrestrictedRolesByTenant(int tenantId) throws VisibilityManagementDAOException;
}

@ -43,4 +43,28 @@ public interface VppApplicationDAO {
int addAssociation(VppAssociationDTO vppAssociationDTO, int tenantId) throws ApplicationManagementDAOException;
VppAssociationDTO updateAssociation(VppAssociationDTO vppAssociationDTO, int tenantId) throws ApplicationManagementDAOException;
/**
* Delete associations of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteAssociationByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete Vpp users of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteVppUserByTenant(int tenantId) throws ApplicationManagementDAOException;
/**
* Delete assets of tenant
*
* @param tenantId Tenant ID
* @throws ApplicationManagementDAOException thrown if an error occurs while deleting data
*/
void deleteAssetsByTenant(int tenantId) throws ApplicationManagementDAOException;
}

@ -1884,4 +1884,165 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
}
}
@Override
public void deleteAppFavouritesByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete app of tenant of id " + tenantId + " from favourites");
}
String sql = "DELETE FROM AP_APP_FAVOURITES "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing app from favourites of tenant "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing app of tenant of id " + tenantId + " from favourites. " +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteApplicationCategoryMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete application category mapping of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_CATEGORY_MAPPING "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing application category mapping of tenant"
+tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing application category mapping of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteApplicationCategoriesByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete application category of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_CATEGORY "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing application category of tenant "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing application category of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteApplicationTagsMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete application tags mapping of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_TAG_MAPPING "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing application tags mapping of tenant"
+tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing application tags mapping of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteApplicationTagsByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete application tags of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_TAG "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing application tags of tenant"
+tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing application tags of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteApplicationsByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete applications of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing applications of tenant"
+tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing applications of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -624,4 +624,30 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements
throw new ApplicationManagementDAOException(msg, e);
}
}
}
@Override
public void deleteReleasesByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete application releases of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_RELEASE "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing application release of tenant"
+tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing application release of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -484,4 +484,57 @@ public class GenericSPApplicationDAOImpl extends AbstractDAOImpl implements SPAp
}
}
@Override
public void deleteIdentityServerByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete identity server of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_IDENTITY_SERVER " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteSPApplicationMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete applications of tenant of id " + tenantId
+ " from service providers");
}
String sql = "DELETE FROM AP_IS_SP_APP_MAPPING "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing applications of tenant"
+tenantId+ "from service providers";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing applications of tenant of id " + tenantId +
"from service providers. Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -485,4 +485,57 @@ public class OracleSPApplicationDAOImpl extends AbstractDAOImpl implements SPAp
}
}
@Override
public void deleteIdentityServerByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete identity server of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_IDENTITY_SERVER " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteSPApplicationMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete applications of tenant of id " + tenantId
+ " from service providers");
}
String sql = "DELETE FROM AP_IS_SP_APP_MAPPING "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing applications of tenant"
+tenantId+ "from service providers";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing applications of tenant of id " + tenantId +
"from service providers. Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -485,4 +485,57 @@ public class PostgreSQLSPApplicationDAOImpl extends AbstractDAOImpl implements S
}
}
@Override
public void deleteIdentityServerByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete identity server of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_IDENTITY_SERVER " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteSPApplicationMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete applications of tenant of id " + tenantId
+ " from service providers");
}
String sql = "DELETE FROM AP_IS_SP_APP_MAPPING "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing applications of tenant"
+tenantId+ "from service providers";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing applications of tenant of id " + tenantId +
"from service providers. Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -485,4 +485,57 @@ public class SQLServerSPApplicationDAOImpl extends AbstractDAOImpl implements S
}
}
@Override
public void deleteIdentityServerByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete identity server of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_IDENTITY_SERVER " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete an identity server of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteSPApplicationMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete applications of tenant of id " + tenantId
+ " from service providers");
}
String sql = "DELETE FROM AP_IS_SP_APP_MAPPING "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing applications of tenant"
+tenantId+ "from service providers";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing applications of tenant of id " + tenantId +
"from service providers. Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -114,6 +114,32 @@ public class GenericLifecycleStateDAOImpl extends AbstractDAOImpl implements Lif
}
}
@Override
public void deleteAppLifecycleStatesByTenant(int tenantId) throws LifeCycleManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete app lifecycle states of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_LIFECYCLE_STATE "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing app lifecycle states of tenant"
+tenantId;
log.error(msg, e);
throw new LifeCycleManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing app lifecycle states of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new LifeCycleManagementDAOException(msg, e);
}
}
@Override
public List<LifecycleState> getLifecycleStates(int appReleaseId, int tenantId) throws LifeCycleManagementDAOException {
try {

@ -602,4 +602,30 @@ public class GenericReviewDAOImpl extends AbstractDAOImpl implements ReviewDAO {
throw new ReviewManagementDAOException(msg, e);
}
}
@Override
public void deleteReviewsByTenant(int tenantId) throws ReviewManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete app reviews of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_APP_REVIEW "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing app reviews of tenant "
+ tenantId;
log.error(msg, e);
throw new ReviewManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing app reviews of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ReviewManagementDAOException(msg, e);
}
}
}

@ -1476,4 +1476,163 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteOperationMappingByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete operation mapping of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_APP_SUB_OP_MAPPING " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete operation mapping of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete operation mapping of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteRoleSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete role subscription of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_ROLE_SUBSCRIPTION " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete role subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete role subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteUserSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete user subscription of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_USER_SUBSCRIPTION " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete user subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete user subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteGroupSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete user subscription of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_GROUP_SUBSCRIPTION " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete group subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete group subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteScheduledSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete scheduled subscription of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_SCHEDULED_SUBSCRIPTION " +
"WHERE APPLICATION_UUID IN " +
"(SELECT UUID FROM AP_APP_RELEASE WHERE TENANT_ID = ?)";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeBatch();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete scheduled subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete scheduled subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteDeviceSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete device subscription of the tenant of id: " + tenantId);
}
String sql = "DELETE FROM AP_DEVICE_SUBSCRIPTION " +
"WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete device subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing SQL to delete device subscription of tenant of id "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -176,4 +176,32 @@ public class GenericVisibilityDAOImpl extends AbstractDAOImpl implements Visibil
throw new VisibilityManagementDAOException(msg, e);
}
}
@Override
public void deleteAppUnrestrictedRolesByTenant(int tenantId) throws VisibilityManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete Application unrestricted roles of tenant of ID "
+ tenantId);
}
String sql = "DELETE "
+ "FROM AP_UNRESTRICTED_ROLE "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to delete application unrestricted roles of tenant: "
+ tenantId;
log.error(msg, e);
throw new VisibilityManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while executing query to delete application unrestricted roles which of"
+ " tenant Id " + tenantId + ". executed query: " + sql;
log.error(msg, e);
throw new VisibilityManagementDAOException(msg, e);
}
}
}

@ -506,4 +506,84 @@ public class GenericVppApplicationDAOImpl extends AbstractDAOImpl implements Vp
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteAssetsByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete application releases of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_ASSETS "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing application release of tenant "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing application release of tenant of id " + tenantId +
" Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteVppUserByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete vpp user of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_VPP_USER "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing vpp user of tenant "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing vpp user of tenant of id " + tenantId +
"Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public void deleteAssociationByTenant(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to delete association of tenant of id " + tenantId);
}
String sql = "DELETE FROM AP_VPP_ASSOCIATION "
+ "WHERE TENANT_ID = ?";
try {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.executeUpdate();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection when removing association of tenant"
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while removing association of tenant of id " + tenantId +
" Executed Query: " + sql;
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.core.exception;
public class FileTransferServiceHelperUtilException extends Exception {
public FileTransferServiceHelperUtilException(String msg) {
super(msg);
}
public FileTransferServiceHelperUtilException(String msg, Throwable t) {
super(msg, t);
}
}

@ -18,11 +18,16 @@
package io.entgra.device.mgt.core.application.mgt.core.impl;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileDownloaderServiceException;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferServiceException;
import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException;
import io.entgra.device.mgt.core.application.mgt.core.dao.*;
import io.entgra.device.mgt.core.application.mgt.core.exception.*;
import io.entgra.device.mgt.core.device.mgt.common.Base64File;
import io.entgra.device.mgt.core.application.mgt.core.dao.SPApplicationDAO;
import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil;
import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
import org.apache.commons.codec.digest.DigestUtils;
@ -75,11 +80,6 @@ import io.entgra.device.mgt.core.application.mgt.common.wrapper.PublicAppWrapper
import io.entgra.device.mgt.core.application.mgt.common.wrapper.WebAppReleaseWrapper;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.WebAppWrapper;
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.core.dao.ApplicationDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.ApplicationReleaseDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.LifecycleStateDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.SubscriptionDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.VisibilityDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.common.ApplicationManagementDAOFactory;
import io.entgra.device.mgt.core.application.mgt.core.util.APIUtil;
import io.entgra.device.mgt.core.application.mgt.core.exception.ApplicationManagementDAOException;
@ -96,6 +96,8 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementEx
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.stratos.common.beans.TenantInfoBean;
import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException;
@ -103,6 +105,8 @@ import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -128,6 +132,8 @@ public class ApplicationManagerImpl implements ApplicationManager {
private SubscriptionDAO subscriptionDAO;
private LifecycleStateManager lifecycleStateManager;
private SPApplicationDAO spApplicationDAO;
private VppApplicationDAO vppApplicationDAO;
private ReviewDAO reviewDAO;
public ApplicationManagerImpl() {
initDataAccessObjects();
@ -141,10 +147,61 @@ public class ApplicationManagerImpl implements ApplicationManager {
this.applicationReleaseDAO = ApplicationManagementDAOFactory.getApplicationReleaseDAO();
this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO();
this.spApplicationDAO = ApplicationManagementDAOFactory.getSPApplicationDAO();
this.vppApplicationDAO = ApplicationManagementDAOFactory.getVppApplicationDAO();
this.reviewDAO = ApplicationManagementDAOFactory.getCommentDAO();
}
@Override
public <T> Application createApplication(T app, boolean isPublished) throws ApplicationManagementException {
return createApplicationBasedOnRemoteStatus(app, isPublished);
}
/**
* Create the application based on the release wrapper's remote status. If the remote status is true, then
* the application creation will take place asynchronously.
* @param app Application release wrapper
* @param isPublished Publish status
* @return {@link Application}
* @throws ApplicationManagementException Throws when error occurred while application creation
*/
@SuppressWarnings("unchecked")
private <T> Application createApplicationBasedOnRemoteStatus(T app, boolean isPublished) throws ApplicationManagementException {
if (ApplicationManagementUtil.getRemoteStatus(app)) {
List<?> releaseWrappers = ApplicationManagementUtil.deriveApplicationWithoutRelease(app);
Application createdApplication = triggerApplicationCreation(app, isPublished);
if (createdApplication == null) {
throw new ApplicationManagementException("Null retrieved for created application.");
}
try {
if (releaseWrappers != null && !releaseWrappers.isEmpty()) {
if (app instanceof ApplicationWrapper) {
((ApplicationWrapper) app).setEntAppReleaseWrappers((List<EntAppReleaseWrapper>) releaseWrappers);
createApplicationReleaseBasedOnRemoteStatus(createdApplication.getId(),
((ApplicationWrapper) app).getEntAppReleaseWrappers().get(0), isPublished);
} else if (app instanceof CustomAppWrapper) {
((CustomAppWrapper) app).setCustomAppReleaseWrappers((List<CustomAppReleaseWrapper>) releaseWrappers);
createApplicationReleaseBasedOnRemoteStatus(createdApplication.getId(),
((CustomAppWrapper) app).getCustomAppReleaseWrappers().get(0), isPublished);
} else {
throw new ApplicationManagementException("Unsupported release wrapper received");
}
}
return createdApplication;
} catch (ResourceManagementException e) {
throw new ApplicationManagementException("Error encountered while creating deploying artifact", e);
}
}
return triggerApplicationCreation(app, isPublished);
}
/**
* Trigger the application creation process
* @param app Application release wrapper
* @param isPublished Publish status
* @return {@link Application}
* @throws ApplicationManagementException Throws when error occurred while creating the application
*/
private <T> Application triggerApplicationCreation(T app, boolean isPublished) throws ApplicationManagementException {
ApplicationDTO applicationDTO = uploadReleaseArtifactIfExist(app);
try {
ConnectionManagerUtil.beginDBTransaction();
@ -172,22 +229,110 @@ public class ApplicationManagerImpl implements ApplicationManager {
}
}
/**
* Create application release based on remote status. If the remote status is true, then the
* application release creation will take place asynchronously.
* @param appId Application id
* @param releaseWrapper Release wrapper
* @param isPublished Publish status
* @return {@link Application}
* @throws ApplicationManagementException Throws when error occurred while deploying the release
* @throws ResourceManagementException Throws when error occurred while deploying the release
*/
private <T> ApplicationRelease createApplicationReleaseBasedOnRemoteStatus(int appId, T releaseWrapper, boolean isPublished)
throws ApplicationManagementException, ResourceManagementException {
if (ApplicationManagementUtil.getRemoteStatusFromWrapper(releaseWrapper)) {
triggerReleaseAsynchronously(appId, releaseWrapper, isPublished);
} else {
if (releaseWrapper instanceof EntAppReleaseWrapper) {
return triggerEntAppRelease(appId, (EntAppReleaseWrapper) releaseWrapper, isPublished);
}
if (releaseWrapper instanceof CustomAppReleaseWrapper) {
return triggerCustomAppRelease(appId, (CustomAppReleaseWrapper) releaseWrapper, isPublished);
}
throw new ApplicationManagementException("Unsupported release wrapper received");
}
return new ApplicationRelease();
}
/**
* Trigger release creation asynchronously
* @param appId Application id
* @param releaseWrapper Release wrapper
* @param isPublished Publish status
*/
private <T> void triggerReleaseAsynchronously(int appId, T releaseWrapper, boolean isPublished) {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
new Thread(() -> {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
if (releaseWrapper instanceof EntAppReleaseWrapper &&
((EntAppReleaseWrapper) releaseWrapper).isRemoteStatus()) {
triggerEntAppRelease(appId, (EntAppReleaseWrapper) releaseWrapper, isPublished);
}else if (releaseWrapper instanceof CustomAppReleaseWrapper &&
((CustomAppReleaseWrapper) releaseWrapper).isRemoteStatus()) {
triggerCustomAppRelease(appId, (CustomAppReleaseWrapper) releaseWrapper, isPublished);
} else {
throw new ApplicationManagementException("Unsupported release wrapper received");
}
} catch (ApplicationManagementException | ResourceManagementException e) {
log.error("Error encountered while deploying remote application release", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}).start();
}
/**
* Trigger enterprise application creation
* @param appId Application id
* @param releaseWrapper Release wrapper
* @param isPublished Publish status
* @return {@link ApplicationRelease}
* @throws ApplicationManagementException Throws when error encountered while creating enterprise application
*/
private ApplicationRelease triggerEntAppRelease(int appId, EntAppReleaseWrapper releaseWrapper, boolean isPublished)
throws ApplicationManagementException{
ApplicationManager applicationManager = APIUtil.getApplicationManager();
try {
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
releaseWrapper.getArtifactLink(), releaseWrapper.getBannerLink());
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadEntAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName(), true);
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.ENTERPRISE, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating ent app release for application with the name: " + applicationDTO.getName();
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
} catch (MalformedURLException e) {
String msg = "Malformed URL link received as a downloadable link";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (FileDownloaderServiceException e) {
String msg = "Error encountered while downloading application release artifacts for app id " + appId;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
}
@Override
public ApplicationRelease createEntAppRelease(int appId, EntAppReleaseWrapper releaseWrapper, boolean isPublished)
throws ApplicationManagementException {
ApplicationManager applicationManager = APIUtil.getApplicationManager();
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), releaseWrapper.getScreenshots(),
releaseWrapper.getBinaryFile(), releaseWrapper.getBanner());
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadEntAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName(), true);
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.ENTERPRISE, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating ent app release for application with the name: " + applicationDTO.getName();
return createApplicationReleaseBasedOnRemoteStatus(appId, releaseWrapper, isPublished);
} catch (ResourceManagementException e) {
String msg = "Error occurred while creating enterprise app release for the app id " + appId;
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
}
@ -196,17 +341,27 @@ public class ApplicationManagerImpl implements ApplicationManager {
public ApplicationRelease createWebAppRelease(int appId, WebAppReleaseWrapper releaseWrapper, boolean isPublished)
throws ApplicationManagementException, ResourceManagementException {
ApplicationManager applicationManager = APIUtil.getApplicationManager();
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadWebAppReleaseArtifacts(releaseDTO, artifact);
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.WEB_CLIP, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating web app release for application with the name: " + applicationDTO.getName();
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
null, releaseWrapper.getBannerLink());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadWebAppReleaseArtifacts(releaseDTO, artifact);
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.WEB_CLIP, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating web app release for application with the name: " + applicationDTO.getName();
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
} catch (MalformedURLException e) {
String msg = "Malformed URL link received as a downloadable link";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (FileDownloaderServiceException e) {
String msg = "Error encountered while downloading application release artifacts";
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
}
@ -215,38 +370,69 @@ public class ApplicationManagerImpl implements ApplicationManager {
public ApplicationRelease createPubAppRelease(int appId, PublicAppReleaseWrapper releaseWrapper, boolean isPublished) throws
ResourceManagementException, ApplicationManagementException {
ApplicationManager applicationManager = APIUtil.getApplicationManager();
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadPubAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName());
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.PUBLIC, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating ent public release for application with the name: " + applicationDTO.getName();
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
null, releaseWrapper.getBannerLink());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadPubAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName());
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.PUBLIC, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating ent public release for application with the name: " + applicationDTO.getName();
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
} catch (MalformedURLException e) {
String msg = "Malformed URL link received as a downloadable link";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (FileDownloaderServiceException e) {
String msg = "Error encountered while downloading application release artifacts";
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
}
@Override
public ApplicationRelease createCustomAppRelease(int appId, CustomAppReleaseWrapper releaseWrapper, boolean isPublished)
throws ApplicationManagementException {
try {
return createApplicationReleaseBasedOnRemoteStatus(appId, releaseWrapper, isPublished);
} catch (ResourceManagementException e) {
String msg = "Error occurred while creating enterprise app release";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
}
private ApplicationRelease triggerCustomAppRelease(int appId, CustomAppReleaseWrapper releaseWrapper, boolean isPublished)
throws ResourceManagementException, ApplicationManagementException {
ApplicationManager applicationManager = APIUtil.getApplicationManager();
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), releaseWrapper.getBinaryFile(), releaseWrapper.getBanner());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadCustomAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName());
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.CUSTOM, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating custom app release for application with the name: " + applicationDTO.getName();
ApplicationDTO applicationDTO = applicationManager.getApplication(appId);
DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
releaseWrapper.getArtifactLink(), releaseWrapper.getBannerLink());
ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper);
releaseDTO = uploadCustomAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName());
try {
return createRelease(applicationDTO, releaseDTO, ApplicationType.CUSTOM, isPublished);
} catch (ApplicationManagementException e) {
String msg = "Error occurred while creating custom app release for application with the name: " + applicationDTO.getName();
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
} catch (MalformedURLException e) {
String msg = "Malformed URL link received as a downloadable link";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (FileDownloaderServiceException e) {
String msg = "Error encountered while downloading application release artifacts";
log.error(msg, e);
deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue()));
throw new ApplicationManagementException(msg, e);
}
}
@ -279,27 +465,27 @@ public class ApplicationManagerImpl implements ApplicationManager {
if (app instanceof ApplicationWrapper) {
ApplicationWrapper wrapper = (ApplicationWrapper) app;
EntAppReleaseWrapper releaseWrapper = wrapper.getEntAppReleaseWrappers().get(0);
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), releaseWrapper.getBinaryFile(), releaseWrapper.getBanner());
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
releaseWrapper.getArtifactLink(), releaseWrapper.getBannerLink());
releaseDTO = uploadEntAppReleaseArtifacts(releaseDTO,
artifact, wrapper.getDeviceType(), false);
} else if (app instanceof PublicAppWrapper) {
PublicAppWrapper wrapper = (PublicAppWrapper) app;
PublicAppReleaseWrapper releaseWrapper = wrapper.getPublicAppReleaseWrappers().get(0);
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner());
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
null, releaseWrapper.getBannerLink());
releaseDTO = uploadPubAppReleaseArtifacts(releaseDTO, artifact, wrapper.getDeviceType());
} else if (app instanceof WebAppWrapper) {
WebAppWrapper wrapper = (WebAppWrapper) app;
WebAppReleaseWrapper releaseWrapper = wrapper.getWebAppReleaseWrappers().get(0);
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner());
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
null, releaseWrapper.getBannerLink());
releaseDTO = uploadWebAppReleaseArtifacts(releaseDTO, artifact);
} else if (app instanceof CustomAppWrapper) {
CustomAppWrapper wrapper = (CustomAppWrapper) app;
CustomAppReleaseWrapper releaseWrapper = wrapper.getCustomAppReleaseWrappers().get(0);
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(),
releaseWrapper.getScreenshots(), releaseWrapper.getBinaryFile(), releaseWrapper.getBanner());
artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIconLink(), releaseWrapper.getScreenshotLinks(),
releaseWrapper.getArtifactLink(), releaseWrapper.getBannerLink());
try {
releaseDTO = uploadCustomAppReleaseArtifacts(releaseDTO, artifact, wrapper.getDeviceType());
} catch (ResourceManagementException e) {
@ -316,7 +502,17 @@ public class ApplicationManagerImpl implements ApplicationManager {
String msg = "Error Occurred when uploading artifacts of the web clip: " + applicationDTO.getName();
log.error(msg);
throw new ApplicationManagementException(msg, e);
} catch (MalformedURLException e) {
String msg = "Malformed URL link received as a downloadable link";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (FileDownloaderServiceException e) {
String msg = "Error encountered while downloading application release artifacts";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
// TODO: artifact URLs are not working for Windows AppX installations https://roadmap.entgra.net/issues/11010
//ApplicationManagementUtil.addInstallerPathToMetadata(releaseDTO);
applicationDTO.getApplicationReleaseDTOs().clear();
applicationDTO.getApplicationReleaseDTOs().add(releaseDTO);
return applicationDTO;
@ -857,7 +1053,8 @@ public class ApplicationManagerImpl implements ApplicationManager {
ApplicationArtifact applicationArtifact, int tenantId) throws ResourceManagementException {
ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager();
applicationReleaseDTO.setIconName(applicationArtifact.getIconName());
applicationReleaseDTO.setIconName(ApplicationManagementUtil.sanitizeName
(applicationArtifact.getIconName(), Constants.ICON_NAME));
applicationReleaseDTO.setBannerName(applicationArtifact.getBannerName());
Map<String, InputStream> screenshots = applicationArtifact.getScreenshots();
@ -866,11 +1063,14 @@ public class ApplicationManagerImpl implements ApplicationManager {
int counter = 1;
for (String scName : screenshotNames) {
if (counter == 1) {
applicationReleaseDTO.setScreenshotName1(scName);
applicationReleaseDTO.setScreenshotName1(ApplicationManagementUtil.sanitizeName
(scName, Constants.SCREENSHOT_NAME + counter));
} else if (counter == 2) {
applicationReleaseDTO.setScreenshotName2(scName);
applicationReleaseDTO.setScreenshotName2(ApplicationManagementUtil.sanitizeName
(scName, Constants.SCREENSHOT_NAME + counter));
} else if (counter == 3) {
applicationReleaseDTO.setScreenshotName3(scName);
applicationReleaseDTO.setScreenshotName3(ApplicationManagementUtil.sanitizeName
(scName, Constants.SCREENSHOT_NAME + counter));
}
counter++;
}
@ -898,7 +1098,8 @@ public class ApplicationManagerImpl implements ApplicationManager {
applicationStorageManager
.deleteAppReleaseArtifact(applicationReleaseDTO.getAppHashValue(), Constants.ICON_ARTIFACT,
applicationReleaseDTO.getIconName(), tenantId);
applicationReleaseDTO.setIconName(applicationArtifact.getIconName());
applicationReleaseDTO.setIconName(ApplicationManagementUtil.sanitizeName
(applicationArtifact.getIconName(), Constants.ICON_NAME));
}
if (!StringUtils.isEmpty(applicationArtifact.getBannerName())){
applicationStorageManager
@ -921,17 +1122,20 @@ public class ApplicationManagerImpl implements ApplicationManager {
applicationStorageManager
.deleteAppReleaseArtifact(applicationReleaseDTO.getAppHashValue(), folderPath,
applicationReleaseDTO.getScreenshotName1(), tenantId);
applicationReleaseDTO.setScreenshotName1(scName);
applicationReleaseDTO.setScreenshotName1(ApplicationManagementUtil.sanitizeName
(scName, Constants.SCREENSHOT_NAME + counter));
} else if (counter == 2) {
applicationStorageManager
.deleteAppReleaseArtifact(applicationReleaseDTO.getAppHashValue(), folderPath,
applicationReleaseDTO.getScreenshotName2(), tenantId);
applicationReleaseDTO.setScreenshotName2(scName);
applicationReleaseDTO.setScreenshotName2(ApplicationManagementUtil.sanitizeName
(scName, Constants.SCREENSHOT_NAME + counter));
} else if (counter == 3) {
applicationStorageManager
.deleteAppReleaseArtifact(applicationReleaseDTO.getAppHashValue(), folderPath,
applicationReleaseDTO.getScreenshotName3(), tenantId);
applicationReleaseDTO.setScreenshotName3(scName);
applicationReleaseDTO.setScreenshotName3(ApplicationManagementUtil.sanitizeName
(scName, Constants.SCREENSHOT_NAME + counter));
}
counter++;
}
@ -2415,20 +2619,22 @@ public class ApplicationManagerImpl implements ApplicationManager {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
ApplicationDTO applicationDTO = getApplication(applicationId);
String sanitizedName = ApplicationManagementUtil.sanitizeName(applicationUpdateWrapper.getName(),
Constants.ApplicationProperties.NAME );
try {
ConnectionManagerUtil.beginDBTransaction();
if (!StringUtils.isEmpty(applicationUpdateWrapper.getName()) && !applicationDTO.getName()
.equals(applicationUpdateWrapper.getName())) {
if (!StringUtils.isEmpty(sanitizedName) && !applicationDTO.getName()
.equals(sanitizedName)) {
if (applicationDAO
.isExistingAppName(applicationUpdateWrapper.getName().trim(), applicationDTO.getDeviceTypeId(),
.isExistingAppName(sanitizedName.trim(), applicationDTO.getDeviceTypeId(),
tenantId)) {
String msg = "Already an application registered with same name " + applicationUpdateWrapper.getName()
String msg = "Already an application registered with same name " + sanitizedName
+ ". Hence you can't update the application name from " + applicationDTO.getName() + " to "
+ applicationUpdateWrapper.getName();
+ sanitizedName;
log.error(msg);
throw new BadRequestException(msg);
}
applicationDTO.setName(applicationUpdateWrapper.getName());
applicationDTO.setName(sanitizedName);
}
if (!StringUtils.isEmpty(applicationUpdateWrapper.getSubMethod()) && !applicationDTO.getSubType()
.equals(applicationUpdateWrapper.getSubMethod())) {
@ -3124,11 +3330,13 @@ public class ApplicationManagerImpl implements ApplicationManager {
}
@Override
public ApplicationRelease updateEntAppRelease(String releaseUuid, EntAppReleaseWrapper entAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException {
public ApplicationRelease updateEntAppRelease(String releaseUuid, EntAppReleaseWrapper entAppReleaseWrapper) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try {
ApplicationArtifact applicationArtifact = ApplicationManagementUtil.
constructApplicationArtifact(entAppReleaseWrapper.getIconLink(), entAppReleaseWrapper.getScreenshotLinks(),
entAppReleaseWrapper.getArtifactLink(), entAppReleaseWrapper.getBannerLink());
ConnectionManagerUtil.beginDBTransaction();
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(releaseUuid, tenantId);
DeviceType deviceTypeObj = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
@ -3195,17 +3403,25 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ "UUID:" + releaseUuid;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (MalformedURLException e) {
throw new ApplicationManagementException("Malformed downloadable URL received for the Public app " +
"release UUID: " + releaseUuid);
} catch (FileDownloaderServiceException e) {
throw new ApplicationManagementException("Error encountered while downloading artifact for the Public app " +
"release UUID: " + releaseUuid);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
@Override
public ApplicationRelease updatePubAppRelease(String releaseUuid, PublicAppReleaseWrapper publicAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException {
public ApplicationRelease updatePubAppRelease(String releaseUuid, PublicAppReleaseWrapper publicAppReleaseWrapper) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try {
ApplicationArtifact applicationArtifact = ApplicationManagementUtil.
constructApplicationArtifact(publicAppReleaseWrapper.getIconLink(), publicAppReleaseWrapper.getScreenshotLinks(),
null, publicAppReleaseWrapper.getBannerLink());
ConnectionManagerUtil.beginDBTransaction();
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(releaseUuid, tenantId);
validateAppReleaseUpdating(publicAppReleaseWrapper, applicationDTO, applicationArtifact,
@ -3264,17 +3480,25 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ "release UUID:" + releaseUuid;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (MalformedURLException e) {
throw new ApplicationManagementException("Malformed downloadable URL received for the Public app " +
"release UUID: " + releaseUuid);
} catch (FileDownloaderServiceException e) {
throw new ApplicationManagementException("Error encountered while downloading artifact for the Public app " +
"release UUID: " + releaseUuid);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
@Override
public ApplicationRelease updateWebAppRelease(String releaseUuid, WebAppReleaseWrapper webAppReleaseWrapper,
ApplicationArtifact applicationArtifact) throws ApplicationManagementException {
public ApplicationRelease updateWebAppRelease(String releaseUuid, WebAppReleaseWrapper webAppReleaseWrapper) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try {
ApplicationArtifact applicationArtifact = ApplicationManagementUtil.
constructApplicationArtifact(webAppReleaseWrapper.getIconLink(), webAppReleaseWrapper.getScreenshotLinks(),
null, webAppReleaseWrapper.getBannerLink());
ConnectionManagerUtil.beginDBTransaction();
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(releaseUuid, tenantId);
validateAppReleaseUpdating(webAppReleaseWrapper, applicationDTO, applicationArtifact,
@ -3329,18 +3553,27 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ "release UUID:" + releaseUuid;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (MalformedURLException e) {
throw new ApplicationManagementException("Malformed downloadable URL received for the Public app " +
"release UUID: " + releaseUuid);
} catch (FileDownloaderServiceException e) {
throw new ApplicationManagementException("Error encountered while downloading artifact for the Public app " +
"release UUID: " + releaseUuid);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
@Override
public ApplicationRelease updateCustomAppRelease(String releaseUuid,
CustomAppReleaseWrapper customAppReleaseWrapper, ApplicationArtifact applicationArtifact)
public ApplicationRelease updateCustomAppRelease(String releaseUuid, CustomAppReleaseWrapper customAppReleaseWrapper)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager();
try {
ApplicationArtifact applicationArtifact = ApplicationManagementUtil.
constructApplicationArtifact(customAppReleaseWrapper.getIconLink(),
customAppReleaseWrapper.getScreenshotLinks(), customAppReleaseWrapper.getArtifactLink(),
customAppReleaseWrapper.getBannerLink());
ConnectionManagerUtil.beginDBTransaction();
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(releaseUuid, tenantId);
AtomicReference<ApplicationReleaseDTO> applicationReleaseDTO = new AtomicReference<>(
@ -3459,6 +3692,12 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ "UUID:" + releaseUuid;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (MalformedURLException e) {
throw new ApplicationManagementException("Malformed downloadable URL received for the Public app " +
"release UUID: " + releaseUuid);
} catch (FileDownloaderServiceException e) {
throw new ApplicationManagementException("Error encountered while downloading artifact for the Public app " +
"release UUID: " + releaseUuid);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
@ -3894,30 +4133,24 @@ public class ApplicationManagerImpl implements ApplicationManager {
public void validateEntAppReleaseCreatingRequest(EntAppReleaseWrapper releaseWrapper, String deviceType)
throws RequestValidatingException, ApplicationManagementException {
validateReleaseCreatingRequest(releaseWrapper, deviceType);
validateBinaryArtifact(releaseWrapper.getBinaryFile());
validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots());
}
@Override
public void validateCustomAppReleaseCreatingRequest(CustomAppReleaseWrapper releaseWrapper, String deviceType)
throws RequestValidatingException, ApplicationManagementException {
validateReleaseCreatingRequest(releaseWrapper, deviceType);
validateBinaryArtifact(releaseWrapper.getBinaryFile());
validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots());
}
@Override
public void validateWebAppReleaseCreatingRequest(WebAppReleaseWrapper releaseWrapper)
throws RequestValidatingException, ApplicationManagementException {
validateReleaseCreatingRequest(releaseWrapper, Constants.ANY);
validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots());
}
@Override
public void validatePublicAppReleaseCreatingRequest(PublicAppReleaseWrapper releaseWrapper, String deviceType)
throws RequestValidatingException, ApplicationManagementException {
validateReleaseCreatingRequest(releaseWrapper, deviceType);
validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots());
validatePublicAppReleasePackageName(releaseWrapper.getPackageName());
}
@ -4158,4 +4391,145 @@ public class ApplicationManagerImpl implements ApplicationManager {
throw new ApplicationManagementException(msg, e);
}
}
@Override
public void deleteApplicationDataOfTenant(int tenantId) throws ApplicationManagementException {
if (log.isDebugEnabled()) {
log.debug("Request is received to delete application related data of tenant with ID: " + tenantId);
}
try {
ConnectionManagerUtil.beginDBTransaction();
vppApplicationDAO.deleteAssociationByTenant(tenantId);
vppApplicationDAO.deleteVppUserByTenant(tenantId);
vppApplicationDAO.deleteAssetsByTenant(tenantId);
reviewDAO.deleteReviewsByTenant(tenantId);
subscriptionDAO.deleteOperationMappingByTenant(tenantId);
subscriptionDAO.deleteDeviceSubscriptionByTenant(tenantId);
subscriptionDAO.deleteGroupSubscriptionByTenant(tenantId);
subscriptionDAO.deleteRoleSubscriptionByTenant(tenantId);
subscriptionDAO.deleteUserSubscriptionByTenant(tenantId);
applicationDAO.deleteAppFavouritesByTenant(tenantId);
applicationDAO.deleteApplicationTagsMappingByTenant(tenantId);
applicationDAO.deleteApplicationTagsByTenant(tenantId);
applicationDAO.deleteApplicationCategoryMappingByTenant(tenantId);
applicationDAO.deleteApplicationCategoriesByTenant(tenantId);
subscriptionDAO.deleteScheduledSubscriptionByTenant(tenantId);
lifecycleStateDAO.deleteAppLifecycleStatesByTenant(tenantId);
applicationReleaseDAO.deleteReleasesByTenant(tenantId);
visibilityDAO.deleteAppUnrestrictedRolesByTenant(tenantId);
spApplicationDAO.deleteSPApplicationMappingByTenant(tenantId);
spApplicationDAO.deleteIdentityServerByTenant(tenantId);
applicationDAO.deleteApplicationsByTenant(tenantId);
APIUtil.getApplicationStorageManager().deleteAppFolderOfTenant(tenantId);
ConnectionManagerUtil.commitDBTransaction();
} catch (DBConnectionException e) {
String msg = "Error occurred while observing the database connection to delete applications for tenant with ID: "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Database access error is occurred when getting applications for tenant with ID: " + tenantId;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting life-cycle state data of application releases of the tenant"
+ " of ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ReviewManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting reviews of application releases of the applications"
+ " of tenant ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationStorageManagementException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting App folder of tenant"
+ " of tenant ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
@Override
public void deleteApplicationDataByTenantDomain(String tenantDomain) throws ApplicationManagementException {
int tenantId;
try{
TenantMgtAdminService tenantMgtAdminService = new TenantMgtAdminService();
TenantInfoBean tenantInfoBean = tenantMgtAdminService.getTenant(tenantDomain);
tenantId = tenantInfoBean.getTenantId();
} catch (Exception e) {
String msg = "Error getting tenant ID from domain: "
+ tenantDomain;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
try {
ConnectionManagerUtil.beginDBTransaction();
vppApplicationDAO.deleteAssociationByTenant(tenantId);
vppApplicationDAO.deleteVppUserByTenant(tenantId);
vppApplicationDAO.deleteAssetsByTenant(tenantId);
reviewDAO.deleteReviewsByTenant(tenantId);
subscriptionDAO.deleteOperationMappingByTenant(tenantId);
subscriptionDAO.deleteDeviceSubscriptionByTenant(tenantId);
subscriptionDAO.deleteGroupSubscriptionByTenant(tenantId);
subscriptionDAO.deleteRoleSubscriptionByTenant(tenantId);
subscriptionDAO.deleteUserSubscriptionByTenant(tenantId);
applicationDAO.deleteAppFavouritesByTenant(tenantId);
applicationDAO.deleteApplicationTagsMappingByTenant(tenantId);
applicationDAO.deleteApplicationTagsByTenant(tenantId);
applicationDAO.deleteApplicationCategoryMappingByTenant(tenantId);
applicationDAO.deleteApplicationCategoriesByTenant(tenantId);
subscriptionDAO.deleteScheduledSubscriptionByTenant(tenantId);
lifecycleStateDAO.deleteAppLifecycleStatesByTenant(tenantId);
applicationReleaseDAO.deleteReleasesByTenant(tenantId);
visibilityDAO.deleteAppUnrestrictedRolesByTenant(tenantId);
spApplicationDAO.deleteSPApplicationMappingByTenant(tenantId);
spApplicationDAO.deleteIdentityServerByTenant(tenantId);
applicationDAO.deleteApplicationsByTenant(tenantId);
APIUtil.getApplicationStorageManager().deleteAppFolderOfTenant(tenantId);
ConnectionManagerUtil.commitDBTransaction();
} catch (DBConnectionException e) {
String msg = "Error occurred while observing the database connection to delete applications for tenant with ID: "
+ tenantId;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Database access error is occurred when getting applications for tenant with ID: " + tenantId;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting life-cycle state data of application releases of the tenant"
+ " of ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ReviewManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting reviews of application releases of the applications"
+ " of tenant ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationStorageManagementException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting App folder of tenant"
+ " of tenant ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
}

@ -310,4 +310,18 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
throw new StorageManagementException(msg, e);
}
}
@Override
public void deleteAppFolderOfTenant(int tenantId) throws ApplicationStorageManagementException{
String folderPath = storagePath + File.separator + tenantId;
File folder = new File(folderPath);
if (folder.exists()) {
try {
StorageManagementUtil.delete(folder);
} catch (IOException e) {
throw new ApplicationStorageManagementException(
"Error occurred while deleting App folder of tenant:" + tenantId, e);
}
}
}
}

@ -0,0 +1,211 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.core.impl;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry;
import io.entgra.device.mgt.core.application.mgt.common.TransferLink;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileDownloaderServiceException;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferServiceException;
import io.entgra.device.mgt.core.application.mgt.common.services.FileDownloaderService;
import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService;
import io.entgra.device.mgt.core.application.mgt.core.internal.DataHolder;
import io.entgra.device.mgt.core.application.mgt.core.util.Constants;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class FileDownloaderServiceProvider {
private static final Log log = LogFactory.getLog(FileDownloaderServiceProvider.class);
private static final FileTransferService fileTransferService = DataHolder.getInstance().getFileTransferService();
private static final LocalFileDownloaderService localFileDownloaderService = new LocalFileDownloaderService();
private static final RemoteFileDownloaderService remoteFileDownloaderService = new RemoteFileDownloaderService();
public static FileDownloaderService getFileDownloaderService(URL downloadUrl) throws FileDownloaderServiceException {
try {
if (fileTransferService.isExistsOnLocal(downloadUrl)) {
return localFileDownloaderService;
}
return remoteFileDownloaderService;
} catch (FileTransferServiceException e) {
String msg = "Error encountered while acquiring file downloader service";
log.error(msg, e);
throw new FileDownloaderServiceException(msg, e);
}
}
/**
* Class holing the implementation of the local file downloading service
*/
private static class LocalFileDownloaderService implements FileDownloaderService {
@Override
public FileDescriptor download(URL downloadUrl) throws FileDownloaderServiceException {
try {
return fileTransferService.resolve(downloadUrl);
} catch (FileTransferServiceException e) {
String msg = "Error encountered while downloading file pointing by " + downloadUrl;
log.error(msg, e);
throw new FileDownloaderServiceException(msg, e);
}
}
}
/**
* Class holing the implementation of the remote file downloading service
*/
private static class RemoteFileDownloaderService implements FileDownloaderService {
private static final OkHttpClient okhttpClient =
new OkHttpClient.Builder().connectTimeout(500, TimeUnit.MILLISECONDS).build();
@Override
public FileDescriptor download(URL downloadUrl) throws FileDownloaderServiceException {
FileMetaEntry fileMetaEntry = getFileMetaEntry(downloadUrl);
try {
TransferLink transferLink = fileTransferService.generateUploadLink(fileMetaEntry);
FileDescriptor fileDescriptor = fileTransferService.resolve(new URL(transferLink.getDirectTransferLink()
+ "/" + fileMetaEntry.getFileName() + "." + fileMetaEntry.getExtension()));
FileUtils.copyURLToFile(downloadUrl, new File(fileDescriptor.getAbsolutePath()),
15000, 3600000);
return fileDescriptor;
} catch (FileTransferServiceException | IOException e) {
String msg = "Error encountered while downloading file";
log.error(msg, e);
throw new FileDownloaderServiceException(msg, e);
}
}
/**
* Generate the {@link FileMetaEntry} from the remote file
* @param downloadUrl Remote file URL
* @return {@link FileMetaEntry}
* @throws FileDownloaderServiceException Throws when error encountered while generating {@link FileMetaEntry}
*/
private FileMetaEntry getFileMetaEntry(URL downloadUrl) throws FileDownloaderServiceException {
Request request = new Request.Builder().url(downloadUrl).head().build();
try (Response response = okhttpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new FileDownloaderServiceException("Unexpected response code received for the remote url " + downloadUrl);
}
String contentDisposition = response.header("Content-Disposition");
String contentType = response.header("Content-Type");
String[] fileNameSegments = extractFileNameSegmentsFromUrl(downloadUrl);
// if the url parsing failed to resolve the file name segments
// falling to remote file name segment resolving
if (fileNameSegments == null) {
fileNameSegments = getFileNameSegments(contentDisposition, contentType);
}
FileMetaEntry fileMetaEntry = new FileMetaEntry();
fileMetaEntry.setSize(Long.parseLong(Objects.requireNonNull(response.header("Content-Length"))));
fileMetaEntry.setFileName(fileNameSegments[0]);
fileMetaEntry.setExtension(fileNameSegments[1]);
return fileMetaEntry;
} catch (IOException e) {
throw new FileDownloaderServiceException("IO error occurred while constructing file name for the remote url " + downloadUrl);
}
}
/**
* Extracting file name segments by parsing the URL
* @param url Remote URL to extract file name segments
* @return Array containing file name segments or null when failed to extract
*/
public static String[] extractFileNameSegmentsFromUrl(URL url) {
if (url == null) {
if (log.isDebugEnabled()) {
log.debug("Null received as the remote URL");
}
return null;
}
String []urlSegments = url.toString().split("/");
if (urlSegments.length < 1) {
if (log.isDebugEnabled()) {
log.debug("Cannot determine the file name for the remote file");
}
return null;
}
String fullQualifiedName = urlSegments[urlSegments.length - 1];
String []fileNameSegments = fullQualifiedName.split("\\.(?=[^.]+$)");
if (fileNameSegments.length != 2) {
if (log.isDebugEnabled()) {
log.debug("Error encountered when constructing file name");
}
return null;
}
return fileNameSegments;
}
/**
* Extract file name segments(filename & extensions) from content disposition header and content type header
* @param contentDisposition Content disposition header value
* @param contentType Content type header value
* @return Array of name segments
* @throws FileDownloaderServiceException Throws when error occurred while extracting name segments
*/
private static String[] getFileNameSegments(String contentDisposition, String contentType) throws FileDownloaderServiceException {
if (contentDisposition == null && contentType == null) {
throw new FileDownloaderServiceException("Cannot determine the file name for the remote file");
}
if (contentDisposition == null) {
String extension;
if (contentType.equals(Constants.MIME_TYPE_VND_ANDROID_PACKAGE_ARCHIVE)) {
extension = Constants.EXTENSION_APK;
} else if (contentType.equals(Constants.MIME_TYPE_OCTET_STREAM)) {
extension = Constants.EXTENSION_IPA;
} else if (contentType.equals(Constants.MIME_TYPE_VND_APPX)) {
extension = Constants.EXTENSION_APPX;
} else if (contentType.equals(Constants.MIME_TYPE_X_MS_INSTALLER)
|| contentType.equals(Constants.MIME_TYPE_VND_MS_WINDOWS_MSI)) {
extension = Constants.EXTENSION_MSI;
} else {
String []contentTypeSegments = contentType.split("/");
if (contentTypeSegments.length != 2) {
throw new FileDownloaderServiceException("Encountered wrong content type header value");
}
extension = contentTypeSegments[contentTypeSegments.length - 1];
}
return new String[]{ UUID.randomUUID().toString(), extension};
}
String []contentDispositionSegments = contentDisposition.split("=");
if (contentDispositionSegments.length != 2) {
throw new FileDownloaderServiceException("Error encountered when constructing file name");
}
String fullQualifiedName = contentDispositionSegments[contentDispositionSegments.length - 1].replace("\"", "");
String []fileNameSegments = fullQualifiedName.split("\\.(?=[^.]+$)");
if (fileNameSegments.length != 2) {
throw new FileDownloaderServiceException("Error encountered when constructing file name");
}
return fileNameSegments;
}
}
}

@ -0,0 +1,124 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.core.impl;
import io.entgra.device.mgt.core.application.mgt.common.ChunkDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry;
import io.entgra.device.mgt.core.application.mgt.common.TransferLink;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferServiceException;
import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService;
import io.entgra.device.mgt.core.application.mgt.core.exception.FileTransferServiceHelperUtilException;
import io.entgra.device.mgt.core.application.mgt.core.util.FileTransferServiceHelperUtil;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.NotFoundException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class FileTransferServiceImpl implements FileTransferService {
private final static Log log = LogFactory.getLog(FileTransferServiceImpl.class);
private static volatile FileTransferServiceImpl INSTANCE;
private FileTransferServiceImpl() throws FileTransferServiceException {
try {
FileTransferServiceHelperUtil.createDefaultRootStructure();
} catch (FileTransferServiceHelperUtilException e) {
String msg = "Error occurred while initializing file transfer service";
log.error(msg, e);
throw new FileTransferServiceException(msg, e);
}
}
public static FileTransferService getInstance() throws FileTransferServiceException{
if (INSTANCE == null) {
synchronized (FileTransferServiceImpl.class) {
if (INSTANCE == null) {
INSTANCE = new FileTransferServiceImpl();
}
}
}
return INSTANCE;
}
@Override
public TransferLink generateUploadLink(FileMetaEntry fileMetaEntry) throws FileTransferServiceException {
try {
Path artifactHolder = FileTransferServiceHelperUtil.createNewArtifactHolder(fileMetaEntry);
String []pathSegments = artifactHolder.toString().split(FileSystems.getDefault().getSeparator());
TransferLink.TransferLinkBuilder transferLinkBuilder =
new TransferLink.TransferLinkBuilder(pathSegments[pathSegments.length - 1]);
return transferLinkBuilder.build();
} catch (FileTransferServiceHelperUtilException e) {
String msg = "Error encountered while generating upload link";
log.error(msg, e);
throw new FileTransferServiceException(msg, e);
}
}
@Override
public ChunkDescriptor resolve(String artifactHolder, InputStream chunk) throws FileTransferServiceException, NotFoundException {
ChunkDescriptor chunkDescriptor = new ChunkDescriptor();
try {
FileTransferServiceHelperUtil.populateChunkDescriptor(artifactHolder, chunk, chunkDescriptor);
return chunkDescriptor;
} catch (FileTransferServiceHelperUtilException e) {
String msg = "Error occurred while resolving chuck descriptor for " + artifactHolder;
log.error(msg);
throw new FileTransferServiceException(msg, e);
}
}
@Override
public void writeChunk(ChunkDescriptor chunkDescriptor) throws FileTransferServiceException {
try {
FileTransferServiceHelperUtil.writeChunk(chunkDescriptor);
} catch (FileTransferServiceHelperUtilException e) {
String msg = "Failed to write data to artifact located in " + chunkDescriptor.getAssociateFileDescriptor().getAbsolutePath();
log.error(msg);
throw new FileTransferServiceException(msg, e);
}
}
@Override
public boolean isExistsOnLocal(URL downloadUrl) throws FileTransferServiceException {
try {
return FileTransferServiceHelperUtil.resolve(downloadUrl) != null;
} catch (FileTransferServiceHelperUtilException e) {
String msg = "Error occurred while checking the existence of artifact on the local environment";
log.error(msg, e);
throw new FileTransferServiceException(msg, e);
}
}
@Override
public FileDescriptor resolve(URL downloadUrl) throws FileTransferServiceException {
try {
return FileTransferServiceHelperUtil.resolve(downloadUrl);
} catch (FileTransferServiceHelperUtilException e) {
String msg = "Error occurred while resolving file descriptor pointing from " + downloadUrl;
log.error(msg, e);
throw new FileTransferServiceException(msg, e);
}
}
}

@ -21,6 +21,7 @@ import io.entgra.device.mgt.core.application.mgt.common.config.LifecycleState;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationStorageManager;
import io.entgra.device.mgt.core.application.mgt.common.services.AppmDataHandler;
import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService;
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
@ -28,6 +29,7 @@ import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationM
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.core.dao.common.ApplicationManagementDAOFactory;
import io.entgra.device.mgt.core.application.mgt.core.impl.AppmDataHandlerImpl;
import io.entgra.device.mgt.core.application.mgt.core.impl.FileTransferServiceImpl;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.application.mgt.core.task.ScheduledAppSubscriptionTaskManager;
import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil;
@ -123,6 +125,10 @@ public class ApplicationManagementServiceComponent {
DataHolder.getInstance().setVppApplicationManager(vppApplicationManager);
bundleContext.registerService(VPPApplicationManager.class.getName(), vppApplicationManager, null);
FileTransferService fileTransferService = FileTransferServiceImpl.getInstance();
DataHolder.getInstance().setFileTransferService(fileTransferService);
bundleContext.registerService(FileTransferService.class.getName(), fileTransferService, null);
ScheduledAppSubscriptionTaskManager taskManager = new ScheduledAppSubscriptionTaskManager();
taskManager.scheduleCleanupTask();

@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.application.mgt.core.internal;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationStorageManager;
import io.entgra.device.mgt.core.application.mgt.common.services.AppmDataHandler;
import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
@ -55,6 +56,7 @@ public class DataHolder {
private AppmDataHandler configManager;
private TaskService taskService;
private FileTransferService fileTransferService;
private static final DataHolder applicationMgtDataHolder = new DataHolder();
@ -153,4 +155,12 @@ public class DataHolder {
public void setVppApplicationManager(VPPApplicationManager vppApplicationManager) {
this.vppApplicationManager = vppApplicationManager;
}
public FileTransferService getFileTransferService() {
return fileTransferService;
}
public void setFileTransferService(FileTransferService fileTransferService) {
this.fileTransferService = fileTransferService;
}
}

@ -59,4 +59,5 @@ public class ScheduledAppSubscriptionCleanupTask extends RandomlyAssignedSchedul
public String getTaskName() {
return TASK_NAME;
}
}

@ -145,4 +145,5 @@ public class ScheduledAppSubscriptionTask extends RandomlyAssignedScheduleTask {
public String getTaskName() {
return TASK_NAME;
}
}

@ -74,6 +74,7 @@ public class APIUtil {
private static volatile AppmDataHandler appmDataHandler;
private static volatile VPPApplicationManager vppApplicationManager;
private static volatile MetadataManagementService metadataManagementService;
private static volatile FileTransferService fileTransferService;
public static SPApplicationManager getSPApplicationManager() {
if (SPApplicationManager == null) {
@ -309,7 +310,8 @@ public class APIUtil {
if (param instanceof ApplicationWrapper){
ApplicationWrapper applicationWrapper = (ApplicationWrapper) param;
DeviceType deviceType = getDeviceTypeData(applicationWrapper.getDeviceType());
applicationDTO.setName(applicationWrapper.getName());
applicationDTO.setName(ApplicationManagementUtil.sanitizeName(applicationWrapper.getName(),
Constants.ApplicationProperties.NAME));
applicationDTO.setDescription(applicationWrapper.getDescription());
applicationDTO.setAppCategories(applicationWrapper.getCategories());
applicationDTO.setType(ApplicationType.ENTERPRISE.toString());
@ -323,7 +325,8 @@ public class APIUtil {
applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities);
} else if (param instanceof WebAppWrapper){
WebAppWrapper webAppWrapper = (WebAppWrapper) param;
applicationDTO.setName(webAppWrapper.getName());
applicationDTO.setName(ApplicationManagementUtil.sanitizeName(webAppWrapper.getName(),
Constants.ApplicationProperties.NAME));
applicationDTO.setDescription(webAppWrapper.getDescription());
applicationDTO.setAppCategories(webAppWrapper.getCategories());
applicationDTO.setSubType(webAppWrapper.getSubMethod());
@ -331,13 +334,14 @@ public class APIUtil {
applicationDTO.setType(webAppWrapper.getType());
applicationDTO.setTags(webAppWrapper.getTags());
applicationDTO.setUnrestrictedRoles(webAppWrapper.getUnrestrictedRoles());
applicationReleaseEntities = webAppWrapper.getWebAppReleaseWrappers()
applicationReleaseEntities = webAppWrapper.getWebAppReleaseWrappers()
.stream().map(APIUtil::releaseWrapperToReleaseDTO).collect(Collectors.toList());
applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities);
} else if (param instanceof PublicAppWrapper) {
PublicAppWrapper publicAppWrapper = (PublicAppWrapper) param;
DeviceType deviceType = getDeviceTypeData(publicAppWrapper.getDeviceType());
applicationDTO.setName(publicAppWrapper.getName());
applicationDTO.setName(ApplicationManagementUtil.sanitizeName(publicAppWrapper.getName(),
Constants.ApplicationProperties.NAME));
applicationDTO.setDescription(publicAppWrapper.getDescription());
applicationDTO.setAppCategories(publicAppWrapper.getCategories());
applicationDTO.setType(ApplicationType.PUBLIC.toString());
@ -352,7 +356,8 @@ public class APIUtil {
} else if (param instanceof CustomAppWrapper){
CustomAppWrapper customAppWrapper = (CustomAppWrapper) param;
DeviceType deviceType = getDeviceTypeData(customAppWrapper.getDeviceType());
applicationDTO.setName(customAppWrapper.getName());
applicationDTO.setName(ApplicationManagementUtil.sanitizeName(customAppWrapper.getName(),
Constants.ApplicationProperties.NAME));
applicationDTO.setDescription(customAppWrapper.getDescription());
applicationDTO.setAppCategories(customAppWrapper.getCategories());
applicationDTO.setType(ApplicationType.CUSTOM.toString());
@ -491,7 +496,6 @@ public class APIUtil {
List<String> screenshotPaths = new ArrayList<>();
ApplicationRelease applicationRelease = new ApplicationRelease();
UrlValidator urlValidator = new UrlValidator();
applicationRelease.setDescription(applicationReleaseDTO.getDescription());
applicationRelease.setVersion(applicationReleaseDTO.getVersion());
@ -514,13 +518,8 @@ public class APIUtil {
.getBannerName());
}
if (urlValidator.isValid(applicationReleaseDTO.getInstallerName())) {
applicationRelease.setInstallerPath(applicationReleaseDTO.getInstallerName());
} else {
applicationRelease.setInstallerPath(
basePath + Constants.APP_ARTIFACT + Constants.FORWARD_SLASH + applicationReleaseDTO
.getInstallerName());
}
applicationRelease.setInstallerPath(constructInstallerPath(applicationReleaseDTO.getInstallerName(),
applicationReleaseDTO.getAppHashValue()));
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName1())) {
screenshotPaths
@ -541,6 +540,21 @@ public class APIUtil {
return applicationRelease;
}
/**
* Construct installer path
* @param installerName Installer name
* @param appHash Application hash
* @return Constructed installer path value
* @throws ApplicationManagementException Throws when error encountered while constructing installer path
*/
public static String constructInstallerPath(String installerName, String appHash) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
UrlValidator urlValidator = new UrlValidator();
String basePath = getArtifactDownloadBaseURL() + tenantId + Constants.FORWARD_SLASH + appHash + Constants.FORWARD_SLASH;
return urlValidator.isValid(installerName) ? installerName
: basePath + Constants.APP_ARTIFACT + Constants.FORWARD_SLASH + installerName;
}
public static String getArtifactDownloadBaseURL() throws ApplicationManagementException {
String host = System.getProperty(Constants.IOT_CORE_HOST);
MDMConfig mdmConfig = ConfigurationManager.getInstance().getConfiguration().getMdmConfig();
@ -587,4 +601,16 @@ public class APIUtil {
}
return metadataManagementService;
}
public static FileTransferService getFileTransferService() {
if (fileTransferService == null) {
synchronized (APIUtil.class) {
if (fileTransferService == null) {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
fileTransferService = (FileTransferService) ctx.getOSGiService(FileTransferService.class, null);
}
}
}
return fileTransferService;
}
}

@ -17,18 +17,27 @@
*/
package io.entgra.device.mgt.core.application.mgt.core.util;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationArtifact;
import io.entgra.device.mgt.core.application.mgt.common.FileDataHolder;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.LifecycleChanger;
import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationReleaseDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.ItuneAppDTO;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileDownloaderServiceException;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferServiceException;
import io.entgra.device.mgt.core.application.mgt.common.exception.InvalidConfigurationException;
import io.entgra.device.mgt.core.application.mgt.common.exception.RequestValidatingException;
import io.entgra.device.mgt.core.application.mgt.common.response.Application;
import io.entgra.device.mgt.core.application.mgt.common.response.Category;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationStorageManager;
import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService;
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
@ -45,15 +54,18 @@ import io.entgra.device.mgt.core.application.mgt.common.wrapper.WebAppWrapper;
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.core.config.Extension;
import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException;
import io.entgra.device.mgt.core.application.mgt.core.impl.FileDownloaderServiceProvider;
import io.entgra.device.mgt.core.application.mgt.core.impl.VppApplicationManagerImpl;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.device.mgt.common.Base64File;
import io.entgra.device.mgt.core.device.mgt.common.DeviceManagementConstants;
import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
import io.entgra.device.mgt.core.device.mgt.core.common.util.FileUtil;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.MetadataManagementServiceImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -74,6 +86,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
/**
@ -159,6 +172,49 @@ public class ApplicationManagementUtil {
return applicationArtifact;
}
public static ApplicationArtifact constructApplicationArtifact(String iconLink, List<String> screenshotLinks, String artifactLink, String bannerLink)
throws MalformedURLException, FileDownloaderServiceException {
ApplicationArtifact applicationArtifact = new ApplicationArtifact();
FileDescriptor fileDescriptor;
if (artifactLink != null) {
URL artifactLinkUrl = new URL(artifactLink);
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(artifactLinkUrl).download(artifactLinkUrl);
applicationArtifact.setInstallerName(fileDescriptor.getFullQualifiedName());
applicationArtifact.setInstallerStream(fileDescriptor.getFile());
}
if (iconLink != null) {
URL iconLinkUrl = new URL(iconLink);
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(iconLinkUrl).download(iconLinkUrl);
applicationArtifact.setIconName(fileDescriptor.getFullQualifiedName());
applicationArtifact.setIconStream(fileDescriptor.getFile());
}
if (bannerLink != null) {
URL bannerLinkUrl = new URL(bannerLink);
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(bannerLinkUrl).download(bannerLinkUrl);
applicationArtifact.setBannerName(fileDescriptor.getFullQualifiedName());
applicationArtifact.setBannerStream(fileDescriptor.getFile());
}
if (screenshotLinks != null) {
Map<String, InputStream> screenshotData = new TreeMap<>();
// This is to handle cases in which multiple screenshots have the same name
Map<String, Integer> screenshotNameCount = new HashMap<>();
URL screenshotLinkUrl;
for (String screenshotLink : screenshotLinks) {
screenshotLinkUrl = new URL(screenshotLink);
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(screenshotLinkUrl).download(screenshotLinkUrl);
String screenshotName = fileDescriptor.getFullQualifiedName();
screenshotNameCount.put(screenshotName, screenshotNameCount.getOrDefault(screenshotName, 0) + 1);
screenshotName = FileUtil.generateDuplicateFileName(screenshotName, screenshotNameCount.get(screenshotName));
screenshotData.put(screenshotName, fileDescriptor.getFile());
}
applicationArtifact.setScreenshots(screenshotData);
}
return applicationArtifact;
}
/**
*
* @param base64File Base64File that should be converted to FileDataHolder bean
@ -251,6 +307,41 @@ public class ApplicationManagementUtil {
throw new IllegalArgumentException("Provided bean does not belong to an Application Wrapper");
}
public static <T> boolean getRemoteStatus(T appWrapper) {
if (!isReleaseAvailable(appWrapper)) {
return false;
}
if (appWrapper instanceof ApplicationWrapper) {
return getRemoteStatusFromWrapper(((ApplicationWrapper) appWrapper).getEntAppReleaseWrappers().get(0));
}
if (appWrapper instanceof PublicAppWrapper) {
return getRemoteStatusFromWrapper(((PublicAppWrapper) appWrapper).getPublicAppReleaseWrappers().get(0));
}
if (appWrapper instanceof WebAppWrapper) {
return getRemoteStatusFromWrapper(((WebAppWrapper) appWrapper).getWebAppReleaseWrappers().get(0));
}
if (appWrapper instanceof CustomAppWrapper) {
return getRemoteStatusFromWrapper(((CustomAppWrapper) appWrapper).getCustomAppReleaseWrappers().get(0));
}
throw new IllegalArgumentException("Provided bean does not belong to an Application Wrapper");
}
public static <T> boolean getRemoteStatusFromWrapper(T releaseWrapper) {
if (releaseWrapper instanceof EntAppReleaseWrapper) {
return ((EntAppReleaseWrapper) releaseWrapper).isRemoteStatus();
}
if (releaseWrapper instanceof PublicAppReleaseWrapper) {
return ((PublicAppReleaseWrapper) releaseWrapper).isRemoteStatus();
}
if (releaseWrapper instanceof WebAppReleaseWrapper) {
return ((WebAppReleaseWrapper) releaseWrapper).isRemoteStatus();
}
if (releaseWrapper instanceof CustomAppReleaseWrapper) {
return ((CustomAppReleaseWrapper) releaseWrapper).isRemoteStatus();
}
throw new IllegalArgumentException("Provided bean does not belong to an Release Wrapper");
}
public static <T> T getInstance(Extension extension, Class<T> cls) throws InvalidConfigurationException {
try {
Class theClass = Class.forName(extension.getClassName());
@ -279,13 +370,12 @@ public class ApplicationManagementUtil {
ApplicationManager applicationManager = APIUtil.getApplicationManager();
List<Category> categories = applicationManager.getRegisteredCategories();
if (product != null && product.getVersion() != null) {
// Generate artifacts
ApplicationArtifact applicationArtifact = generateArtifacts(product);
List<String> packageNamesOfApps = new ArrayList<>();
packageNamesOfApps.add(product.getPackageName());
List<Application> existingApps = applicationManager.getApplications(packageNamesOfApps);
PublicAppReleaseWrapper publicAppReleaseWrapper = generatePublicAppReleaseWrapper(product);
if (existingApps != null && existingApps.size() > 0) {
Application app = existingApps.get(0);
@ -293,7 +383,6 @@ public class ApplicationManagementUtil {
ApplicationUpdateWrapper applicationUpdateWrapper = generatePubAppUpdateWrapper(product, categories);
applicationManager.updateApplication(app.getId(), applicationUpdateWrapper);
PublicAppReleaseWrapper publicAppReleaseWrapper = new PublicAppReleaseWrapper();
if (app.getSubMethod()
.equalsIgnoreCase(Constants.ApplicationProperties.FREE_SUB_METHOD)) {
publicAppReleaseWrapper.setPrice(0.0);
@ -306,56 +395,48 @@ public class ApplicationManagementUtil {
publicAppReleaseWrapper.setVersion(product.getVersion());
publicAppReleaseWrapper.setSupportedOsVersions("4.0-12.3");
applicationManager.updatePubAppRelease(app.getApplicationReleases().get(0).getUuid(),
publicAppReleaseWrapper, applicationArtifact);
publicAppReleaseWrapper);
return;
}
} else {
// Generate App wrapper
PublicAppWrapper publicAppWrapper = generatePubAppWrapper(product, categories);
PublicAppReleaseWrapper appReleaseWrapper = new PublicAppReleaseWrapper();
if (publicAppWrapper.getSubMethod()
.equalsIgnoreCase(Constants.ApplicationProperties.FREE_SUB_METHOD)) {
appReleaseWrapper.setPrice(0.0);
} else {
appReleaseWrapper.setPrice(1.0);
}
appReleaseWrapper.setDescription(product.getDescription());
appReleaseWrapper.setReleaseType("ga");
appReleaseWrapper.setVersion(product.getVersion());
appReleaseWrapper.setPackageName(product.getPackageName());
appReleaseWrapper.setSupportedOsVersions("4.0-12.3");
publicAppWrapper.setPublicAppReleaseWrappers(
Arrays.asList(new PublicAppReleaseWrapper[]{appReleaseWrapper}));
try {
updateImages(appReleaseWrapper, applicationArtifact.getIconName(),
applicationArtifact.getIconStream(), applicationArtifact.getScreenshots());
Application application = applicationManager.createApplication(publicAppWrapper, false);
if (application != null && (application.getApplicationReleases().get(0).getCurrentStatus() == null
|| application.getApplicationReleases().get(0).getCurrentStatus().equals("CREATED"))) {
String uuid = application.getApplicationReleases().get(0).getUuid();
LifecycleChanger lifecycleChanger = new LifecycleChanger();
lifecycleChanger.setAction("IN-REVIEW");
applicationManager.changeLifecycleState(uuid, lifecycleChanger);
lifecycleChanger.setAction("APPROVED");
applicationManager.changeLifecycleState(uuid, lifecycleChanger);
lifecycleChanger.setAction("PUBLISHED");
applicationManager.changeLifecycleState(uuid, lifecycleChanger);
}
} catch (IOException e) {
String msg = "Error while downloading images of release.";
log.error(msg);
throw new ApplicationManagementException(msg, e);
Arrays.asList(new PublicAppReleaseWrapper[]{publicAppReleaseWrapper}));
Application application = applicationManager.createApplication(publicAppWrapper, false);
if (application != null && (application.getApplicationReleases().get(0).getCurrentStatus() == null
|| application.getApplicationReleases().get(0).getCurrentStatus().equals("CREATED"))) {
String uuid = application.getApplicationReleases().get(0).getUuid();
LifecycleChanger lifecycleChanger = new LifecycleChanger();
lifecycleChanger.setAction("IN-REVIEW");
applicationManager.changeLifecycleState(uuid, lifecycleChanger);
lifecycleChanger.setAction("APPROVED");
applicationManager.changeLifecycleState(uuid, lifecycleChanger);
lifecycleChanger.setAction("PUBLISHED");
applicationManager.changeLifecycleState(uuid, lifecycleChanger);
}
}
}
}
private static PublicAppReleaseWrapper generatePublicAppReleaseWrapper(ItuneAppDTO product) {
PublicAppReleaseWrapper publicAppReleaseWrapper = new PublicAppReleaseWrapper();
publicAppReleaseWrapper.setDescription(product.getDescription());
publicAppReleaseWrapper.setReleaseType("ga");
publicAppReleaseWrapper.setVersion(product.getVersion());
publicAppReleaseWrapper.setPackageName(product.getPackageName());
publicAppReleaseWrapper.setSupportedOsVersions("4.0-12.3");
publicAppReleaseWrapper.setIconLink(product.getIconURL());
publicAppReleaseWrapper.setRemoteStatus(false);
List<String> screenshotUrls = new ArrayList<>(Collections.nCopies(3, product.getIconURL()));
publicAppReleaseWrapper.setScreenshotLinks(screenshotUrls);
publicAppReleaseWrapper.setPrice(1.0);
return publicAppReleaseWrapper;
}
private static PublicAppWrapper generatePubAppWrapper(ItuneAppDTO product, List<Category> categories) {
PublicAppWrapper publicAppWrapper = new PublicAppWrapper();
publicAppWrapper.setName(product.getTitle());
@ -535,4 +616,102 @@ public class ApplicationManagementUtil {
packageNamesOfApps.add(adamId);
return applicationManager.getApplications(packageNamesOfApps);
}
/**
* Sanitize app names and shorten icon/screenshot file names
*
* @param originalName Original name of the file which is being uploaded
* @param type Type - Name/Artifact(Icon, Screenshot, etc.)
* @return Sanitized and shortened file name
*/
public static String sanitizeName(String originalName, String type) {
String sanitizedName = originalName.replaceAll(Constants.APP_NAME_REGEX, "");
if (Constants.ApplicationProperties.NAME.equals(type) && sanitizedName.length() > Constants.MAX_APP_NAME_CHARACTERS) {
sanitizedName = sanitizedName.substring(0, Constants.MAX_APP_NAME_CHARACTERS);
return sanitizedName;
} else if (Constants.ICON_NAME.equals(type) || Constants.SCREENSHOT_NAME.equals(type)) {
// Shortening icon/screenshot names
String fileExtension = "";
int dotIndex = originalName.lastIndexOf('.');
if (dotIndex >= 0) {
fileExtension = originalName.substring(dotIndex);
}
return type + fileExtension;
} else {
return sanitizedName;
}
}
public static <T> List<?> deriveApplicationWithoutRelease(T app) {
List<?> releaseWrappers = null;
if (app instanceof ApplicationWrapper) {
ApplicationWrapper applicationWrapper = (ApplicationWrapper) app;
releaseWrappers = applicationWrapper.getEntAppReleaseWrappers();
applicationWrapper.setEntAppReleaseWrappers(Collections.emptyList());
}
if (app instanceof CustomAppWrapper) {
CustomAppWrapper applicationWrapper = (CustomAppWrapper) app;
releaseWrappers = applicationWrapper.getCustomAppReleaseWrappers();
applicationWrapper.setCustomAppReleaseWrappers(Collections.emptyList());
}
return releaseWrappers;
}
/**
* Add installer path metadata value to windows applications
* @param applicationReleaseDTO {@link ApplicationReleaseDTO}
* @throws ApplicationManagementException Throws when error encountered while updating the app metadata
*/
public static void addInstallerPathToMetadata(ApplicationReleaseDTO applicationReleaseDTO)
throws ApplicationManagementException {
if (applicationReleaseDTO.getMetaData() == null) return;
Gson gson = new Gson();
String installerPath = APIUtil.constructInstallerPath(applicationReleaseDTO.getInstallerName(), applicationReleaseDTO.getAppHashValue());
String[] fileNameSegments = extractNameSegments(applicationReleaseDTO, installerPath);
String extension = fileNameSegments[fileNameSegments.length - 1];
if (!Objects.equals(extension, "appx") && !Objects.equals(extension, "msi")) {
return;
}
String installerPaths = "[ {" +
"\"key\": \"Content_Uri\", " +
"\"value\" : \"" + installerPath + "\"" +
"}]";
if (Objects.equals(extension, "appx")) {
installerPaths = "[ {" +
"\"key\": \"Package_Url\", " +
"\"value\" : \"" + installerPath + "\"" +
"}]";
}
JsonArray parsedMetadataList = gson.fromJson(applicationReleaseDTO.getMetaData(), JsonArray.class);
JsonArray installerPathsArray = gson.fromJson(installerPaths, JsonArray.class);
parsedMetadataList.addAll(installerPathsArray);
applicationReleaseDTO.setMetaData(gson.toJson(parsedMetadataList));
}
/**
* Extract name segments from installer path
* @param applicationReleaseDTO {@link ApplicationReleaseDTO}
* @param installerPath Installer path
* @return Extracted file name segments
* @throws ApplicationManagementException Throws when error encountered while extracting name segments from installer path
*/
private static String[] extractNameSegments(ApplicationReleaseDTO applicationReleaseDTO, String installerPath)
throws ApplicationManagementException {
String []installerPathSegments = installerPath.split("/");
if (installerPathSegments.length == 0) {
throw new ApplicationManagementException("Received malformed url for installer path of the app : "
+ applicationReleaseDTO.getInstallerName());
}
String fullQualifiedName = installerPathSegments[installerPathSegments.length - 1];
String []fileNameSegments = fullQualifiedName.split("\\.(?=[^.]+$)");
if (fileNameSegments.length != 2) {
throw new ApplicationManagementException("Received malformed url for installer path of the app : "
+ applicationReleaseDTO.getInstallerName());
}
return fileNameSegments;
}
}

@ -214,4 +214,20 @@ public class Constants {
public static final String ASSOCIATION_DEVICE = "ASSOCIATION_DEVICE";
public static final String ASSOCIATION_USER = "ASSOCIATION_USER";
}
/**
* App name sanitization related constants
*/
public static final int MAX_APP_NAME_CHARACTERS = 350;
public static final String APP_NAME_REGEX = "[^a-zA-Z0-9.\\s-]";
public static final String EXTENSION_APK = ".apk";
public static final String EXTENSION_IPA = ".ipa";
public static final String EXTENSION_MSI = ".msi";
public static final String EXTENSION_APPX = ".appx";
public static final String MIME_TYPE_OCTET_STREAM = "application/octet-stream";
public static final String MIME_TYPE_VND_ANDROID_PACKAGE_ARCHIVE = "application/vnd.android.package-archive";
public static final String MIME_TYPE_VND_MS_WINDOWS_MSI = "application/vnd.ms-windows.msi";
public static final String MIME_TYPE_X_MS_INSTALLER = "application/x-ms-installer";
public static final String MIME_TYPE_VND_APPX = "application/vnd.appx";
}

@ -0,0 +1,237 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.application.mgt.core.util;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.application.mgt.common.ChunkDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry;
import io.entgra.device.mgt.core.application.mgt.core.exception.FileTransferServiceHelperUtilException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.NotFoundException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Objects;
import java.util.UUID;
public class FileTransferServiceHelperUtil {
private static final Log log = LogFactory.getLog(FileTransferServiceHelperUtil.class);
private static final String ROOT = "iot-artifact-holder";
private static final String SYSTEM_PROPERTY_TEMP_DIR = "java.io.tmpdir";
private static final String META_ENTRY_FILE_NAME = ".meta.json";
private static final Gson gson = new Gson();
public static void createDefaultRootStructure() throws FileTransferServiceHelperUtilException {
try {
Path root = Paths.get(System.getProperty(SYSTEM_PROPERTY_TEMP_DIR), ROOT);
if (Files.notExists(root)) {
setMinimumPermissions(Files.createDirectory(root));
}
if (!Files.isDirectory(root)) {
throw new FileTransferServiceHelperUtilException(root.toAbsolutePath() + " is not a directory");
}
setMinimumPermissions(root);
} catch (IOException e) {
String msg = "Error encountered while creating default artifact root structure";
log.error(msg, e);
throw new FileTransferServiceHelperUtilException(msg, e);
}
}
public static Path createNewArtifactHolder(FileMetaEntry fileMetaEntry) throws FileTransferServiceHelperUtilException {
try {
Path artifactHolder = Paths.get(System.getProperty(SYSTEM_PROPERTY_TEMP_DIR), ROOT, UUID.randomUUID().toString());
if (Files.exists(artifactHolder)) {
throw new FileTransferServiceHelperUtilException("Artifact holder already exists in " + artifactHolder);
}
setMinimumPermissions(Files.createDirectory(artifactHolder));
createMetaEntry(fileMetaEntry, artifactHolder);
createArtifactFile(fileMetaEntry, artifactHolder);
return artifactHolder;
} catch (IOException e) {
String msg = "Error occurred while creating artifact holder";
log.error(msg, e);
throw new FileTransferServiceHelperUtilException(msg, e);
}
}
public static void populateChunkDescriptor(String artifactHolder, InputStream chunk, ChunkDescriptor chunkDescriptor)
throws FileTransferServiceHelperUtilException, NotFoundException {
Path holder = locateArtifactHolder(artifactHolder);
Path metaEntry = locateMetaEntry(holder);
chunkDescriptor.setChunk(chunk);
FileDescriptor fileDescriptor = new FileDescriptor();
populateFileDescriptor(metaEntry, holder, fileDescriptor);
chunkDescriptor.setAssociateFileDescriptor(fileDescriptor);
}
public static void populateFileDescriptor(String artifactHolder, FileDescriptor fileDescriptor)
throws FileTransferServiceHelperUtilException, NotFoundException {
Path holder = locateArtifactHolder(artifactHolder);
Path metaEntry = locateMetaEntry(holder);
populateFileDescriptor(metaEntry, holder, fileDescriptor);
}
public static void populateFileDescriptor(Path metaEntry, Path artifactHolder, FileDescriptor fileDescriptor) throws FileTransferServiceHelperUtilException {
try {
byte []metaEntryByteContent = Files.readAllBytes(metaEntry);
FileMetaEntry fileMetaEntry = gson.fromJson(new String(metaEntryByteContent, StandardCharsets.UTF_8), FileMetaEntry.class);
fileDescriptor.setFileName(fileMetaEntry.getFileName());
fileDescriptor.setActualFileSize(fileMetaEntry.getSize());
fileDescriptor.setFullQualifiedName(fileMetaEntry.getFileName() + "." + fileMetaEntry.getExtension());
Path artifact = artifactHolder.resolve(fileDescriptor.getFullQualifiedName());
fileDescriptor.setAbsolutePath(artifact.toAbsolutePath().toString());
fileDescriptor.setExtension(fileMetaEntry.getExtension());
fileDescriptor.setFile(Files.newInputStream(artifact));
} catch (IOException e) {
String msg = "Error encountered while populating chuck descriptor";
log.error(msg, e);
throw new FileTransferServiceHelperUtilException(msg, e);
}
}
private static Path locateArtifactHolder(String artifactHolder) throws FileTransferServiceHelperUtilException, NotFoundException {
Path holder = Paths.get(System.getProperty(SYSTEM_PROPERTY_TEMP_DIR), ROOT, artifactHolder);
if (Files.notExists(holder)) {
throw new NotFoundException(holder.toAbsolutePath() + " is not exists");
}
if (!Files.isDirectory(holder)) {
throw new FileTransferServiceHelperUtilException(holder.toFile().getAbsolutePath() + " is not a directory");
}
return holder;
}
private static Path locateMetaEntry(Path artifactHolder) throws FileTransferServiceHelperUtilException {
Path metaEntry = artifactHolder.resolve(META_ENTRY_FILE_NAME);
if (Files.notExists(metaEntry) || Files.isDirectory(metaEntry)) {
throw new FileTransferServiceHelperUtilException("Can't locate " + META_ENTRY_FILE_NAME);
}
if (!Files.isReadable(metaEntry)) {
throw new FileTransferServiceHelperUtilException("Unreadable " + META_ENTRY_FILE_NAME);
}
return metaEntry;
}
public static void writeChunk(ChunkDescriptor chunkDescriptor) throws FileTransferServiceHelperUtilException {
if (chunkDescriptor == null) {
throw new FileTransferServiceHelperUtilException("Received null for chuck descriptor");
}
FileDescriptor fileDescriptor = chunkDescriptor.getAssociateFileDescriptor();
if (fileDescriptor == null) {
throw new FileTransferServiceHelperUtilException("Target file descriptor is missing for retrieved chunk");
}
Path artifact = Paths.get(fileDescriptor.getAbsolutePath());
try {
InputStream chuckStream = chunkDescriptor.getChunk();
byte []chunk = new byte[chuckStream.available()];
chuckStream.read(chunk);
Files.write(artifact, chunk, StandardOpenOption.CREATE, StandardOpenOption.SYNC, StandardOpenOption.APPEND);
} catch (IOException e) {
String msg = "Error encountered while writing to the " + artifact;
log.error(msg, e);
throw new FileTransferServiceHelperUtilException(msg, e);
}
}
public static FileDescriptor resolve(URL downloadUrl) throws FileTransferServiceHelperUtilException {
if (downloadUrl == null) {
throw new FileTransferServiceHelperUtilException("Received null for download url");
}
if (!Objects.equals(System.getProperty("iot.gateway.host"), downloadUrl.getHost()) &&
!Objects.equals(System.getProperty("iot.core.host"), downloadUrl.getHost())) {
if (log.isDebugEnabled()) {
log.debug("Download URL " + downloadUrl + " contains not matching host");
}
return null;
}
String []urlPathSegments = downloadUrl.getPath().split("/");
if (urlPathSegments.length < 2) {
if (log.isDebugEnabled()) {
log.debug("URL patch segments contain less than 2 segments");
}
return null;
}
String file = urlPathSegments[urlPathSegments.length - 1];
String artifactHolder = urlPathSegments[urlPathSegments.length - 2];
try {
FileDescriptor fileDescriptor = new FileDescriptor();
populateFileDescriptor(artifactHolder, fileDescriptor);
if (!Objects.equals(file, fileDescriptor.getFullQualifiedName())) {
if (log.isDebugEnabled()) {
log.debug("File name not equal to the file exists in the local");
}
return null;
}
return fileDescriptor;
} catch (NotFoundException e) {
if (log.isDebugEnabled()) {
log.debug("Local URL not found in the system");
}
return null;
}
}
private static void setMinimumPermissions(Path path) throws FileTransferServiceHelperUtilException {
File file = path.toFile();
if (!file.setReadable(true, true)) {
throw new FileTransferServiceHelperUtilException("Failed to set read permission for " + file.getAbsolutePath());
}
if (!file.setWritable(true, true)) {
throw new FileTransferServiceHelperUtilException("Failed to set write permission for " + file.getAbsolutePath());
}
}
private static void createMetaEntry(FileMetaEntry fileMetaEntry, Path artifactHolder) throws FileTransferServiceHelperUtilException {
try {
Path metaEntry = artifactHolder.resolve(META_ENTRY_FILE_NAME);
String fileMetaJsonContent = gson.toJson(fileMetaEntry);
Files.write(metaEntry, fileMetaJsonContent.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE, StandardOpenOption.SYNC);
} catch (IOException e) {
throw new FileTransferServiceHelperUtilException("Error encountered while creating meta entry", e);
}
}
private static void createArtifactFile(FileMetaEntry fileMetaEntry, Path artifactHolder) throws FileTransferServiceHelperUtilException {
try {
Path artifactFile = artifactHolder.resolve(fileMetaEntry.getFileName() + "." + fileMetaEntry.getExtension());
fileMetaEntry.setAbsolutePath(artifactFile.toAbsolutePath().toString());
Files.createFile(artifactFile);
setMinimumPermissions(artifactFile);
} catch (IOException e) {
throw new FileTransferServiceHelperUtilException("Error encountered while creating artifact file", e);
}
}
}

@ -19,8 +19,13 @@ package io.entgra.device.mgt.core.application.mgt.core.management;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationArtifact;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationList;
import io.entgra.device.mgt.core.application.mgt.common.ChunkDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry;
import io.entgra.device.mgt.core.application.mgt.common.Filter;
import io.entgra.device.mgt.core.application.mgt.common.LifecycleState;
import io.entgra.device.mgt.core.application.mgt.common.TransferLink;
import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService;
import io.entgra.device.mgt.core.application.mgt.core.impl.FileTransferServiceImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
@ -52,6 +57,10 @@ import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceTypeVersion;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderServiceImpl;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -98,32 +107,72 @@ public class ApplicationManagementTest extends BaseTestCase {
EntAppReleaseWrapper releaseWrapper = new EntAppReleaseWrapper();
releaseWrapper.setDescription("First release");
releaseWrapper.setIsSharedWithAllTenants(false);
releaseWrapper.setMetaData("Just meta data");
releaseWrapper.setMetaData("[{\"key\": \"Just a metadata\"}]");
releaseWrapper.setReleaseType("free");
releaseWrapper.setPrice(5.7);
releaseWrapper.setSupportedOsVersions("4.0-7.0");
File banner = new File("src/test/resources/samples/app1/banner1.jpg");
File icon = new File("src/test/resources/samples/app1/icon.png");
File ss1 = new File("src/test/resources/samples/app1/shot1.png");
File ss2 = new File("src/test/resources/samples/app1/shot2.png");
File ss3 = new File("src/test/resources/samples/app1/shot3.png");
Base64File bannerBase64 = new Base64File("banner", FileUtil.fileToBase64String(banner));
Base64File iconBase64 = new Base64File("icon", FileUtil.fileToBase64String(icon));
Base64File ss1Base64 = new Base64File("ss1", FileUtil.fileToBase64String(ss1));
Base64File ss2Base64 = new Base64File("ss2", FileUtil.fileToBase64String(ss2));
Base64File ss3Base64 = new Base64File("ss3", FileUtil.fileToBase64String(ss3));
File apk = new File("src/test/resources/samples/app1/sample.apk");
Base64File apkBase64 = new Base64File("apk", FileUtil.fileToBase64String(apk));
releaseWrapper.setBanner(bannerBase64);
releaseWrapper.setIcon(iconBase64);
releaseWrapper.setBinaryFile(apkBase64);
releaseWrapper.setScreenshots(Arrays.asList(ss1Base64, ss2Base64, ss3Base64));
FileTransferService fileTransferService = FileTransferServiceImpl.getInstance();
DataHolder.getInstance().setFileTransferService(fileTransferService);
FileMetaEntry metaEntry = new FileMetaEntry();
TransferLink transferLink;
String []segments;
ChunkDescriptor chunkDescriptor;
metaEntry.setFileName("banner1");
metaEntry.setExtension("jpg");
metaEntry.setSize(179761);
transferLink = fileTransferService.generateUploadLink(metaEntry);
segments = transferLink.getRelativeTransferLink().split("/");
chunkDescriptor = fileTransferService.
resolve(segments[segments.length-1], Files.newInputStream(
Paths.get("src/test/resources/samples/app1/banner1.jpg")));
fileTransferService.writeChunk(chunkDescriptor);
releaseWrapper.setBannerLink(transferLink.getDirectTransferLink() + "/banner1.jpg");
metaEntry.setFileName("icon");
metaEntry.setExtension("png");
metaEntry.setSize(41236);
transferLink = fileTransferService.generateUploadLink(metaEntry);
segments = transferLink.getRelativeTransferLink().split("/");
chunkDescriptor = fileTransferService.
resolve(segments[segments.length-1], Files.newInputStream(
Paths.get("src/test/resources/samples/app1/icon.png")));
fileTransferService.writeChunk(chunkDescriptor);
releaseWrapper.setIconLink(transferLink.getDirectTransferLink() + "/icon.png");
List<String> screenshotPaths = Arrays.asList("src/test/resources/samples/app1/shot1.png",
"src/test/resources/samples/app1/shot2.png", "src/test/resources/samples/app1/shot3.png");
List<String> screenshotLinks = new ArrayList<>();
String []pathSegments;
for (String path: screenshotPaths) {
pathSegments = path.split("/");
String fullQualifiedName = pathSegments[pathSegments.length - 1];
String []nameSegments = fullQualifiedName.split("\\.(?=[^.]+$)");
metaEntry.setFileName(nameSegments[0]);
metaEntry.setExtension(nameSegments[1]);
metaEntry.setSize(41236);
transferLink = fileTransferService.generateUploadLink(metaEntry);
segments = transferLink.getRelativeTransferLink().split("/");
chunkDescriptor = fileTransferService.
resolve(segments[segments.length-1], Files.newInputStream(Paths.get(path)));
fileTransferService.writeChunk(chunkDescriptor);
screenshotLinks.add(transferLink.getDirectTransferLink() + "/" + fullQualifiedName);
}
releaseWrapper.setScreenshotLinks(screenshotLinks);
metaEntry.setFileName("sample");
metaEntry.setExtension("apk");
metaEntry.setSize(6259412);
TransferLink apkTransferLink = fileTransferService.generateUploadLink(metaEntry);
segments = apkTransferLink.getRelativeTransferLink().split("/");
chunkDescriptor = fileTransferService.
resolve(segments[segments.length-1], Files.newInputStream(Paths.get("src/test/resources/samples/app1/sample.apk")));
fileTransferService.writeChunk(chunkDescriptor);
releaseWrapper.setArtifactLink(apkTransferLink.getDirectTransferLink() + "/sample.apk");
releaseWrapper.setRemoteStatus(false);
entAppReleaseWrappers.add(releaseWrapper);
applicationWrapper.setEntAppReleaseWrappers(entAppReleaseWrappers);

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -18,13 +18,11 @@
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>certificate-mgt</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -346,14 +346,14 @@ public interface DeviceOrganizationMgtService {
Response getDeviceOrganizationLeafs(
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items",
value = "leaf node offset",
required = false,
defaultValue = "0")
@DefaultValue("0") @QueryParam("offset")
int offset,
@ApiParam(
name = "limit",
value = "Provide how many policy details you require from the starting pagination index/offset.",
value = "leaf node limit",
required = false,
defaultValue = "5")
@DefaultValue("20") @QueryParam("limit")
@ -369,8 +369,8 @@ public interface DeviceOrganizationMgtService {
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Retrieve leaf Device Organizations",
notes = "Get a list of leaf device organizations.",
value = "Retrieve root Device Organizations",
notes = "Get a list of root device organizations.",
tags = "Device Organization Management",
extensions = {
@Extension(properties = {
@ -414,19 +414,97 @@ public interface DeviceOrganizationMgtService {
Response getDeviceOrganizationRoots(
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items",
value = "root node offset",
required = false,
defaultValue = "0")
@DefaultValue("0") @QueryParam("offset")
int offset,
@ApiParam(
name = "limit",
value = "Provide how many policy details you require from the starting pagination index/offset.",
value = "root node limit",
required = false,
defaultValue = "5")
defaultValue = "20")
@DefaultValue("20") @QueryParam("limit")
int limit);
/**
* Retrieves a list of root device organizations.
*
* @return A response containing a list of root device organizations.
*/
@GET
@Path("roots/children")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Retrieve children for root Device Organizations",
notes = "Get a list of children for root device organizations.",
tags = "Device Organization Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "dm:device-org:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the all devices.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request. \n"),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the " +
"list of supported device types.",
response = ErrorResponse.class)
})
Response getDeviceOrganizationChildrenForRoots(
@ApiParam(
name = "offset",
value = "root offset",
required = false,
defaultValue = "0")
@DefaultValue("0") @QueryParam("offset")
int offset,
@ApiParam(
name = "limit",
value = "root limit.",
required = false,
defaultValue = "20")
@DefaultValue("20") @QueryParam("limit")
int limit,
@ApiParam(
name= "maxDepth",
value = "The maximum depth of child nodes to retrieve for each root.",
required = true) @QueryParam("maxDepth")
int maxDepth,
@ApiParam(
name= "includeDevice",
value = "Indicates whether to include device information in the retrieved child nodes.",
required = true) @QueryParam("includeDevice")
boolean includeDevice);
/**
* Retrieves a specific device organization by its organization ID.
*

@ -24,6 +24,7 @@ import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.api.u
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNodeResult;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.RootChildrenRequest;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtPluginException;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.spi.DeviceOrganizationService;
import org.apache.commons.logging.Log;
@ -124,6 +125,7 @@ public class DeviceOrganizationMgtServiceImpl implements DeviceOrganizationMgtSe
@DefaultValue("20") @QueryParam("limit") int limit) {
RequestValidationUtil.validatePaginationParameters(offset, limit);
try {
RequestValidationUtil.validatePaginationParameters(offset, limit);
DeviceOrganizationService deviceOrganizationService = DeviceOrgAPIUtils.getDeviceOrganizationService();
PaginationRequest request = new PaginationRequest(offset, limit);
List<DeviceOrganization> organizations = deviceOrganizationService.getDeviceOrganizationLeafs(request);
@ -143,6 +145,7 @@ public class DeviceOrganizationMgtServiceImpl implements DeviceOrganizationMgtSe
@DefaultValue("20") @QueryParam("limit") int limit) {
RequestValidationUtil.validatePaginationParameters(offset, limit);
try {
RequestValidationUtil.validatePaginationParameters(offset, limit);
DeviceOrganizationService deviceOrganizationService = DeviceOrgAPIUtils.getDeviceOrganizationService();
PaginationRequest request = new PaginationRequest(offset, limit);
List<DeviceOrganization> organizations = deviceOrganizationService.getDeviceOrganizationRoots(request);
@ -154,6 +157,30 @@ public class DeviceOrganizationMgtServiceImpl implements DeviceOrganizationMgtSe
}
}
@GET
@Path("roots/children")
@Override
public Response getDeviceOrganizationChildrenForRoots(
@DefaultValue("0") @QueryParam("offset") int offset,
@DefaultValue("20") @QueryParam("limit") int limit,
@QueryParam("maxDepth") int maxDepth,
@QueryParam("includeDevice") boolean includeDevice) {
RequestValidationUtil.validatePaginationParameters(offset, limit);
try {
RequestValidationUtil.validatePaginationParameters(offset, limit);
DeviceOrganizationService deviceOrganizationService = DeviceOrgAPIUtils.getDeviceOrganizationService();
RootChildrenRequest request = new RootChildrenRequest(offset, limit);
request.setMaxDepth(maxDepth);
request.setIncludeDevice(includeDevice);
List<DeviceNodeResult> nodeResultList = deviceOrganizationService.getAllDeviceOrganizationsForRoots(request);
return Response.status(Response.Status.OK).entity(nodeResultList).build();
} catch (DeviceOrganizationMgtPluginException e) {
String errorMessage = "get children for root organizations failed";
log.error(errorMessage);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).build();
}
}
@GET
@Override
@Path("{organizationId}")

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId>
<version>5.0.40-SNAPSHOT</version>
<version>5.0.42-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,3 +1,21 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto;
public class AdditionResult {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -0,0 +1,48 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto;
public class RootChildrenRequest extends PaginationRequest{
int maxDepth;
boolean includeDevice;
public RootChildrenRequest(int start, int limit) {
super(start, limit);
}
public int getMaxDepth() {
return maxDepth;
}
public void setMaxDepth(int maxDepth) {
if (maxDepth < 0) {
throw new IllegalArgumentException("maxDepth cannot be negative");
}
this.maxDepth = maxDepth;
}
public boolean isIncludeDevice() {
return includeDevice;
}
public void setIncludeDevice(boolean includeDevice) {
this.includeDevice = includeDevice;
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@ -20,10 +20,11 @@ package io.entgra.device.mgt.core.device.mgt.extensions.device.organization.impl
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.DeviceOrganizationDAO;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.DeviceOrganizationDAOFactory;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.util.ConnectionManagerUtil;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.AdditionResult;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNodeResult;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.RootChildrenRequest;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.AdditionResult;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.BadRequestException;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DBConnectionException;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtDAOException;
@ -33,7 +34,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
public class DeviceOrganizationServiceImpl implements DeviceOrganizationService {
@ -164,6 +165,34 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService
}
}
/**
* {@inheritDoc}
*/
@Override
public List<DeviceNodeResult> getAllDeviceOrganizationsForRoots(RootChildrenRequest request) throws DeviceOrganizationMgtPluginException {
List<DeviceNodeResult> allDeviceOrganizations = new ArrayList<>();
try {
// Get all root device organizations
PaginationRequest paginationRequest = new PaginationRequest(request.getOffSet(), request.getLimit());
List<DeviceOrganization> roots = getDeviceOrganizationRoots(paginationRequest);
// Iterate over each root and fetch its children
for (DeviceOrganization root : roots) {
DeviceNodeResult childrenResult = getChildrenOfDeviceNode(root.getDeviceId(), request.getMaxDepth(), request.isIncludeDevice());
if (childrenResult != null) {
allDeviceOrganizations.add(childrenResult);
}
}
return allDeviceOrganizations;
} catch (DeviceOrganizationMgtPluginException e) {
String msg = "Error occurred while retrieving all device organizations for roots.";
log.error(msg, e);
throw new DeviceOrganizationMgtPluginException(msg, e);
}
}
/**
* {@inheritDoc}
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.device.mgt.extensions.device.organization.spi;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNodeResult;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.RootChildrenRequest;
import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtPluginException;
import java.util.List;
@ -71,6 +72,15 @@ public interface DeviceOrganizationService {
*/
List<DeviceOrganization> getAllDeviceOrganizations() throws DeviceOrganizationMgtPluginException;
/**
* Retrieves a list of all device organizations for roots.
* @param request
* @return
* @throws DeviceOrganizationMgtPluginException
*/
List<DeviceNodeResult> getAllDeviceOrganizationsForRoots(RootChildrenRequest request)
throws DeviceOrganizationMgtPluginException;
/**
* Retrieves device Organization Leafs
*

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except

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

Loading…
Cancel
Save