diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidConstants.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidConstants.java index fd29cb29eb..e7d618b70f 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidConstants.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidConstants.java @@ -70,6 +70,8 @@ public final class AndroidConstants { public static final String USER_CLAIM_FIRST_NAME_PLACEHOLDER = "$firstName"; public static final String USER_CLAIM_LAST_NAME_PLACEHOLDER = "$lastName"; + public static final String GOOGLE_PLAY_SYNCED_APP_CATEGORY = "GooglePlaySyncedApp"; + public final class DeviceProperties { private DeviceProperties() { throw new AssertionError(); @@ -186,6 +188,8 @@ public final class AndroidConstants { public static final String VERSION = "version"; public static final String ICON = "icon"; public static final String IS_ACTIVE = "isActive"; + public static final String FREE_SUB_METHOD = "FREE"; + public static final String PAID_SUB_METHOD = "PAID"; } public final class ApplicationInstall { diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidEnterpriseUtils.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidEnterpriseUtils.java index 9bd2a953f8..6bd4e0be89 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidEnterpriseUtils.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidEnterpriseUtils.java @@ -44,6 +44,7 @@ import org.wso2.carbon.device.application.mgt.common.response.Application; import org.wso2.carbon.device.application.mgt.common.response.Category; import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; +import org.wso2.carbon.device.application.mgt.common.wrapper.ApplicationUpdateWrapper; import org.wso2.carbon.device.application.mgt.common.wrapper.PublicAppReleaseWrapper; import org.wso2.carbon.device.application.mgt.common.wrapper.PublicAppWrapper; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; @@ -76,9 +77,11 @@ import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class AndroidEnterpriseUtils { @@ -277,85 +280,70 @@ public class AndroidEnterpriseUtils { ApplicationManager applicationManager = getAppManagerServer(); List categories = applicationManager.getRegisteredCategories(); if (productListResponse != null && productListResponse.getProduct() != null - && productListResponse.getProduct().size() > 0) { + && !productListResponse.getProduct().isEmpty()) { + + List packageNamesOfApps = productListResponse.getProduct().stream() + .map(product -> (product.getProductId().replaceFirst("app:", ""))).collect(Collectors.toList()); + + List existingApps = applicationManager.getApplications(packageNamesOfApps); + List products = productListResponse.getProduct(); + + for (Application app : existingApps){ + for (Product product : products){ + if (product.getProductId().replaceFirst("app:", "").equals(app.getPackageName())){ + ApplicationUpdateWrapper applicationUpdateWrapper = generatePubAppUpdateWrapper(product, categories); + applicationManager.updateApplication(app.getId(), applicationUpdateWrapper); + + PublicAppReleaseWrapper publicAppReleaseWrapper = new PublicAppReleaseWrapper(); + if (app.getSubMethod() + .equalsIgnoreCase(AndroidConstants.ApplicationProperties.FREE_SUB_METHOD)) { + publicAppReleaseWrapper.setPrice(0.0); + } else { + publicAppReleaseWrapper.setPrice(1.0); + } + + publicAppReleaseWrapper.setDescription(product.getRecentChanges()); + publicAppReleaseWrapper.setReleaseType("ga"); + publicAppReleaseWrapper.setVersion(getAppString(product.getAppVersion())); + publicAppReleaseWrapper + .setSupportedOsVersions(String.valueOf(product.getMinAndroidSdkVersion()) + "-ALL"); - for (Product product : productListResponse.getProduct()) { + ApplicationArtifact applicationArtifact = generateArtifacts(product); + applicationManager.updatePubAppRelease(app.getApplicationReleases().get(0).getUuid(), + publicAppReleaseWrapper, applicationArtifact); + products.remove(product); + break; + } + } + } + for (Product product : products) { if (product.getAppVersion() == null) { // This is to handled removed apps from playstore continue; } // Generate App wrapper - PublicAppWrapper publicAppWrapper = new PublicAppWrapper(); + PublicAppWrapper publicAppWrapper = generatePubAppWrapper(product, categories); PublicAppReleaseWrapper appReleaseWrapper = new PublicAppReleaseWrapper(); - publicAppWrapper.setName(product.getTitle()); - publicAppWrapper.setDescription(product.getDescription()); - publicAppWrapper.setCategories(Arrays.asList(new String[]{"GooglePlaySyncedApp"}));//Default category - for (Category category : categories) { - if (product.getCategory() == null) { - publicAppWrapper.setCategories(Arrays.asList(new String[]{"GooglePlaySyncedApp"})); - break; - } else if (product.getCategory().equalsIgnoreCase(category.getCategoryName())) { - publicAppWrapper.setCategories(Arrays.asList(new String[]{category.getCategoryName(), "GooglePlaySyncedApp"})); - break; - } - } - if (product.getProductPricing().equalsIgnoreCase("free")) { - publicAppWrapper.setSubMethod("FREE"); + + if (publicAppWrapper.getSubMethod() + .equalsIgnoreCase(AndroidConstants.ApplicationProperties.FREE_SUB_METHOD)) { + appReleaseWrapper.setPrice(0.0); } else { - publicAppWrapper.setSubMethod("PAID"); + appReleaseWrapper.setPrice(1.0); } - // TODO: purchase an app from Playstore and see how to capture the real value for price field. - publicAppWrapper.setPaymentCurrency("$"); - appReleaseWrapper.setPrice(1.0); - publicAppWrapper.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID); appReleaseWrapper.setDescription(product.getRecentChanges()); appReleaseWrapper.setReleaseType("ga"); appReleaseWrapper.setVersion(getAppString(product.getAppVersion())); appReleaseWrapper.setPackageName(product.getProductId().replaceFirst("app:", "")); appReleaseWrapper.setSupportedOsVersions(String.valueOf(product.getMinAndroidSdkVersion()) + "-ALL"); - publicAppWrapper.setPublicAppReleaseWrappers(Arrays.asList(new PublicAppReleaseWrapper[]{appReleaseWrapper})); + publicAppWrapper.setPublicAppReleaseWrappers( + Arrays.asList(new PublicAppReleaseWrapper[] { appReleaseWrapper })); // Generate artifacts - ApplicationArtifact applicationArtifact = new ApplicationArtifact(); - - String iconName = product.getIconUrl().split(".com/")[1]; - applicationArtifact.setIconName(iconName); - - - InputStream iconInputStream = getInputStream(iconName, product.getIconUrl()); - applicationArtifact.setIconStream(iconInputStream); - Map screenshotMap = new HashMap<>(); - - int numberOfScreenShots = 3;// This is to handle some apps in playstore without 3 screenshots. - if (product.getScreenshotUrls() != null) { - if (product.getScreenshotUrls().size() < 3) { - numberOfScreenShots = product.getScreenshotUrls().size(); - } - - for (int y = 1; y < 4; y++) { - int screenshotNumber = y - 1; - if (y > numberOfScreenShots) { - screenshotNumber = 0; - } - String screenshot = product.getScreenshotUrls().get(screenshotNumber); - String screenshotName = screenshot.split(".com/")[1]; - InputStream screenshotInputStream = getInputStream(screenshotName, screenshot); - screenshotMap.put(screenshotName, screenshotInputStream); - } - } else { // Private apps doesn't seem to send screenshots. Handling it. - for (int a = 0; a < 3; a++) { - String screenshot = product.getIconUrl(); - String screenshotName = screenshot.split(".com/")[1]; - InputStream screenshotInputStream = getInputStream(screenshotName, screenshot); - screenshotMap.put(screenshotName, screenshotInputStream); - } - } - - applicationArtifact.setScreenshots(screenshotMap); - + ApplicationArtifact applicationArtifact = generateArtifacts(product); Application application = applicationManager.createPublicApp(publicAppWrapper, applicationArtifact); if (application != null && (application.getApplicationReleases().get(0).getCurrentStatus() == null @@ -373,6 +361,129 @@ public class AndroidEnterpriseUtils { } } + /** + * To generate {@link ApplicationUpdateWrapper} + * + * @param product {@link Product} + * @param categories List of categories registered with app manager + * @return {@link ApplicationUpdateWrapper} + */ + private static ApplicationUpdateWrapper generatePubAppUpdateWrapper(Product product, List categories) { + ApplicationUpdateWrapper applicationUpdateWrapper = new ApplicationUpdateWrapper(); + applicationUpdateWrapper.setName(product.getTitle()); + applicationUpdateWrapper.setDescription(product.getDescription()); + applicationUpdateWrapper.setCategories( + Collections.singletonList(AndroidConstants.GOOGLE_PLAY_SYNCED_APP_CATEGORY));//Default category + for (Category category : categories) { + if (product.getCategory() == null) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(AndroidConstants.GOOGLE_PLAY_SYNCED_APP_CATEGORY); + applicationUpdateWrapper.setCategories(pubAppCategories); + break; + } else if (product.getCategory().equalsIgnoreCase(category.getCategoryName())) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(category.getCategoryName()); + pubAppCategories.add(AndroidConstants.GOOGLE_PLAY_SYNCED_APP_CATEGORY); + applicationUpdateWrapper.setCategories(pubAppCategories); + break; + } + } + if (product.getProductPricing().equalsIgnoreCase(AndroidConstants.ApplicationProperties.FREE_SUB_METHOD)) { + applicationUpdateWrapper.setSubMethod(AndroidConstants.ApplicationProperties.FREE_SUB_METHOD); + } else { + applicationUpdateWrapper.setSubMethod(AndroidConstants.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; + } + + /** + * To generate {@link PublicAppWrapper} + * + * @param product {@link Product} + * @param categories List of categories registered with app manager + * @return {@link PublicAppWrapper} + */ + private static PublicAppWrapper generatePubAppWrapper(Product product, List categories) { + PublicAppWrapper publicAppWrapper = new PublicAppWrapper(); + publicAppWrapper.setName(product.getTitle()); + publicAppWrapper.setDescription(product.getDescription()); + publicAppWrapper.setCategories( + Collections.singletonList(AndroidConstants.GOOGLE_PLAY_SYNCED_APP_CATEGORY));//Default category + for (Category category : categories) { + if (product.getCategory() == null) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(AndroidConstants.GOOGLE_PLAY_SYNCED_APP_CATEGORY); + publicAppWrapper.setCategories(pubAppCategories); + break; + } else if (product.getCategory().equalsIgnoreCase(category.getCategoryName())) { + List pubAppCategories = new ArrayList<>(); + pubAppCategories.add(category.getCategoryName()); + pubAppCategories.add(AndroidConstants.GOOGLE_PLAY_SYNCED_APP_CATEGORY); + publicAppWrapper.setCategories(pubAppCategories); + break; + } + } + if (product.getProductPricing().equalsIgnoreCase(AndroidConstants.ApplicationProperties.FREE_SUB_METHOD)) { + publicAppWrapper.setSubMethod(AndroidConstants.ApplicationProperties.FREE_SUB_METHOD); + } else { + publicAppWrapper.setSubMethod(AndroidConstants.ApplicationProperties.PAID_SUB_METHOD); + } + // TODO: purchase an app from Playstore and see how to capture the real value for price field. + publicAppWrapper.setPaymentCurrency("$"); + publicAppWrapper.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID); + return publicAppWrapper; + } + + /** + * To generate {@link ApplicationArtifact} + * + * @param product {@link Product} + * @return {@link ApplicationArtifact} + * @throws ApplicationManagementException if I/O exception occurred while generating application artifact. + */ + private static ApplicationArtifact generateArtifacts(Product product) throws ApplicationManagementException { + ApplicationArtifact applicationArtifact = new ApplicationArtifact(); + try { + String iconName = product.getIconUrl().split(".com/")[1]; + applicationArtifact.setIconName(iconName); + InputStream iconInputStream = getInputStream(iconName, product.getIconUrl()); + applicationArtifact.setIconStream(iconInputStream); + Map screenshotMap = new HashMap<>(); + + int numberOfScreenShots = 3;// This is to handle some apps in playstore without 3 screenshots. + if (product.getScreenshotUrls() != null) { + if (product.getScreenshotUrls().size() < 3) { + numberOfScreenShots = product.getScreenshotUrls().size(); + } + for (int y = 1; y < 4; y++) { + int screenshotNumber = y - 1; + if (y > numberOfScreenShots) { + screenshotNumber = 0; + } + String screenshot = product.getScreenshotUrls().get(screenshotNumber); + String screenshotName = screenshot.split(".com/")[1]; + InputStream screenshotInputStream = getInputStream(screenshotName, screenshot); + screenshotMap.put(screenshotName, screenshotInputStream); + } + } else { // Private apps doesn't seem to send screenshots. Handling it. + for (int a = 0; a < 3; a++) { + String screenshot = product.getIconUrl(); + String screenshotName = screenshot.split(".com/")[1]; + InputStream screenshotInputStream = getInputStream(screenshotName, screenshot); + 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 { diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android/src/main/java/org/wso2/carbon/device/mgt/mobile/android/impl/AndroidDeviceManagementService.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android/src/main/java/org/wso2/carbon/device/mgt/mobile/android/impl/AndroidDeviceManagementService.java deleted file mode 100644 index bccceedbb5..0000000000 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android/src/main/java/org/wso2/carbon/device/mgt/mobile/android/impl/AndroidDeviceManagementService.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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. - * - * Copyright (c) 2019, 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 org.wso2.carbon.device.mgt.mobile.android.impl; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.device.mgt.common.DeviceManager; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.ProvisioningConfig; -import org.wso2.carbon.device.mgt.common.InitialOperationConfig; -import org.wso2.carbon.device.mgt.common.DeviceStatusTaskPluginConfig; -import org.wso2.carbon.device.mgt.common.StartupOperationConfig; -import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; -import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; -import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; -import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; -import org.wso2.carbon.device.mgt.common.general.GeneralConfig; -import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; -import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; -import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; -import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; -import org.wso2.carbon.device.mgt.common.type.mgt.DeviceTypePlatformDetails; -import org.wso2.carbon.device.mgt.mobile.android.impl.util.AndroidPluginConstants; -import org.wso2.carbon.device.mgt.mobile.android.internal.AndroidDeviceManagementDataHolder; - -import java.util.HashMap; -import java.util.List; - -/** - * This represents the Android implementation of DeviceManagerService. - */ -public class AndroidDeviceManagementService implements DeviceManagementService { - - private static final Log log = LogFactory.getLog(AndroidDeviceManagementService.class); - private DeviceManager deviceManager; - public static final String DEVICE_TYPE_ANDROID = "android"; - private static final String SUPER_TENANT_DOMAIN = "carbon.super"; - private static final String NOTIFIER_PROPERTY = "notifierType"; - private static final String FCM_API_KEY = "fcmAPIKey"; - private static final String FCM_SENDER_ID = "fcmSenderId"; - private PolicyMonitoringManager policyMonitoringManager; - - @Override - public String getType() { - return AndroidDeviceManagementService.DEVICE_TYPE_ANDROID; - } - - @Override - public OperationMonitoringTaskConfig getOperationMonitoringConfig() { - return null; - } - - @Override - public void init() throws DeviceManagementException { - - } - - @Override - public DeviceManager getDeviceManager() { - return deviceManager; - } - - @Override - public ApplicationManager getApplicationManager() { - return null; - } - - @Override - public ProvisioningConfig getProvisioningConfig() { - return new ProvisioningConfig(SUPER_TENANT_DOMAIN, true); - } - - @Override - public PushNotificationConfig getPushNotificationConfig() { - return null; - } - - @Override - public PolicyMonitoringManager getPolicyMonitoringManager() { - return policyMonitoringManager; - } - - @Override - public InitialOperationConfig getInitialOperationConfig() { - return null; - } - - @Override - public StartupOperationConfig getStartupOperationConfig() { - return null; - } - - @Override - public PullNotificationSubscriber getPullNotificationSubscriber() { - return null; - } - - @Override - public DeviceStatusTaskPluginConfig getDeviceStatusTaskPluginConfig() { - return null; - } - - @Override - public GeneralConfig getGeneralConfig() { - return null; - } - - @Override - public DeviceTypePlatformDetails getDeviceTypePlatformDetails() { return null; } - - private String getConfigProperty(List configs, String propertyName) { - for (ConfigurationEntry entry : configs) { - if (propertyName.equals(entry.getName())) { - return entry.getValue().toString(); - } - } - return null; - } -}