diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/ItuneAppDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/ItuneAppDTO.java new file mode 100644 index 00000000000..a76a9ec12b9 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/ItuneAppDTO.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018 - 2023, 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.dto; + +public class ItuneAppDTO { + int id; + String packageName; + String version; + String description; + String title; + String paymentMethod; + String iconURL; + String category; + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getIconURL() { + return iconURL; + } + + public void setIconURL(String iconURL) { + this.iconURL = iconURL; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getPaymentMethod() { + return paymentMethod; + } + + public void setPaymentMethod(String paymentMethod) { + this.paymentMethod = paymentMethod; + } + +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppAssetDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppAssetDTO.java new file mode 100644 index 00000000000..1ce0d3c3cfc --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppAssetDTO.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 - 2023, 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.dto; + +public class VppAssetDTO extends VppItuneAssetDTO { + int id; + int appId; + int tenantId; + String createdTime; + String lastUpdatedTime; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getAppId() { + return appId; + } + + public void setAppId(int appId) { + this.appId = appId; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } + + public String getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(String createdTime) { + this.createdTime = createdTime; + } + + public String getLastUpdatedTime() { + return lastUpdatedTime; + } + + public void setLastUpdatedTime(String lastUpdatedTime) { + this.lastUpdatedTime = lastUpdatedTime; + } + +} \ No newline at end of file diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppItuneAssetDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppItuneAssetDTO.java new file mode 100644 index 00000000000..71e9429c685 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppItuneAssetDTO.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 - 2023, 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 String LicenseString ); 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 + * String AS ISString 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.dto; + +import java.util.List; + +public class VppItuneAssetDTO { + + + String adamId; + String assignedCount; + String availableCount; + String deviceAssignable; + String pricingParam; + String productType; + String retiredCount; + String revocable; + + List supportedPlatforms; + + public List getSupportedPlatforms() { + return supportedPlatforms; + } + + public void setSupportedPlatforms(List supportedPlatforms) { + this.supportedPlatforms = supportedPlatforms; + } + + public String getAdamId() { + return adamId; + } + + public void setAdamId(String adamId) { + this.adamId = adamId; + } + + public String getAssignedCount() { + return assignedCount; + } + + public void setAssignedCount(String assignedCount) { + this.assignedCount = assignedCount; + } + + public String getAvailableCount() { + return availableCount; + } + + public void setAvailableCount(String availableCount) { + this.availableCount = availableCount; + } + + public String getDeviceAssignable() { + return deviceAssignable; + } + + public void setDeviceAssignable(String deviceAssignable) { + this.deviceAssignable = deviceAssignable; + } + + public String getPricingParam() { + return pricingParam; + } + + public void setPricingParam(String pricingParam) { + this.pricingParam = pricingParam; + } + + public String getProductType() { + return productType; + } + + public void setProductType(String productType) { + this.productType = productType; + } + + public String getRetiredCount() { + return retiredCount; + } + + public void setRetiredCount(String retiredCount) { + this.retiredCount = retiredCount; + } + + public String getRevocable() { + return revocable; + } + + public void setRevocable(String revocable) { + this.revocable = revocable; + } + + +} \ No newline at end of file diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppPaginationDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppPaginationDTO.java index 32c4f12f9bc..95cf054f9c8 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppPaginationDTO.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/VppPaginationDTO.java @@ -22,6 +22,7 @@ public class VppPaginationDTO { int currentPageIndex; int size; String tokenExpirationDate; + int nextPageIndex; int totalPages; String uId; String versionId; @@ -50,6 +51,14 @@ public class VppPaginationDTO { this.tokenExpirationDate = tokenExpirationDate; } + public int getNextPageIndex() { + return nextPageIndex; + } + + public void setNextPageIndex(int nextPageIndex) { + this.nextPageIndex = nextPageIndex; + } + public int getTotalPages() { return totalPages; } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/VPPApplicationManager.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/VPPApplicationManager.java index 4b08001e084..55a3ee51b8b 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/VPPApplicationManager.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/VPPApplicationManager.java @@ -19,6 +19,7 @@ package io.entgra.device.mgt.core.application.mgt.common.services; import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse; +import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; @@ -34,5 +35,9 @@ public interface VPPApplicationManager { void syncUsers(String clientId) throws ApplicationManagementException; + void syncAssets(int nextPageIndex) throws ApplicationManagementException; + + VppAssetDTO getAssetByAppId(String appId) throws ApplicationManagementException; + ProxyResponse callVPPBackend(String url, String payload, String accessToken, String method) throws IOException; } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/wrapper/VppItuneAssetResponseWrapper.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/wrapper/VppItuneAssetResponseWrapper.java new file mode 100644 index 00000000000..26c45207abf --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/wrapper/VppItuneAssetResponseWrapper.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 - 2023, 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; + +import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneUserDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.VppPaginationDTO; + +import java.util.ArrayList; +import java.util.List; + +public class VppItuneAssetResponseWrapper extends VppPaginationDTO { + + List assets; + + public List getAssets() { + return assets; + } + + public void setAssets(List assets) { + this.assets = assets; + } + +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/VppApplicationManagerImpl.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/VppApplicationManagerImpl.java index 6ec3023def7..37cf50a394a 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/VppApplicationManagerImpl.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/VppApplicationManagerImpl.java @@ -18,16 +18,18 @@ package io.entgra.device.mgt.core.application.mgt.core.impl; -import com.google.gson.ExclusionStrategy; -import com.google.gson.FieldAttributes; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.entgra.device.mgt.core.application.mgt.common.dto.ItuneAppDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse; +import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneUserDTO; -import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserRequestWrapper; import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager; +import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneAssetResponseWrapper; +import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserRequestWrapper; import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserResponseWrapper; import io.entgra.device.mgt.core.application.mgt.core.dao.ApplicationDAO; import io.entgra.device.mgt.core.application.mgt.core.dao.SPApplicationDAO; @@ -35,11 +37,13 @@ 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.internal.DataHolder; import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager; +import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil; import io.entgra.device.mgt.core.application.mgt.core.util.Constants; import io.entgra.device.mgt.core.application.mgt.core.util.VppHttpUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpStatus; +import org.wso2.carbon.context.PrivilegedCarbonContext; import java.io.IOException; @@ -50,8 +54,14 @@ public class VppApplicationManagerImpl implements VPPApplicationManager { private static final String USER_UPDATE = APP_API + "/users/update"; private static final String USER_GET = APP_API + "/users"; private static final String TOKEN = ""; + private static final String LOOKUP_API = "https://uclient-api.itunes.apple" + + ".com/WebObjects/MZStorePlatform.woa/wa/lookup?version=2&id="; + private static final String LOOKUP_API_PREFIX = + "&p=mdm-lockup&caller=MDM&platform=enterprisestore&cc=us&l=en"; + private static final Log log = LogFactory.getLog(VppApplicationManagerImpl.class); + private ApplicationDAO applicationDAO; private SPApplicationDAO spApplicationDAO; private VisibilityDAO visibilityDAO; @@ -154,6 +164,56 @@ public class VppApplicationManagerImpl implements VPPApplicationManager { Gson gson = new Gson(); VppItuneUserResponseWrapper vppUserResponseWrapper = gson.fromJson (proxyResponse.getData(), VppItuneUserResponseWrapper.class); + // TODO: to implement later + } + } catch (IOException e) { + String msg = "Error while syncing VPP users with backend"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + + } + + @Override + public void syncAssets(int nextPageIndex) throws ApplicationManagementException { + ProxyResponse proxyResponse = null; + try { + String url = ASSETS; + if (nextPageIndex > 0) { // Not the first page + url += "?pageIndex=" + nextPageIndex; + } + proxyResponse = callVPPBackend(url, null, TOKEN, Constants.VPP.GET); + if ((proxyResponse.getCode() == HttpStatus.SC_OK || proxyResponse.getCode() == + HttpStatus.SC_CREATED) && proxyResponse.getData().contains(Constants.VPP.TOTAL_PAGES)) { + Gson gson = new Gson(); + VppItuneAssetResponseWrapper vppItuneAssetResponse = gson.fromJson + (proxyResponse.getData(), VppItuneAssetResponseWrapper.class); + if (vppItuneAssetResponse.getSize() > 0) { + for (VppAssetDTO vppAssetDTO : vppItuneAssetResponse.getAssets()) { + vppAssetDTO.setTenantId(PrivilegedCarbonContext + .getThreadLocalCarbonContext().getTenantId()); + vppAssetDTO.setCreatedTime(String.valueOf(System.currentTimeMillis())); + vppAssetDTO.setLastUpdatedTime(String.valueOf(System.currentTimeMillis())); + } + + for (VppAssetDTO vppAssetDTO : vppItuneAssetResponse.getAssets()) { + ItuneAppDTO ituneAppDTO = lookupAsset(vppAssetDTO.getAdamId()); + ApplicationManagementUtil.persistApp(ituneAppDTO); + } + + // TODO: Store/update vppItuneAssetResponse.getAssets() in the DB + + // TODO: END of DAO access + + } + + + if (vppItuneAssetResponse.getCurrentPageIndex() == (vppItuneAssetResponse + .getTotalPages() - 1)) { + return; + } else { + syncAssets(vppItuneAssetResponse.getNextPageIndex()); + } } } catch (IOException e) { String msg = "Error while syncing VPP users with backend"; @@ -161,6 +221,73 @@ public class VppApplicationManagerImpl implements VPPApplicationManager { throw new ApplicationManagementException(msg, e); } + + } + + private ItuneAppDTO lookupAsset(String packageName) throws ApplicationManagementException { + String lookupURL = LOOKUP_API + packageName + LOOKUP_API_PREFIX; + try { + ProxyResponse proxyResponse = callVPPBackend(lookupURL, null, TOKEN, Constants.VPP.GET); + if ((proxyResponse.getCode() == HttpStatus.SC_OK || proxyResponse.getCode() == + HttpStatus.SC_CREATED) && proxyResponse.getData().contains(Constants.VPP.GET_APP_DATA_RESPONSE_START)) { + String responseData = proxyResponse.getData(); + JsonObject responseJson = new JsonParser().parse(responseData) + .getAsJsonObject(); + + JsonObject results = responseJson.getAsJsonObject(Constants.ApplicationProperties.RESULTS); + JsonObject result = results.getAsJsonObject(packageName); + + String iconUrl = result.getAsJsonObject(Constants.ApplicationProperties.ARTWORK) + .get(Constants.ApplicationProperties.URL).getAsString(); + int lastSlashIndex = iconUrl.lastIndexOf("/"); + if (lastSlashIndex != -1) { + iconUrl = iconUrl.substring(0, lastSlashIndex + 1) + Constants.VPP.REMOTE_FILE_NAME; + } + + String descriptionStandard = result.getAsJsonObject(Constants.ApplicationProperties.DESCRIPTION) + .get(Constants.ApplicationProperties.STANDARD).getAsString(); + if (descriptionStandard != null && !descriptionStandard.isEmpty()) { + descriptionStandard = descriptionStandard.substring(0, 199); + } + String name = result.get(Constants.ApplicationProperties.NAME).getAsString(); + double price = result.getAsJsonArray(Constants.ApplicationProperties.OFFERS).get(0) + .getAsJsonObject().get(Constants.ApplicationProperties.PRICE).getAsDouble(); + String version = result.getAsJsonArray(Constants.ApplicationProperties.OFFERS) + .get(0).getAsJsonObject().get(Constants.ApplicationProperties.VERSION) + .getAsJsonObject().get(Constants.ApplicationProperties.DISPLAY).getAsString(); + + String[] genreNames = new Gson().fromJson(result.getAsJsonArray(Constants.ApplicationProperties.GENRE_NAMES), + String[].class); + + ItuneAppDTO ituneAppDTO = new ItuneAppDTO(); + ituneAppDTO.setPackageName(packageName); + ituneAppDTO.setVersion(version); + ituneAppDTO.setDescription(descriptionStandard); + ituneAppDTO.setTitle(name); + + if (Constants.ApplicationProperties.PRICE_ZERO.equalsIgnoreCase(String.valueOf(price))) { + ituneAppDTO.setPaymentMethod(Constants.ApplicationProperties.FREE_SUB_METHOD); + } else { + ituneAppDTO.setPaymentMethod(Constants.ApplicationProperties.PAID_SUB_METHOD); + } + ituneAppDTO.setIconURL(iconUrl); + ituneAppDTO.setCategory(genreNames[0]); + + return ituneAppDTO; + } + } catch (IOException e) { + String msg = "Error while looking up the app details"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + return null; + } + + + public VppAssetDTO getAssetByAppId(String appId) throws ApplicationManagementException { + // App ID is the app id of the App management database + VppAssetDTO assetDTO = null; // TODO: load from the DB + return assetDTO; } @Override diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/ApplicationManagementUtil.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/ApplicationManagementUtil.java index 55bf0b1a72f..8ae9a580f49 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/ApplicationManagementUtil.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/ApplicationManagementUtil.java @@ -18,15 +18,21 @@ package io.entgra.device.mgt.core.application.mgt.core.util; import io.entgra.device.mgt.core.application.mgt.common.ApplicationArtifact; -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.device.mgt.common.Base64File; import io.entgra.device.mgt.core.application.mgt.common.FileDataHolder; +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.ItuneAppDTO; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; +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.ReviewManager; import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager; +import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager; +import io.entgra.device.mgt.core.application.mgt.common.wrapper.ApplicationUpdateWrapper; import io.entgra.device.mgt.core.application.mgt.common.wrapper.ApplicationWrapper; import io.entgra.device.mgt.core.application.mgt.common.wrapper.CustomAppReleaseWrapper; import io.entgra.device.mgt.core.application.mgt.common.wrapper.CustomAppWrapper; @@ -35,18 +41,31 @@ import io.entgra.device.mgt.core.application.mgt.common.wrapper.PublicAppRelease 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 org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import io.entgra.device.mgt.core.application.mgt.common.exception.InvalidConfigurationException; -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.ReviewManager; -import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager; +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.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.core.common.util.FileUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -247,4 +266,258 @@ public class ApplicationManagementUtil { throw new InvalidConfigurationException(msg, e); } } + + public static void persistApp(ItuneAppDTO product) throws ApplicationManagementException { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + List categories = applicationManager.getRegisteredCategories(); + if (product != null && product.getVersion() != null) { + // Generate artifacts + ApplicationArtifact applicationArtifact = generateArtifacts(product); + + List packageNamesOfApps = new ArrayList<>(); + packageNamesOfApps.add(product.getPackageName()); + + List existingApps = applicationManager.getApplications(packageNamesOfApps); + + if (existingApps != null && existingApps.size() > 0) { + Application app = existingApps.get(0); + if (product.getPackageName().equals(app.getPackageName())) { + 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); + } else { + publicAppReleaseWrapper.setPrice(1.0); + } + + publicAppReleaseWrapper.setDescription(product.getDescription()); + publicAppReleaseWrapper.setReleaseType("ga"); + publicAppReleaseWrapper.setVersion(product.getVersion()); + publicAppReleaseWrapper.setSupportedOsVersions("4.0-12.3"); + applicationManager.updatePubAppRelease(app.getApplicationReleases().get(0).getUuid(), + publicAppReleaseWrapper, applicationArtifact); + 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); + } + } + } + } + + private static PublicAppWrapper generatePubAppWrapper(ItuneAppDTO product, List categories) { + PublicAppWrapper publicAppWrapper = new PublicAppWrapper(); + publicAppWrapper.setName(product.getTitle()); + publicAppWrapper.setDescription(product.getDescription()); + publicAppWrapper.setCategories( + Collections.singletonList(Constants.ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY));//Default category + for (Category category : categories) { + if (product.getCategory() == null) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(Constants.ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY); + publicAppWrapper.setCategories(pubAppCategories); + break; + } else if (product.getCategory().equalsIgnoreCase(category.getCategoryName())) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(category.getCategoryName()); + pubAppCategories.add(Constants.ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY); + publicAppWrapper.setCategories(pubAppCategories); + break; + } + } + if (product.getPaymentMethod().equalsIgnoreCase(Constants.ApplicationProperties.FREE_SUB_METHOD)) { + publicAppWrapper.setSubMethod(Constants.ApplicationProperties.FREE_SUB_METHOD); + } else { + publicAppWrapper.setSubMethod(Constants.ApplicationProperties.PAID_SUB_METHOD); + } + // TODO: purchase an app from app store and see how to capture the real value for price + // field. + publicAppWrapper.setPaymentCurrency("$"); + publicAppWrapper.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); + return publicAppWrapper; + } + + private static ApplicationUpdateWrapper generatePubAppUpdateWrapper(ItuneAppDTO product, List categories) { + ApplicationUpdateWrapper applicationUpdateWrapper = new ApplicationUpdateWrapper(); + applicationUpdateWrapper.setName(product.getTitle()); + applicationUpdateWrapper.setDescription(product.getDescription()); + applicationUpdateWrapper.setCategories( + Collections.singletonList(Constants + .ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY));//Default + // add the default APPLE_STORE_SYNCED_APP_CATEGORY + for (Category category : categories) { + if (product.getCategory() == null) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(Constants.ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY); + applicationUpdateWrapper.setCategories(pubAppCategories); + break; + } else if (product.getCategory().equalsIgnoreCase(category.getCategoryName())) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(category.getCategoryName()); + pubAppCategories.add(Constants.ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY); + applicationUpdateWrapper.setCategories(pubAppCategories); + break; + } + } + if (product.getPaymentMethod().equalsIgnoreCase(Constants.ApplicationProperties.FREE_SUB_METHOD)) { + applicationUpdateWrapper.setSubMethod(Constants.ApplicationProperties.FREE_SUB_METHOD); + } else { + applicationUpdateWrapper.setSubMethod(Constants.ApplicationProperties.PAID_SUB_METHOD); + } + // TODO: purchase an app from Playstore and see how to capture the real value for price field. + applicationUpdateWrapper.setPaymentCurrency("$"); + return applicationUpdateWrapper; + } + + private static ApplicationArtifact generateArtifacts(ItuneAppDTO product) throws ApplicationManagementException { + ApplicationArtifact applicationArtifact = new ApplicationArtifact(); + String prefix = product.getPackageName(); + try { + String iconName = prefix + "_icon"; + applicationArtifact.setIconName(iconName); + InputStream iconInputStream = getInputStream(iconName, product.getIconURL()); + applicationArtifact.setIconStream(iconInputStream); + Map screenshotMap = new HashMap<>(); + // TODO: look for a way to get screenshots + + for (int a = 0; a < 3; a++) { + String screenshotName = product.getPackageName() + a; + InputStream screenshotInputStream = getInputStream(screenshotName, product.getIconURL()); + screenshotMap.put(screenshotName, screenshotInputStream); + } + + applicationArtifact.setScreenshots(screenshotMap); + return applicationArtifact; + } catch (ApplicationManagementException e) { + String msg = "Error occurred while generating Application artifact"; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + } + + private static InputStream getInputStream(String filename, String url) throws ApplicationManagementException { + URL website; + try { + website = new URL(url); + } catch (MalformedURLException e) { + String msg = "Error occurred while converting the url " + url; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + ReadableByteChannel rbc = null; + FileOutputStream fos = null; + try { + rbc = Channels.newChannel(website.openStream()); + fos = new FileOutputStream(System.getProperty("java.io.tmpdir") + + File.separator + filename); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + } catch (IOException e) { + String msg = "Error occurred while opening stream for url " + url; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } finally { + try { + fos.close(); + rbc.close(); + } catch (IOException e) { + } + } + + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + filename); + InputStream targetStream; + try { + targetStream = new FileInputStream(file); + } catch (FileNotFoundException e) { + String msg = "Error occurred while reading the tmp file " + System.getProperty("java.io.tmpdir") + + File.separator + filename; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + file.deleteOnExit(); + return targetStream; + } + + private static void updateImages(PublicAppReleaseWrapper appReleaseWrapper, String iconName, + InputStream iconStream, Map + screenshotsMaps) throws IOException { + List screenshots = new ArrayList<>(); + Base64File iconFile = new Base64File(iconName, + convertStreamToBase64(iconStream)); + appReleaseWrapper.setIcon(iconFile); + if (screenshotsMaps.size() > 0) { + for (Map.Entry screenshotEntry : screenshotsMaps.entrySet()) { + Base64File screenshot = new Base64File(screenshotEntry.getKey(), + convertStreamToBase64(screenshotEntry.getValue())); + screenshots.add(screenshot); + } + appReleaseWrapper.setScreenshots(screenshots); + } + } + + private static String convertStreamToBase64(InputStream inputStream) throws IOException { + final int bufLen = 4 * 0x400; // 4KB + byte[] buf = new byte[bufLen]; + int readLen; + + try { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + while ((readLen = inputStream.read(buf, 0, bufLen)) != -1) + outputStream.write(buf, 0, readLen); + + return Base64.getEncoder().encodeToString(outputStream.toByteArray()); + } + } catch (IOException e) { + String msg = "Error while converting image to base64"; + log.error(msg); + throw e; + } finally { + try { + inputStream.close(); + } catch (IOException e) { + } + } + } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java index ce61c1a81b3..7b804e7fa88 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java @@ -109,10 +109,11 @@ public class Constants { public static final String POST = "POST"; public static final String PUT = "PUT"; public static final String DELETE = "DELETE"; - public static final String CLIENT_USER_ID = "clientUserId"; public static final String EVENT_ID = "eventId"; public static final String CLIENT_USER_ID_PARAM = "?clientUserId="; public static final String TOTAL_PAGES = "totalPages"; + public static final String GET_APP_DATA_RESPONSE_START = "results"; + public static final String REMOTE_FILE_NAME = "512x512w.png"; private VPP() { } @@ -182,4 +183,29 @@ public class Constants { public static final String AUTHORIZATION = "Authorization"; public static final String AUTHORIZATION_HEADER_VALUE = "Bearer "; } + + public final class ApplicationProperties { + private ApplicationProperties() { + throw new AssertionError(); + } + + public static final String NAME = "name"; + public static final String VERSION = "version"; + public static final String FREE_SUB_METHOD = "FREE"; + public static final String PAID_SUB_METHOD = "PAID"; + public static final String TYPE = "type";; + public static final String PACKAGE_NAME = "packageName"; + public static final String APPLE_STORE_SYNCED_APP_CATEGORY = "APPLE_STORE_SYNCED_APP"; + + public static final String RESULTS = "results"; + public static final String ARTWORK = "artwork"; + public static final String URL = "url"; + public static final String DESCRIPTION = "description"; + public static final String STANDARD = "standard"; + public static final String OFFERS = "offers"; + public static final String PRICE = "price"; + public static final String DISPLAY = "display"; + public static final String GENRE_NAMES = "genreNames"; + public static final String PRICE_ZERO = "0.0"; + } }